Focus/README.org

5.4 KiB

https://melpa.org/packages/focus-badge.svg https://stable.melpa.org/packages/focus-badge.svg

Focus

/larstvei/Focus/media/commit/350e711fa729946b8447911a1ec6ebe7b6c00b89/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 MELPA and MELPA Stable:

M-x package-install focus

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 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

'((prog-mode . defun) (text-mode . sentence))

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:

(add-to-list 'focus-mode-to-thing '(python-mode . paragraph))

changes python-mode to focus in on code-blocks with no blank lines rather than the entire function.

According to 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:

  (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)
    )

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.