diff --git a/README.md b/README.md deleted file mode 100644 index 3cc53ad..0000000 --- a/README.md +++ /dev/null @@ -1,43 +0,0 @@ -[![MELPA](http://melpa.org/packages/focus-badge.svg)](http://melpa.org/#/focus) -# Focus - -Focus provides `focus-mode` that dims the text of surrounding sections, similar to [iA Writer's](https://ia.net/writer) Focus Mode. - -## Installation - -You can install Focus using elpa. It's available on [melpa](http://melpa.milkbox.net/): - - M-x package-install focus - -The package has only been tried on Emacs 24.4 and 24.5, but should work on Emacs 24 or higher. - -## Usage - -Enable the `focus-mode` with M-x focus-mode . - -Also, `focus-read-only-mode` is provided, which is a mode optimized for continuous reading. It inhibits change in the buffer, hides the cursor and provides bindings for moving between *things* (defined in [Thing At Point](http://emacswiki.org/emacs/ThingAtPoint)). One can toggle `focus-read-only-mode` with M-x focus-read-only-mode or C-c C-q if `focus-mode` is enabled. - -Some bindings for simple navigation and exiting `focus-read-only-mode` are provided. - -Keybinding | Description --------------------|---------------------------- - n | Jump to next *thing* - SPC | Jump to next *thing* - p | Jump to previous *thing* - S-SPC | Jump to previous *thing* - i | Exit `focus-read-only-mode` - q | Exit `focus-read-only-mode` - -## Configuring - -The amount of dimness can be customized by setting the `focus-dimness` variable, where a positive integer indicates a more dim color (i.e. more blended with the background color of your theme), and a negative integer indicates a less dim color. - -Focus uses the [Thing At Point](http://emacswiki.org/emacs/ThingAtPoint) library to choose what section should be in focus. By default, modes derived from `prog-mode` uses `defun`, and modes derived from `text-mode` uses `sentence`. This a customizable by setting the `focus-mode-to-thing` variable, which is a list containing pairs on the form `(mode . thing)`. - -### Example - -This is what it looks like: - -Light Theme (leuven) | Dark Theme (monokai) -:---------------------------------------:|:---------------------------------------: - | diff --git a/README.org b/README.org new file mode 100644 index 0000000..5d39115 --- /dev/null +++ b/README.org @@ -0,0 +1,87 @@ +[[https://melpa.org/#/focus][file:https://melpa.org/packages/focus-badge.svg]] +[[https://stable.melpa.org/#/focus][file:https://stable.melpa.org/packages/focus-badge.svg]] + +* Focus + + [[./focus-demo.gif]] + + This is Focus, a package that dims surrounding text. It works with any theme + and can be configured to focus in on different regions like sentences, + paragraphs or code-blocks. + +* Installation + + It's available on [[https://melpa.org/#/focus][MELPA]] and [[https://stable.melpa.org/#/focus][MELPA Stable]]: + + #+BEGIN_EXAMPLE + M-x package-install focus + #+END_EXAMPLE + +* Usage + + Enable ~focus-mode~ with ~M-x focus-mode~. + + A few interactive functions are provided: + + | Function | Description | + |--------------------+--------------------------------------------------------------------------| + | focus-change-thing | Adjust the narrowness of the focused section for the current buffer | + | focus-pin | Pin the focused section to its current location or the region, if active | + | focus-unpin | Unpin the focused section | + | focus-next-thing | Move the point to the middle of the Nth next thing | + | focus-prev-thing | Move the point to the middle of the Nth previous thing | + + Focus relies on [[https://www.emacswiki.org/emacs/ThingAtPoint][Thing At Point]], which can retrieve a /thing/ surrounding the + point. These /things/ may be a symbol, list, S-expression (sexp), function + definition (defun), sentence, line, page and others. Calling ~M-x + focus-change-thing~ allows you to interactively change the kind of region + which should be in focus. + +** Focus read-only mode + + Enable ~focus-read-only-mode~ with ~M-x focus-read-only-mode~, which is + optimized for continuous reading. It inhibits changes in a buffer, hides the + cursor and provides bindings for moving between /things/. + + Some bindings for simple navigation and exiting `focus-read-only-mode` are + provided. + + | Keybinding | Description | + |------------+-----------------------------| + | ~n~ | Jump to next /thing/ | + | ~SPC~ | Jump to next /thing/ | + | ~p~ | Jump to previous /thing/ | + | ~S-SPC~ | Jump to previous /thing/ | + | ~i~ | Exit ~focus-read-only-mode~ | + | ~q~ | Exit ~focus-read-only-mode~ | + +* Customization + + The choice of what /thing/ is suitable for a mode may be configured by + setting the variable ~focus-mode-to-thing~. The default is + + #+BEGIN_EXAMPLE + '((prog-mode . defun) (text-mode . sentence)) + #+END_EXAMPLE + + For modes inheriting ~prog-mode~ (which are most programming modes), the + default is the function-body, and for modes inheriting ~text-mode~, the + default is a sentence. + + For instance, adding the following to your ~.emacs~-file: + + #+BEGIN_SRC emacs-lisp + (add-to-list 'focus-mode-to-thing '(python-mode . paragraph)) + #+END_SRC + + changes ~python-mode~ to focus in on code-blocks with no blank lines rather + than the entire function. + + According to [[https://www.reddit.com/r/emacs/comments/b1vrar/lsp_support_for_focusel_using_lspmode/][this reddit post]], Focus plays nice with ~lsp-mode~. + +** Faces + + Focus offers two faces, one for the focused- and unfocused area. By default, + the ~focus-focused~ is the empty face, meaning there is no change, and + ~focus-unfocused~ inherits the comment face (which is usually subtle). The + faces can easily be customized via ~M-x list-faces-display~. diff --git a/demo-dark.gif b/demo-dark.gif deleted file mode 100644 index 94c1c28..0000000 Binary files a/demo-dark.gif and /dev/null differ diff --git a/demo-light.gif b/demo-light.gif deleted file mode 100644 index 59a63ab..0000000 Binary files a/demo-light.gif and /dev/null differ diff --git a/focus-demo.gif b/focus-demo.gif new file mode 100644 index 0000000..4a10b92 Binary files /dev/null and b/focus-demo.gif differ diff --git a/focus.el b/focus.el index 58b6a9e..82343d8 100644 --- a/focus.el +++ b/focus.el @@ -38,17 +38,6 @@ :group 'font-lock :prefix "focus-") -(defcustom focus-dimness 0 - "Amount of dimness in out of focus sections is determined by this integer. - -A positive value increases the dimness of the sections. -A negative value decreases the dimness. - -The default is 0 which means a 50/50 mixture of the background -and foreground color." - :type '(integer) - :group 'focus) - (defcustom focus-mode-to-thing '((prog-mode . defun) (text-mode . sentence)) "An associated list between mode and thing. @@ -70,12 +59,18 @@ Things that are defined include `symbol', `list', `sexp', :type '(float) :group 'focus) +(defface focus-unfocused + '((t :inherit font-lock-comment-face)) + "The face that overlays the unfocused area." + :group 'focus) + +(defface focus-focused nil + "The face that overlays the focused area." + :group 'focus) + (defvar focus-cursor-type cursor-type "Used to restore the users `cursor-type'") -(defvar focus-dim-color nil - "Overrides the color used for dimmed text.") - (defvar-local focus-current-thing nil "Overrides the choice of thing dictated by `focus-mode-to-thing' if set.") @@ -85,6 +80,9 @@ Things that are defined include `symbol', `list', `sexp', (defvar-local focus-pre-overlay nil "The overlay that dims the text prior to the current-point.") +(defvar-local focus-mid-overlay nil + "The overlay that surrounds the text of the current-point.") + (defvar-local focus-post-overlay nil "The overlay that dims the text past the current-point.") @@ -105,28 +103,6 @@ The timer calls `focus-read-only-hide-cursor' after "Return the current bounds, based on `focus-get-thing'." (bounds-of-thing-at-point (focus-get-thing))) -(defun focus-average-colors (color &rest colors) - "Takes an average of the colors given by argument. -Argument COLOR is a color name, and so are the COLORS; COLOR is -there to ensure that the the function receives at least one -argument." - (let* ((colors (cons color colors)) - (colors (mapcar 'color-name-to-rgb colors)) - (len (length colors)) - (sums (apply 'cl-mapcar '+ colors)) - (avg (mapcar (lambda (v) (/ v len)) sums))) - (apply 'color-rgb-to-hex avg))) - -(defun focus-make-dim-color () - "Return a dimmed color relative to the current theme." - (let ((background (face-attribute 'default :background)) - (foreground (face-attribute 'default :foreground)) - (backgrounds (if (> focus-dimness 0) focus-dimness 1)) - (foregrounds (if (< focus-dimness 0) (- focus-dimness) 1))) - (apply 'focus-average-colors - (append (make-list backgrounds background) - (make-list foregrounds foreground))))) - (defun focus-move-focus () "Move the focused section according to `focus-bounds'. @@ -138,35 +114,41 @@ command." (focus-move-overlays (car bounds) (cdr bounds)))))) (defun focus-move-overlays (low high) - "Move `focus-pre-overlay' and `focus-post-overlay'." - (move-overlay focus-pre-overlay (point-min) low) + "Move `focus-pre-overlay', `focus-mid-overlay' and `focus-post-overlay'." + (move-overlay focus-pre-overlay (point-min) low) + (move-overlay focus-mid-overlay low high) (move-overlay focus-post-overlay high (point-max))) (defun focus-init () "This function is run when command `focus-mode' is enabled. -It sets the `focus-pre-overlay' and `focus-post-overlay' to -overlays; these are invisible until `focus-move-focus' is run. It -adds `focus-move-focus' to `post-command-hook'." +It sets the `focus-pre-overlay', `focus-min-overlay', and +`focus-post-overlay' to overlays; these are invisible until +`focus-move-focus' is run. It adds `focus-move-focus' to +`post-command-hook'." (unless (or focus-pre-overlay focus-post-overlay) (setq focus-pre-overlay (make-overlay (point-min) (point-min)) + focus-mid-overlay (make-overlay (point-min) (point-max)) focus-post-overlay (make-overlay (point-max) (point-max)) focus-buffer (current-buffer)) - (let ((color (or focus-dim-color (focus-make-dim-color)))) - (mapc (lambda (o) (overlay-put o 'face (cons 'foreground-color color))) - (list focus-pre-overlay focus-post-overlay))) + (overlay-put focus-mid-overlay 'face 'focus-focused-face) + (mapc (lambda (o) (overlay-put o 'face 'focus-unfocused-face)) + (list focus-pre-overlay focus-post-overlay)) (add-hook 'post-command-hook 'focus-move-focus nil t) (add-hook 'change-major-mode-hook 'focus-terminate nil t))) (defun focus-terminate () "This function is run when command `focus-mode' is disabled. -The overlays pointed to by `focus-pre-overlay' and `focus-post-overlay' are -deleted, and `focus-move-focus' is removed from `post-command-hook'." +The overlays pointed to by `focus-pre-overlay', +`focus-mid-overlay' and `focus-post-overlay' are deleted, and +`focus-move-focus' is removed from `post-command-hook'." (when (and focus-pre-overlay focus-post-overlay) - (mapc 'delete-overlay (list focus-pre-overlay focus-post-overlay)) + (mapc 'delete-overlay + (list focus-pre-overlay focus-mid-overlay focus-post-overlay)) (remove-hook 'post-command-hook 'focus-move-focus t) - (setq focus-pre-overlay nil + (setq focus-pre-overlay nil + focus-mid-overlay nil focus-post-overlay nil))) (defun focus-goto-thing (bounds) @@ -183,9 +165,7 @@ according to major-mode. If `focus-current-thing' is set, this default is overwritten. This function simply helps set the `focus-current-thing'." (interactive) - (let* ((candidates '(symbol list sexp defun - filename url email word - sentence whitespace line page)) + (let* ((candidates '(defun line list paragraph sentence sexp symbol word)) (thing (completing-read "Thing: " candidates))) (setq focus-current-thing (intern thing)))) @@ -276,11 +256,6 @@ It cleans up the `focus-read-only-blink-timer' and hooks." :keymap (let ((map (make-sparse-keymap))) (define-key map (kbd "C-c C-q") 'focus-read-only-mode) map) - (unless (or (and (color-defined-p (face-attribute 'default :background)) - (color-defined-p (face-attribute 'default :foreground))) - focus-dim-color) - (message "Can't enable focus mode when no theme is loaded. Try setting focus-dim-color!") - (setq focus-mode nil)) (if focus-mode (focus-init) (focus-terminate))) ;;;###autoload