info-gnu-emacs
[Top][All Lists]
Advanced

[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))))
  └────


reply via email to

[Prev in Thread] Current Thread [Next in Thread]