[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
New GNU ELPA package: logos - Simple focus mode and extras
From: |
Sacha Chua |
Subject: |
New GNU ELPA package: logos - Simple focus mode and extras |
Date: |
Mon, 14 Mar 2022 23:15:19 -0400 |
Requires: emacs-27.1
Website: https://gitlab.com/protesilaos/logos
Maintainer: Protesilaos Stavrou <info@protesilaos.com>
Author: Protesilaos Stavrou <info@protesilaos.com>
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
LOGOS.EL: SIMPLE FOCUS MODE FOR EMACS WITH PAGE
BREAKS OR OUTLINES
Protesilaos Stavrou
info@protesilaos.com
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
This manual, written by Protesilaos Stavrou, describes the customization
options for `logos' (or `logos.el'), and provides every other piece of
information pertinent to it.
The documentation furnished herein corresponds to stable version 0.1.0,
released on 2022-03-11. Any reference to a newer feature which does not
yet form part of the latest tagged commit, is explicitly marked as such.
Current development target is 0.2.0-dev.
Table of Contents
─────────────────
1. COPYING
2. Overview
3. Installation
4. Sample configuration
5. Extra tweaks
.. 1. Center the buffer in its window
.. 2. Automatically reveal Org or Outline subtree
.. 3. Recenter at the top upon page motion
.. 4. Use outlines and page breaks
1 COPYING
═════════
Copyright (C) 2022 Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify
this document under the terms of the GNU Free
Documentation License, Version 1.3 or any later version
published by the Free Software Foundation; with no
Invariant Sections, with the Front-Cover Texts being “A
GNU Manual,” and with the Back-Cover Texts as in (a)
below. A copy of the license is included in the section
entitled “GNU Free Documentation License.”
(a) The FSF’s Back-Cover Text is: “You have the freedom to
copy and modify this GNU manual.”
2 Overview
══════════
This package provides a simple “focus mode” which can be applied to
any buffer for reading, writing, or even doing a presentation. The
buffer can be divided in pages using the `page-delimiter', outline
structure, or any other pattern. Commands are provided to move
between those pages. These motions work even when narrowing is in
effect (and they preserve it). `logos.el' is designed to be simple by
default and easy to extend. This manual provides concrete examples to
that end.
What constitutes a page delimiter is determined by the user options
`logos-outlines-are-pages' and `logos-outline-regexp-alist'. By
default, this only corresponds to the `^L' character (which can be
inserted using the standard keys with `C-q C-l').
Logos does not define any key bindings. Try something like this, if
you want:
┌────
│ (let ((map global-map))
│ (define-key map [remap narrow-to-region] #'logos-narrow-dwim)
│ (define-key map [remap forward-page] #'logos-forward-page-dwim)
│ (define-key map [remap backward-page] #'logos-backward-page-dwim))
└────
On stanard Emacs, those key bindings are: `C-x n n', `C-x ]', `C-x ['.
The `logos-narrow-dwim' is not necessary for users who already know
how to narrow effectively. Such users may still want to bind it to a
key.
Logos provides some optional aesthetic tweaks which come into effect
when the buffer-local `logos-focus-mode' is enabled. These will hide
the mode line (`logos-hide-mode-line'), enable `scroll-lock-mode'
(`logos-scroll-lock'), and use `variable-pitch-mode' in
non-programming buffers (`logos-variable-pitch'). All these variables
are buffer-local.
Logos is the familiar word derived from Greek (watch my presentation
on philosophy about Cosmos, Logos, and the living universe:
<https://protesilaos.com/books/2022-02-05-cosmos-logos-living-universe/>),
though it also stands for these two perhaps equally insightful
backronyms about the mechanics of this package:
1. `^L' Only Generates Ostensible Slides
2. Logos Optionally Garners Outline Sections
3 Installation
══════════════
Logos is not in any package archive for the time being, though I plan
to submit it to GNU ELPA (as such, any non-trivial patches require
copyright assignment to the Free Software Foundation). Users can rely
on `straight.el', `quelpa', or equivalent to fetch the source. Below
are the essentials for those who prefer the manual method.
Assuming your Emacs files are found in `~/.emacs.d/', execute the
following commands in a shell prompt:
┌────
│ cd ~/.emacs.d
│
│ # Create a directory for manually-installed packages
│ mkdir manual-packages
│
│ # Go to the new directory
│ cd manual-packages
│
│ # Clone this repo, naming it "logos"
│ git clone https://gitlab.com/protesilaos/logos.git logos
└────
Finally, in your `init.el' (or equivalent) evaluate this:
┌────
│ ;; Make Elisp files in that directory available to the user.
│ (add-to-list 'load-path "~/.emacs.d/manual-packages/logos")
└────
Everything is in place to set up the package.
4 Sample configuration
══════════════════════
Logos does not bind its own keys and does not make any opinionated
changes out-of-the-box ([Extra tweaks]):
⁃ To get the do-what-I-mean page motions add your own key bindings.
In the example below, they take the stead of `forward-page' (`C-x
]') and `backward-page' (`C-x ['). The command `logos-narrow-dwim'
need not be bound, especially if you are already familiar with the
various narrowing commands (otherwise it maps to `C-x n n' in this
example, assuming the default keys).
⁃ To have quick access to `logos-focus-mode', bind it to a key. This
mode checks the variables `logos-hide-mode-line',
`logos-scroll-lock', `logos-variable-pitch' and applies their
effects if they are non-nil. Note that everything is buffer-local,
so it is possible to use file variables as described in the Emacs
manual.
┌────
│ (require 'logos)
│
│ ;; If you want to use outlines instead of page breaks (the ^L)
│ (setq logos-outlines-are-pages t)
│ (setq logos-outline-regexp-alist
│ `((emacs-lisp-mode . "^;;;+ ")
│ (org-mode . "^\\*+ +")
│ (t . ,(or outline-regexp logos--page-delimiter))))
│
│ ;; These apply when `logos-focus-mode' is enabled. Their value is
│ ;; buffer-local.
│ (setq-default logos-hide-mode-line nil)
│ (setq-default logos-scroll-lock nil)
│ (setq-default logos-variable-pitch nil)
│
│ (let ((map global-map))
│ (define-key map [remap narrow-to-region] #'logos-narrow-dwim)
│ (define-key map [remap forward-page] #'logos-forward-page-dwim)
│ (define-key map [remap backward-page] #'logos-backward-page-dwim)
│ (define-key map (kbd "<f9>") #'logos-focus-mode))
└────
[Extra tweaks] See section 5
5 Extra tweaks
══════════════
This section contains snippets of code that extend the functionality
of `logos'. These either apply to `logos-focus-mode' or enhance the
page motions through the `logos-page-motion-hook'.
5.1 Center the buffer in its window
───────────────────────────────────
Use the excellent `olivetti' package by Paul W. Rankin. Here we
configure Olivetti to take effect when we enter `logos-focus-mode' and
be disabled when we exit.
┌────
│ ;; glue code for `logos-focus-mode' and `olivetti-mode'
│ (defun my-logos--olivetti-mode ()
│ "Toggle `olivetti-mode'."
│ (if (or (bound-and-true-p olivetti-mode)
│ (null (logos--focus-p)))
│ (olivetti-mode -1)
│ (olivetti-mode 1)))
│
│ (add-hook 'logos-focus-mode-hook #'my-logos--olivetti-mode)
└────
5.2 Automatically reveal Org or Outline subtree
───────────────────────────────────────────────
The Logos page motions normally jump between positions. Though Org
and Outline require that Logos also reveals the headings’ contents.
This is necessary to avoid invisible motions inside a folded heading
that contains subheadings. The unfolding only applies to the current
entry. This is the relevant snippet from `logos.el':
┌────
│ (defun logos--reveal-entry ()
│ "Reveal Org or Outline entry."
│ (cond
│ ((and (eq major-mode 'org-mode)
│ (org-at-heading-p))
│ (org-show-entry))
│ ((or (eq major-mode 'outline-mode)
│ (bound-and-true-p outline-minor-mode))
│ (outline-show-entry))))
│
│ (add-hook 'logos-page-motion-hook #'logos--reveal-entry)
└────
Users may prefer to reveal the entire subtree instead of the current
entry: the heading at point and all of its subheadings. In this case,
one may override the definition of `logos--reveal-entry':
┌────
│ ;; glue code to expand an Org/Outline heading
│ (defun logos--reveal-entry ()
│ "Reveal Org or Outline entry."
│ (cond
│ ((and (eq major-mode 'org-mode)
│ (org-at-heading-p))
│ (org-show-subtree))
│ ((or (eq major-mode 'outline-mode)
│ (bound-and-true-p outline-minor-mode))
│ (outline-show-subtree))))
└────
5.3 Recenter at the top upon page motion
────────────────────────────────────────
Page motions normally reposition the point at the centre of the window
if necessary (this is standard Emacs behaviour). To always change the
placement invoke the `recenter' function with a numeric argument.
┌────
│ ;; place point at the top when changing pages
│ (defun my-logos--recenter-top ()
│ "Use `recenter' to reposition the view at the top."
│ (recenter 0))
│
│ (add-hook 'logos-page-motion-hook #'my-logos--recenter-top)
└────
The `0' argument refers to the topmost line. So `1' points to the
line below and so on.
If the recentering should not affect specific modes, tweak the
function accordingly:
┌────
│ (defvar my-logos-no-recenter-top-modes
│ '(emacs-lisp-mode lisp-interaction-mode))
│
│ (defun my-logos--recenter-top ()
│ "Use `recenter' to reposition the view at the top."
│ (unless (memq major-mode my-logos-no-recenter-top-modes)
│ (recenter 0)))
└────
Or simply exclude all programming modes:
┌────
│ (defun my-logos--recenter-top ()
│ "Use `recenter' to reposition the view at the top."
│ (unless (derived-mode-p 'prog-mode)
│ (recenter 0)))
└────
5.4 Use outlines and page breaks
────────────────────────────────
By default, the page motions only move between the `^L' delimiters.
While the option `logos-outlines-are-pages' changes the behaviour to
move between outline headings instead. What constitutes an “outline
heading” is determined by `logos-outline-regexp-alist'.
Provided this:
┌────
│ (setq logos-outlines-are-pages t)
└────
The default value of `logos-outline-regexp-alist' will affect
`org-mode', `emacs-lisp-mode', and any of their derivatives
(e.g. `lisp-interaction-mode' (the standard scratch buffer) is based
on `emacs-lisp-mode'). Its fallback value is whatever the major mode
sets as an outline, else the standard `^L'.
┌────
│ (setq logos-outline-regexp-alist
│ `((emacs-lisp-mode . "^;;;+ ")
│ (org-mode . "^\\*+ +")
│ (t . ,(or outline-regexp logos--page-delimiter))))
└────
It is possible to tweak those regular expressions to target both the
outline and the page delimiters:
┌────
│ (setq logos-outline-regexp-alist
│ `((emacs-lisp-mode . ,(format "\\(^;;;+ \\|%s\\)" (default-value
'page-delimiter)))
│ (org-mode . ,(format "\\(^\\*+ +\\|%s\\)" (default-value
'page-delimiter)))
│ (t . ,(or outline-regexp logos--page-delimiter))))
└────
The form `,(format "\\(^;;;+ \\|%s\\)" logos--page-delimiter)' expands
to `"\\(^;;;+ \\|^\\)"'.
For Org it may be better to either not target the `^L' or to also
target the horizontal rule (five hyphens on a line, else the
`^-\\{5\\}$' pattern). Putting it all together:
┌────
│ (setq logos-outline-regexp-alist
│ `((emacs-lisp-mode . ,(format "\\(^;;;+ \\|%s\\)"
logos--page-delimiter))
│ (org-mode . ,(format "\\(^\\*+ +\\|^-\\{5\\}$\\|%s\\)"
logos--page-delimiter))
│ (t . ,(or outline-regexp logos--page-delimiter))))
└────
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- New GNU ELPA package: logos - Simple focus mode and extras,
Sacha Chua <=