[[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~. 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~. Focus also works well with the built-in tree-sitter library which comes with Emacs 29 or above. Below is an example configuration of using Focus with ~pyton-ts-mode~: #+begin_src emacs-lisp (use-package focus :config (add-to-list 'focus-mode-to-thing '(python-ts-mode . py-thing)) ) (use-package treesit ;; Remember to run `treesit-install-language-grammar' to install the grammar ;; for each designated language. :when (and (fboundp 'treesit-available-p) (treesit-available-p)) :custom (major-mode-remap-alist (python-mode . python-ts-mode) )) :config ;; define `py-thing' for `thing-at-point' so that the `focus-mode' can focus ;; on such python things. (defvar py-thing--thing nil "Store the thing at point. `thing-at-point' moves to the end of the thing first. We should not re-run `py-thing' after that." ) (defvar py-things-to-focus '("class_definition" "function_definition" "try_statement" "except_clause" "if_statement" "else_clause" "for_statement" "while_statement" "module") "Node types considered as python thing.") (defun py-thing-begin () (when-let ((thing (or py-thing--thing (py-thing)))) (goto-char (treesit-node-start thing)))) (defun py-thing-end () (when-let ((thing (py-thing))) (setq py-thing--thing thing) (goto-char (treesit-node-end thing)))) (defun py-thing () (treesit-parent-until (treesit-node-at (point)) (lambda (parent) (member (treesit-node-type parent) py-things-to-focus)))) (put 'py-thing 'beginning-op 'py-thing-begin) (put 'py-thing 'end-op 'py-thing-end) ) #+end_src ** 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~.