Skip to content

Commit

Permalink
Move lisp-mode advice to its own file, improve comments/doc strings
Browse files Browse the repository at this point in the history
  • Loading branch information
greghendershott committed Jan 30, 2024
1 parent b702c19 commit ce57719
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 30 deletions.
30 changes: 0 additions & 30 deletions racket-indent.el
Expand Up @@ -32,36 +32,6 @@
;; `racket-indent-line'. That just directly calls
;; `racket-indent-function'.

;; Having said all that, we still have the matter of `paredit-mode'.
;; It directly calls `lisp-indent-line' instead of
;; `indent-line-function'. And, it directly calls `indent-sexp'
;; instead of `prog-indent-sexp'. Therefore it gets `lisp-mode'
;; indent, not ours. To address this, advise those two functions to do
;; the right thing when one of our major modes is active.
(defun racket--lisp-indent-line-advice (orig &rest args)
"If `racket--mode-edits-racket-p' use the variable `indent-line-function'."
(apply (if (racket--mode-edits-racket-p) indent-line-function orig)
args))
(defun racket--indent-sexp-advice (orig &rest args)
"If `racket--mode-edits-racket-p' use `racket-indent-sexp-contents'."
(apply (if (racket--mode-edits-racket-p) #'racket-indent-sexp-contents orig)
args))
(advice-add 'lisp-indent-line :around #'racket--lisp-indent-line-advice)
(advice-add 'indent-sexp :around #'racket--indent-sexp-advice)

;; lisp-mode's `indent-sexp' differs from `prog-indent-sexp'. The
;; former does NOT indent the current line, just subsequent lines (if
;; any). In other words it does not indent the sexp as a whole, just
;; its contents. That behavior is desirable in some cases; see e.g.
;; issue #293. So supply our equivalent of `indent-sexp' here, too:
(defun racket-indent-sexp-contents ()
"Indent each line of the sexp starting just after point."
(interactive)
(let ((end-of-expression (save-excursion (forward-sexp 1) (point)))
(beg-of-2nd-line (save-excursion (forward-line 1) (point))))
(when (< beg-of-2nd-line end-of-expression)
(indent-region beg-of-2nd-line end-of-expression))))

(defun racket-indent-line (&optional _whole-exp)
"Indent current line as Racket code.
Expand Down
59 changes: 59 additions & 0 deletions racket-lisp-mode.el
@@ -0,0 +1,59 @@
;;; racket-lisp-mode.el -*- lexical-binding: t; -*-

;; Copyright (c) 2013-2024 by Greg Hendershott.
;; Portions Copyright (C) 1985-1986, 1999-2013 Free Software Foundation, Inc.

;; Author: Greg Hendershott
;; URL: https://github.com/greghendershott/racket-mode

;; SPDX-License-Identifier: GPL-3.0-or-later

;; 1. Some packages like paredit and lispy directly call `lisp-mode'
;; functions `lisp-indent-line' and `indent-sexp'. (As opposed to
;; calling functions like `indent-line-to' and `prog-indent-sexp'
;; that a mode can specialize via `indent-line-function' and
;; `indent-region-function'.)
;;
;; 2. Although that's OK for modes like `scheme-mode' that are derived
;; from `lisp-mode', `racket-mode' is not.
;;
;; Therefore if users want to use such packages hardwired to call
;; those two `lisp-mode' function, AFAICT we have no choice but to
;; advise those two functions. :(
;;
;; Furthermore lisp-mode's `indent-sexp' differs from
;; `prog-indent-sexp' as explained below in the doc string for
;; `racket-indent-sexp-contents'.

(require 'lisp-mode)
(require 'racket-util)

(defun racket--lisp-indent-line-advice (orig &rest args)
"If `racket--mode-edits-racket-p' use the variable `indent-line-function'."
(apply (if (racket--mode-edits-racket-p) indent-line-function orig)
args))
(advice-add 'lisp-indent-line :around #'racket--lisp-indent-line-advice)

(defun racket--indent-sexp-advice (orig &rest args)
"If `racket--mode-edits-racket-p' use `racket-indent-sexp-contents'."
(apply (if (racket--mode-edits-racket-p) #'racket-indent-sexp-contents orig)
args))
(advice-add 'indent-sexp :around #'racket--indent-sexp-advice)

(defun racket-indent-sexp-contents ()
"Indent each line of the sexp starting just after point.
Unlike `prog-indent-sexp', which indents the entire sexp, this
does /not/ indent the first line, at point, just subsequent lines
if any. In other words it does not indent the sexp as a whole,
just its contents. In this regard it is similar to the
`lisp-mode'-specific function `indent-sexp'."
(interactive)
(let ((beg-of-2nd-line (save-excursion (forward-line 1) (point)))
(end-of-expression (save-excursion (forward-sexp 1) (point))))
(when (< beg-of-2nd-line end-of-expression)
(indent-region beg-of-2nd-line end-of-expression))))

(provide 'racket-lisp-mode)

;; racket-lisp-mode.el ends here
1 change: 1 addition & 0 deletions racket-mode.el
Expand Up @@ -36,6 +36,7 @@
(require 'racket-repl)
(require 'racket-repl-buffer-name)
(require 'racket-collection)
(require 'racket-lisp-mode)
(require 'racket-bug-report)
(require 'racket-util)
(require 'easymenu)
Expand Down

0 comments on commit ce57719

Please sign in to comment.