emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: New for GNU ELPA: literate-scratch


From: Philip Kaludercic
Subject: Re: New for GNU ELPA: literate-scratch
Date: Sat, 15 Jun 2024 13:12:41 +0000

Sean Whitton via "Emacs development discussions." <emacs-devel@gnu.org>
writes:

> Hello,
>
> I'm planning to add this to GNU ELPA.  Posting here for comments.
>
> Variant Lisp Interaction mode for easier interleaving of paragraphs of
> plain text with Lisp code.  This means you can have
>
>     ;; This buffer is for text that is not saved ...
>     ;; To create a file, visit it with C-x C-f and ...
>
>     (here is some Lisp)
>
>     Here is a plain text paragraph )( including some unmatched parentheses.
>     Uh oh!  Paredit won't like that.
>
>     (here is some more Lisp)
>
> but (e.g.) Paredit won't complain about the unmatched parentheses.
> Indeed, the whole plain text paragraph is font-locked as a comment.
>
> If you use Paredit but want to be able to use *scratch* for both Lisp
> interaction and blocks of plain text, then this mode is for you.
> Also compatible with the orgalist-mode and orgtbl-mode minor modes.
>
> To enable this mode after installing this file, simply customise
> `initial-major-mode' to `literate-scratch-mode'.
>
> ;;; literate-scratch.el --- Lisp Interaction w/ text paragraphs  -*- 
> lexical-binding: t -*-
>
> ;; Copyright (C) 2023-2024  Free Software Foundation, Inc.
>
> ;; Author: Sean Whitton <spwhitton@spwhitton.name>
> ;; Maintainer: Sean Whitton <spwhitton@spwhitton.name>
> ;; Package-Requires: ((emacs "29.1"))
> ;; Version: 1.0pre
> ;; URL: 
> https://git.spwhitton.name/dotfiles/tree/.emacs.d/site-lisp/literate-scratch.el
> ;; Keywords: lisp text
>
> ;; This file is free software: you can redistribute it and/or modify
> ;; it under the terms of the GNU General Public License as published by
> ;; the Free Software Foundation, either version 3 of the License, or
> ;; (at your option) any later version.
>
> ;; This file is distributed in the hope that it will be useful,
> ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
> ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> ;; GNU General Public License for more details.
>
> ;; You should have received a copy of the GNU General Public License
> ;; along with this file.  If not, see <https://www.gnu.org/licenses/>.
>
> ;;; Commentary:
>
> ;; Variant Lisp Interaction mode for easier interleaving of paragraphs of
> ;; plain text with Lisp code.  This means you can have
> ;;
> ;;     ;; This buffer is for text that is not saved ...
> ;;     ;; To create a file, visit it with C-x C-f and ...
> ;;
> ;;     (here is some Lisp)
> ;;
> ;;     Here is a plain text paragraph )( including some unmatched parentheses.
> ;;     Uh oh!  Paredit won't like that.
> ;;
> ;;     (here is some more Lisp)
> ;;
> ;; but (e.g.) Paredit won't complain about the unmatched parentheses.
> ;; Indeed, the whole plain text paragraph is font-locked as a comment.
> ;;
> ;; If you use Paredit but want to be able to use *scratch* for both Lisp
> ;; interaction and blocks of plain text, then this mode is for you.
> ;; Also compatible with the orgalist-mode and orgtbl-mode minor modes.
> ;;
> ;; To enable this mode after installing this file, simply customise
> ;; `initial-major-mode' to `literate-scratch-mode'.
>
> ;;; News:
>
> ;; Ver 1.0 YYYY/MM/DD Sean Whitton
> ;;     Initial release.
>
> ;;; Code:
>
> (defun literate-scratch--extend (start end)
>   (save-excursion
>     (let ((res1
>          (and (goto-char start)
>               (not (looking-at paragraph-separate))
>               (and-let* ((new (car (bounds-of-thing-at-point 'paragraph))))
>                 (and (< new start)
>                      (setq start new)))))

You should be able to merge the `and-let*' and `and' like

--8<---------------cut here---------------start------------->8---
(and-let* ((new (car (bounds-of-thing-at-point 'paragraph)))
           ((< new start)))
  (setq start new))
--8<---------------cut here---------------end--------------->8---


>         (res2
>          (and (goto-char end)
>               (not (looking-at paragraph-separate))
>               (and-let* ((new (cdr (bounds-of-thing-at-point 'paragraph))))
>                 (and (> new end)
>                      (setq end new))))))
>       (and (or res1 res2)
>          (cons start end)))))
>
> (defun literate-scratch--propertize (start end)
>   (goto-char start)
>   (let ((start (1- start)))
>     (catch 'finish
>       (while t
>       (when-let* ((comment-start (nth 8 (syntax-ppss))))

Could `while-let' be useful here?

>         (put-text-property (1- (point)) (point) 'syntax-table
>                            (eval-when-compile
>                              (string-to-syntax "!")))
>         (put-text-property comment-start (point) 'syntax-multiline t))
>       (forward-paragraph 1)
>       (backward-paragraph 1)
>       (unless (> end (point) start)
>         (throw 'finish nil))
>       (setq start (point))
>       (unless
>           (save-excursion
>             (catch 'done
>               (while t
>                 ;; Examine the syntax of the paragraph's first char.
>                 ;; If it's whitespace, we need to check the previous
>                 ;; paragraph, to handle multiple paragraphs within a defun.
>                 (let ((syn
>                        (char-syntax
>                         (char-after
>                          ;; (1+ point) unless at end-of-buf or on first line
>                          ;; of a paragraph beginning right at beg-of-buf.
>                          (and (not (eobp))
>                               (not (and (bobp)
>                                         (looking-at
>                                          "[[:space:]]*[^[:space:]\n]")))

You should be able to merge this into a single `looking-at' expression
by matching against the beginning of a buffer (\\`).

>                               (1+ (point)))))))
>                   (cond ((bobp) (throw 'done (memq syn '(?\( ?<))))
>                         ((memq syn '(?\( ?<)) (throw 'done t))
>                         ((not (eq syn ?\s)) (throw 'done nil))))
>                 (backward-paragraph 1))))
>         (put-text-property (point) (1+ (point)) 'syntax-table
>                            (eval-when-compile
>                              (string-to-syntax "!"))))
>       (forward-paragraph 1))))
>   ;; Now also call the usual `syntax-propertize-function' for this mode.
>   (elisp-mode-syntax-propertize start end))
>
> (define-derived-mode literate-scratch-mode lisp-interaction-mode
>   "Lisp Interaction"
>   "Variant `lisp-interaction-mode' designed for the *scratch* buffer.
>
> Paragraphs that don't start with `(' or `;' are treated as block comments.
> This makes it easier to interleave paragraphs of plain text with Lisp.
>
> You can enable this mode by customizing the variable `initial-major-mode'
> to `literate-scratch-mode'."
>   (add-hook 'syntax-propertize-extend-region-functions
>           #'syntax-propertize-multiline t t)
>   (add-hook 'syntax-propertize-extend-region-functions
>           #'literate-scratch--extend t t)
>   (setq-local syntax-propertize-function #'literate-scratch--propertize))
>
> (provide 'literate-scratch)
>
> ;;; literate-scratch.el ends here

Otherwise looks neat!

-- 
        Philip Kaludercic on peregrine



reply via email to

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