mirror of
https://github.com/larstvei/Focus.git
synced 2024-11-26 11:38:32 +00:00
commit
cfb1672fca
43
README.md
43
README.md
@ -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/):
|
|
||||||
|
|
||||||
<kbd> M-x package-install focus </kbd>
|
|
||||||
|
|
||||||
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 <kbd> M-x focus-mode </kbd>.
|
|
||||||
|
|
||||||
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 <kbd> M-x focus-read-only-mode </kbd> or <kbd> C-c C-q </kbd> if `focus-mode` is enabled.
|
|
||||||
|
|
||||||
Some bindings for simple navigation and exiting `focus-read-only-mode` are provided.
|
|
||||||
|
|
||||||
Keybinding | Description
|
|
||||||
-------------------|----------------------------
|
|
||||||
<kbd> n </kbd> | Jump to next *thing*
|
|
||||||
<kbd> SPC </kbd> | Jump to next *thing*
|
|
||||||
<kbd> p </kbd> | Jump to previous *thing*
|
|
||||||
<kbd> S-SPC </kbd> | Jump to previous *thing*
|
|
||||||
<kbd> i </kbd> | Exit `focus-read-only-mode`
|
|
||||||
<kbd> q </kbd> | 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)
|
|
||||||
:---------------------------------------:|:---------------------------------------:
|
|
||||||
<img src="./demo-light.gif" width="333"> | <img src="./demo-dark.gif" width="333">
|
|
87
README.org
Normal file
87
README.org
Normal file
@ -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~.
|
BIN
demo-dark.gif
BIN
demo-dark.gif
Binary file not shown.
Before Width: | Height: | Size: 353 KiB |
BIN
demo-light.gif
BIN
demo-light.gif
Binary file not shown.
Before Width: | Height: | Size: 279 KiB |
BIN
focus-demo.gif
Normal file
BIN
focus-demo.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 MiB |
87
focus.el
87
focus.el
@ -38,17 +38,6 @@
|
|||||||
:group 'font-lock
|
:group 'font-lock
|
||||||
:prefix "focus-")
|
: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))
|
(defcustom focus-mode-to-thing '((prog-mode . defun) (text-mode . sentence))
|
||||||
"An associated list between mode and thing.
|
"An associated list between mode and thing.
|
||||||
|
|
||||||
@ -70,12 +59,18 @@ Things that are defined include `symbol', `list', `sexp',
|
|||||||
:type '(float)
|
:type '(float)
|
||||||
:group 'focus)
|
: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
|
(defvar focus-cursor-type cursor-type
|
||||||
"Used to restore the users `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
|
(defvar-local focus-current-thing nil
|
||||||
"Overrides the choice of thing dictated by `focus-mode-to-thing' if set.")
|
"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
|
(defvar-local focus-pre-overlay nil
|
||||||
"The overlay that dims the text prior to the current-point.")
|
"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
|
(defvar-local focus-post-overlay nil
|
||||||
"The overlay that dims the text past the current-point.")
|
"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'."
|
"Return the current bounds, based on `focus-get-thing'."
|
||||||
(bounds-of-thing-at-point (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 ()
|
(defun focus-move-focus ()
|
||||||
"Move the focused section according to `focus-bounds'.
|
"Move the focused section according to `focus-bounds'.
|
||||||
|
|
||||||
@ -138,35 +114,41 @@ command."
|
|||||||
(focus-move-overlays (car bounds) (cdr bounds))))))
|
(focus-move-overlays (car bounds) (cdr bounds))))))
|
||||||
|
|
||||||
(defun focus-move-overlays (low high)
|
(defun focus-move-overlays (low high)
|
||||||
"Move `focus-pre-overlay' and `focus-post-overlay'."
|
"Move `focus-pre-overlay', `focus-mid-overlay' and `focus-post-overlay'."
|
||||||
(move-overlay focus-pre-overlay (point-min) low)
|
(move-overlay focus-pre-overlay (point-min) low)
|
||||||
|
(move-overlay focus-mid-overlay low high)
|
||||||
(move-overlay focus-post-overlay high (point-max)))
|
(move-overlay focus-post-overlay high (point-max)))
|
||||||
|
|
||||||
(defun focus-init ()
|
(defun focus-init ()
|
||||||
"This function is run when command `focus-mode' is enabled.
|
"This function is run when command `focus-mode' is enabled.
|
||||||
|
|
||||||
It sets the `focus-pre-overlay' and `focus-post-overlay' to
|
It sets the `focus-pre-overlay', `focus-min-overlay', and
|
||||||
overlays; these are invisible until `focus-move-focus' is run. It
|
`focus-post-overlay' to overlays; these are invisible until
|
||||||
adds `focus-move-focus' to `post-command-hook'."
|
`focus-move-focus' is run. It adds `focus-move-focus' to
|
||||||
|
`post-command-hook'."
|
||||||
(unless (or focus-pre-overlay focus-post-overlay)
|
(unless (or focus-pre-overlay focus-post-overlay)
|
||||||
(setq focus-pre-overlay (make-overlay (point-min) (point-min))
|
(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-post-overlay (make-overlay (point-max) (point-max))
|
||||||
focus-buffer (current-buffer))
|
focus-buffer (current-buffer))
|
||||||
(let ((color (or focus-dim-color (focus-make-dim-color))))
|
(overlay-put focus-mid-overlay 'face 'focus-focused-face)
|
||||||
(mapc (lambda (o) (overlay-put o 'face (cons 'foreground-color color)))
|
(mapc (lambda (o) (overlay-put o 'face 'focus-unfocused-face))
|
||||||
(list focus-pre-overlay focus-post-overlay)))
|
(list focus-pre-overlay focus-post-overlay))
|
||||||
(add-hook 'post-command-hook 'focus-move-focus nil t)
|
(add-hook 'post-command-hook 'focus-move-focus nil t)
|
||||||
(add-hook 'change-major-mode-hook 'focus-terminate nil t)))
|
(add-hook 'change-major-mode-hook 'focus-terminate nil t)))
|
||||||
|
|
||||||
(defun focus-terminate ()
|
(defun focus-terminate ()
|
||||||
"This function is run when command `focus-mode' is disabled.
|
"This function is run when command `focus-mode' is disabled.
|
||||||
|
|
||||||
The overlays pointed to by `focus-pre-overlay' and `focus-post-overlay' are
|
The overlays pointed to by `focus-pre-overlay',
|
||||||
deleted, and `focus-move-focus' is removed from `post-command-hook'."
|
`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)
|
(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)
|
(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)))
|
focus-post-overlay nil)))
|
||||||
|
|
||||||
(defun focus-goto-thing (bounds)
|
(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
|
default is overwritten. This function simply helps set the
|
||||||
`focus-current-thing'."
|
`focus-current-thing'."
|
||||||
(interactive)
|
(interactive)
|
||||||
(let* ((candidates '(symbol list sexp defun
|
(let* ((candidates '(defun line list paragraph sentence sexp symbol word))
|
||||||
filename url email word
|
|
||||||
sentence whitespace line page))
|
|
||||||
(thing (completing-read "Thing: " candidates)))
|
(thing (completing-read "Thing: " candidates)))
|
||||||
(setq focus-current-thing (intern thing))))
|
(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)))
|
:keymap (let ((map (make-sparse-keymap)))
|
||||||
(define-key map (kbd "C-c C-q") 'focus-read-only-mode)
|
(define-key map (kbd "C-c C-q") 'focus-read-only-mode)
|
||||||
map)
|
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)))
|
(if focus-mode (focus-init) (focus-terminate)))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
|
Loading…
Reference in New Issue
Block a user