A bunch of changes

This commit is contained in:
Alexander Rosenberg 2024-10-09 07:32:06 -07:00
parent 2c08ad6436
commit a6ba5e74a3
Signed by: Zander671
GPG Key ID: 5FD0394ADBD72730
2 changed files with 332 additions and 34 deletions

273
elisp/latex-help.el Normal file
View File

@ -0,0 +1,273 @@
;;; latex-help.el --- Lookup LaTeX symbols -*- lexical-binding: t -*-
;;; Commentary:
;; This is inspired by an old package (originally from the 90s!!) called
;; ltx-help.el. This package used to be called latex-help.el too, but it seems
;; to have had its name changed sometime around 2010. This package aims for
;; similar functionality, but using more up to date and convention-conforming
;; Elisp. For example, the original package still assumes that you may not have
;; `add-hook' or `buffer-substring-no-properties'. Only very old versions of
;; Emacs are missing these, so almost everyone has them nowadays.
;;; Code:
(require 'info)
(defcustom latex-help-info-manual "latex2e"
"The name of the info manual to use when looking up latex commands."
:group 'latex-help
:type '(choice
(string :tag "English" "latex2e")
(string :tag "French" "latex2e-fr")
(string :tag "Spanish" "latex2e-es")))
(defcustom latex-help-buffer-name "*latex-help*"
"The name of the info buffer to use when showing LaTeX documentation."
:group 'latex-help
:type 'string)
(defun latex-help--run-index-search (regexp)
"Search the LaTeX info pages index for REGEXP.
This returns a list of cache entries suitable for use in
`latex-help--commands-cache'."
(with-temp-buffer
(Info-mode)
(Info-find-node latex-help-info-manual "Index" nil t)
(let ((found))
(while (re-search-forward regexp nil t)
(let ((match (match-string-no-properties 1))
(node (match-string-no-properties 2)))
(if (equal (caar found) match)
(push (cons node (pos-bol)) (cdar found))
(push (list match (cons node (pos-bol))) found))))
found)))
(defvar latex-help--commands-cache nil
"Cahce of discovered of LaTeX commands.
These do NOT have a leading '\\'.")
(defun latex-help--discover-commands ()
"Discover LaTeX commands.
This is done by parsing the index for `latex-help-info-manual'."
(let ((found (latex-help--run-index-search
(rx (and bol "* \\"
(group (or
","
(+ (not (any " " "{" ",")))))
(*? any) ":" (+ " ")
(group (+? any)) ".")))))
(push (list "(SPACE)" "\\(SPACE)") found)
(when-let (entry (assoc "(...\\)" found))
(setq found (assoc-delete-all "(...\\)" found))
(push (cons "(" (cdr entry)) found)
(push (cons ")" (cdr entry)) found))
(when-let (entry (assoc "[...\\]" found))
(setq found (assoc-delete-all "[...\\]" found))
(push (cons "[" (cdr entry)) found)
(push (cons "]" (cdr entry)) found))
found))
(defvar latex-help--package-cache nil
"Cache of discovered LaTeX packages.")
(defun latex-help--discover-packages ()
"Discover LaTeX packages.
This is done by parsing the index for `latex-help-info-manual'."
(latex-help--run-index-search (rx (and bol "* package, "
(group (+? any))
(any " " ":")
(+? any) (+ " ")
(group (+? any))
"."))))
(defvar latex-help--environment-cache nil
"Cache of discovered LaTeX environments.")
(defun latex-help--discover-environments ()
"Discover LaTeX environments.
This is done by parsing the index for `latex-help-info-manual'."
(latex-help--run-index-search (rx (and bol "* environment, "
(group (+? any))
(any " " ":" "-")
(+? any) (+ " ")
(group (+? any))
"."))))
(defvar latex-help--class-cache nil
"Cache of discovered LaTeX document classes.")
(defun latex-help--discover-classes ()
"Discover LaTeX document classes.
This is done by parsing the index for `latex-help-info-manual'."
(latex-help--run-index-search (rx (and bol "* "
(group (+ (not (any "," " "))))
" class:" (+ " ")
(group (+ (not ".")))))))
(defun latex-help--goto-entry (entry)
"Open the info page for ENTRY, a cache entry."
(let ((buffer (get-buffer-create latex-help-buffer-name)))
(with-current-buffer buffer
(unless (derived-mode-p 'Info-mode)
(Info-mode))
(Info-find-node latex-help-info-manual "Index" nil t)
(goto-char (cdr entry))
(Info-follow-nearest-node))
(pop-to-buffer buffer)))
(defvar latex-help--caches-initialized-p nil
"Non-nil if the latex-help caches have been initialized.")
(defun latex-help--get-cache-for-type (type)
"Lookup the cache for TYPE.
If the caches are not yet initialized, do that first."
(unless latex-help--caches-initialized-p
(setq latex-help--commands-cache (latex-help--discover-commands)
latex-help--package-cache (latex-help--discover-packages)
latex-help--environment-cache (latex-help--discover-environments)
latex-help--class-cache (latex-help--discover-classes)
latex-help--caches-initialized-p t))
(cond
((eq type 'command)
latex-help--commands-cache)
((eq type 'package)
latex-help--package-cache)
((eq type 'environment)
latex-help--environment-cache)
((eq type 'class)
latex-help--class-cache)))
(defun latex-help--history nil
"History list for `latex-help--maybe-prompt-entry'.")
(defun latex-help--maybe-prompt-entry (name type &optional default)
"Lookup and prompt the user for the node of NAME.
The lookup is performed in the correct cache for TYPE. If there is only one
node associated with NAME, return its entry. Otherwise, ask the user which node
they want to use.
If DEFAULT is non-nil, use that instead of prompting. If it does not exist,
return nil."
(when-let (entries (alist-get name (latex-help--get-cache-for-type type)
nil nil 'equal))
(cond
(default
(assoc default entries))
((length= entries 1)
(car entries))
(t
(let ((resp (completing-read "Select Node: " (mapcar 'car entries)
nil t nil)))
(assoc resp entries))))))
(defun latex-help--get-thing-at-point ()
"Return a cons of the LaTeX thing at point and its type (as a symbol).
If nothing is found, return nil.
The following types are known:
- command
- package
- environment
- class
The following are some examples:
- \\textbf{Hello World} -> \\='(\"textbf\" . command)
- \\begin{math} (on \"math\") -> \\='(\"math\" . environment)
- \\begin{math} (on \"begin\") -> \\='(\"begin\" . command)
- \\usepackage{amsmath} (on \"amsmath\") -> \\='(\"amsmath\" . package)
- \\usepackage{amsmath} (on \"usepackage\") -> \\='(\"usepackage\" . command)"
(save-excursion
(let ((orig-point (point)))
(when (eq (char-after) ?\\)
(forward-char))
(when (and (search-backward "\\" nil t)
(looking-at (rx "\\"
(group (+ (not (any " " "\n" "("
"{" "[" "|"
"}" "]" ")")))))))
(let ((cmd (match-string-no-properties 1)))
(if (> (match-end 1) orig-point)
(cons cmd 'command)
(goto-char orig-point)
(condition-case _
(progn
(backward-up-list nil t t)
(when (looking-at (rx "{" (group (+ (not (any "}" "\n"))))))
(let ((thing (match-string-no-properties 1)))
(cond
((equal cmd "usepackage")
(cons thing 'package))
((or (equal cmd "begin")
(equal cmd "end"))
(cons thing 'environment))
((equal cmd "documentclass")
(cons thing 'class))))))
;; just return nil
((or user-error scan-error)))))))))
(defun latex-help--prompt-for (type)
"Prompt for a command, environment, etc. from TYPE.
This returns the name of the thing that was prompted."
(let* ((cache (latex-help--get-cache-for-type type))
(tap (latex-help--get-thing-at-point))
(default (and (eq (cdr tap) type) (car tap))))
(unless (assoc default cache)
(setq default nil))
(completing-read (format "LaTeX %s%s: "
(capitalize (symbol-name type))
(if default
(format " (default %s)" default)
""))
(latex-help--get-cache-for-type type)
nil t nil 'latex-help--history
default)))
(defun latex-help-command (name &optional node)
"Lookup the LaTeX command NAME.
Unless NODE is non-nil, if NAME is in more than one node, prompt the user for
which to use. If NODE is non-nil, use that instead."
(interactive (list (latex-help--prompt-for 'command)))
(when-let (entry (latex-help--maybe-prompt-entry name 'command node))
(latex-help--goto-entry entry)))
(defun latex-help-environment (name &optional node)
"Lookup the LaTeX environment NAME.
Unless NODE is non-nil, if NAME is in more than one node, prompt the user for
which to use. If NODE is non-nil, use that instead."
(interactive (list (latex-help--prompt-for 'environment)))
(when-let (entry (latex-help--maybe-prompt-entry name 'environment node))
(latex-help--goto-entry entry)))
(defun latex-help-package (name &optional node)
"Lookup the LaTeX package NAME.
Unless NODE is non-nil, if NAME is in more than one node, prompt the user for
which to use. If NODE is non-nil, use that instead."
(interactive (list (latex-help--prompt-for 'package)))
(when-let (entry (latex-help--maybe-prompt-entry name 'package node))
(latex-help--goto-entry entry)))
(defun latex-help-class (name &optional node)
"Lookup the LaTeX document class NAME.
Unless NODE is non-nil, if NAME is in more than one node, prompt the user for
which to use. If NODE is non-nil, use that instead."
(interactive (list (latex-help--prompt-for 'class)))
(when-let (entry (latex-help--maybe-prompt-entry name 'class node))
(latex-help--goto-entry entry)))
(defun latex-help-at-point ()
"Try to lookup the LaTeX thing at point, whatever it may be.
This will try to look up the command, package, document class, or environment at
point. If that thing at point is valid, it will open an info buffer to the
documentation for that thing."
(interactive)
(if-let (thing (latex-help--get-thing-at-point))
(if-let (entry (latex-help--maybe-prompt-entry (car thing)
(cdr thing)))
(latex-help--goto-entry entry)
(user-error "Unknown %s: \"%s\""
(symbol-name (cdr thing))
(if (eq (cdr thing) 'command)
(concat "\\" (car thing))
(car thing))))
(user-error "Nothing at point to look up")))
(provide 'latex-help)
;;; latex-help.el ends here

87
init.el
View File

@ -215,7 +215,8 @@ BUFFER can be a string or a buffer."
((stringp buffer) ((stringp buffer)
(not (string-prefix-p " " buffer))) (not (string-prefix-p " " buffer)))
((bufferp buffer) ((bufferp buffer)
(my/buffer-visible-p (buffer-name buffer))) (and (stringp (buffer-name buffer))
(my/buffer-visible-p (buffer-name buffer))))
(t (t
(signal 'wrong-type-argument `((or bufferp stringp) ,buffer))))) (signal 'wrong-type-argument `((or bufferp stringp) ,buffer)))))
@ -378,7 +379,8 @@ directory. Otherwise, run `find-file' on that file."
:hook (undo-tree-visualizer-mode . my/-undo-tree-visualizer-mode-setup) :hook (undo-tree-visualizer-mode . my/-undo-tree-visualizer-mode-setup)
:config :config
(defun my/-undo-tree-visualizer-mode-setup () (defun my/-undo-tree-visualizer-mode-setup ()
(visual-line-mode -1)) (visual-line-mode -1)
(setq truncate-lines t))
(global-undo-tree-mode)) (global-undo-tree-mode))
;; evil ;; evil
@ -722,11 +724,21 @@ to `posframe-show' if the display is graphical."
:init :init
(defun my/flymake-show-diagnostic-at-point () (defun my/flymake-show-diagnostic-at-point ()
(interactive) (interactive)
(if-let ((pos (point)) (when flymake-mode
(diag (and flymake-mode (let* ((diag (get-char-property (point) 'flymake-diagnostic))
(get-char-property pos 'flymake-diagnostic))) (diag-msg (when diag
(message (flymake--diag-text diag))) (apply 'concat
(my/floating-tooltip " *flymake-error-posframe*" message)))) (mapcar
(lambda (msg)
(concat "" msg "\n"))
(split-string (flymake--diag-text diag)
"\n")))))
(jinx-msg (when (jinx--get-overlays (point) (1+ (point)))
"•misspelled word\n")))
(unless (and (zerop (length diag-msg))
(zerop (length jinx-msg)))
(my/floating-tooltip " *flymake-error-posframe*"
(concat diag-msg jinx-msg)))))))
;; flycheck ;; flycheck
(use-package flycheck (use-package flycheck
@ -740,12 +752,15 @@ to `posframe-show' if the display is graphical."
(defun my/flycheck-show-diagnostic-at-point () (defun my/flycheck-show-diagnostic-at-point ()
(interactive) (interactive)
(if-let ((flycheck-mode) (if-let ((flycheck-mode)
(errors (flycheck-overlay-errors-at (point))) (message
(message (apply 'concat (apply 'concat
(mapcar (nconc (mapcar
(lambda (error) (lambda (error)
(concat "" (flycheck-error-message error) "\n")) (concat "" (flycheck-error-message error) "\n"))
errors)))) (flycheck-overlay-errors-at (point)))
(when (jinx--get-overlays (point) (1+ (point)))
'("•misspelled word\n")))))
((not (zerop (length message)))))
(my/floating-tooltip " *flycheck-error-posframe*" (my/floating-tooltip " *flycheck-error-posframe*"
(substring message 0 (1- (length message))))))) (substring message 0 (1- (length message)))))))
(use-package consult-flycheck (use-package consult-flycheck
@ -1019,7 +1034,7 @@ When EXCLUDE-BRACES is non-nil, don't count the first and last brace of the
entry as in the entry. That is, if the point is on the first { or last } of the entry as in the entry. That is, if the point is on the first { or last } of the
entry, return nil." entry, return nil."
(save-excursion (save-excursion
(when (and exclude-braces (= ?\} (char-after))) (when (and exclude-braces (eq ?\} (char-after)))
(forward-char)) (forward-char))
;; go to top level and check if the character at point is { ;; go to top level and check if the character at point is {
(let ((start-pos (point)) (let ((start-pos (point))
@ -1030,7 +1045,7 @@ entry, return nil."
(setq last-valid (point))) (setq last-valid (point)))
(error (error
(and (and
(= ?\{ (char-after last-valid)) (eq ?\{ (char-after last-valid))
(or (not exclude-braces) (or (not exclude-braces)
(not (= start-pos last-valid))))))))) (not (= start-pos last-valid)))))))))
(defvar my/bibtex-indent-width 4 (defvar my/bibtex-indent-width 4
@ -1082,10 +1097,14 @@ otherwise, call `bibtex-find-text'."
(evil-define-key 'normal bibtex-mode-map (evil-define-key 'normal bibtex-mode-map
(kbd "TAB") 'my/bibtex-indent-or-find-text-and-insert) (kbd "TAB") 'my/bibtex-indent-or-find-text-and-insert)
;; Latex help (from elisp file)
(require 'latex-help)
;; AUCTeX ;; AUCTeX
(use-package auctex (use-package auctex
:hook ((LaTeX-mode . turn-on-reftex) :hook ((LaTeX-mode . turn-on-reftex)
(LaTeX-mode . LaTeX-math-mode)) (LaTeX-mode . LaTeX-math-mode)
(LaTeX-mode . my/-setup-LaTeX-mode))
:init :init
(add-to-list 'major-mode-remap-alist '(plain-tex-mode . plain-TeX-mode)) (add-to-list 'major-mode-remap-alist '(plain-tex-mode . plain-TeX-mode))
(add-to-list 'major-mode-remap-alist '(latex-mode . LaTeX-mode)) (add-to-list 'major-mode-remap-alist '(latex-mode . LaTeX-mode))
@ -1095,6 +1114,8 @@ otherwise, call `bibtex-find-text'."
(add-to-list 'major-mode-remap-alist '(doctex-mode . docTeX-mode)) (add-to-list 'major-mode-remap-alist '(doctex-mode . docTeX-mode))
(add-to-list 'auto-mode-alist '("/\\.latexmkrc\\'" . perl-mode)) (add-to-list 'auto-mode-alist '("/\\.latexmkrc\\'" . perl-mode))
:config :config
(defun my/-setup-LaTeX-mode ()
(setq evil-lookup-func 'latex-help-at-point))
(setq TeX-auto-save t (setq TeX-auto-save t
TeX-parse-self t TeX-parse-self t
reftex-plug-into-AUCTeX t) reftex-plug-into-AUCTeX t)
@ -1419,7 +1440,7 @@ argument."
(funcall-interactively #'sage-shell:run-sage (funcall-interactively #'sage-shell:run-sage
(sage-shell:read-command))))) (sage-shell:read-command)))))
;; fricas (because I like calculator) ;; fricas (because I like calculators)
(add-to-list 'load-path "/usr/lib/fricas/emacs/") (add-to-list 'load-path "/usr/lib/fricas/emacs/")
(use-package fricas (use-package fricas
:ensure nil :ensure nil
@ -1762,10 +1783,14 @@ If no name is given, list all bookmarks instead."
(setq-local evil-lookup-func #'helpful-at-point)) (setq-local evil-lookup-func #'helpful-at-point))
(defun my/-setup-helpful-mode () (defun my/-setup-helpful-mode ()
(setq-local evil-lookup-func #'helpful-at-point)) (setq-local evil-lookup-func #'helpful-at-point))
(defvar my/helpful-symbol-history-size 20 (defvar my/helpful-symbol-history-size 50
"Max size of `my/helpful-symbol-history'.") "Max size of `my/helpful-symbol-history'.")
(defvar my/helpful-symbol-history '() (defvar my/helpful-symbol-history '()
"History of helpful symbols.") "History of helpful symbols.")
(defvar my/-helpful-inhibit-history nil
"If non-nil, don't add symbols to `my/helpful-symbol-history'.")
(defvar my/-helpful-last-entry nil
"Last entry looked up with helpful.")
(defun my/helpful-history-back (count) (defun my/helpful-history-back (count)
"Go back COUNT symbols in `my/helpful-symbol-history'. If called "Go back COUNT symbols in `my/helpful-symbol-history'. If called
interactively, COUNT defaults to 1." interactively, COUNT defaults to 1."
@ -1791,7 +1816,8 @@ the oldest entry if -COUNT is larger than the history."
((and (< count 0) (= (1+ current-pos) hist-len)) ((and (< count 0) (= (1+ current-pos) hist-len))
(message "%s" "No older symbol!")) (message "%s" "No older symbol!"))
(t (t
(let ((entry (cond (let ((my/-helpful-inhibit-history t)
(entry (cond
((<= new-pos 0) ((<= new-pos 0)
(seq-first my/helpful-symbol-history)) (seq-first my/helpful-symbol-history))
((>= new-pos hist-len) ((>= new-pos hist-len)
@ -1804,29 +1830,29 @@ the oldest entry if -COUNT is larger than the history."
(defun my/-helpful-switch-buffer-function (helpful-buf) (defun my/-helpful-switch-buffer-function (helpful-buf)
"Like `pop-to-buffer', but kill previous helpful buffers and save the new "Like `pop-to-buffer', but kill previous helpful buffers and save the new
buffers `helpful--sym' to `my/helpful-symbol-history'." buffers `helpful--sym' to `my/helpful-symbol-history'."
(cl-loop for buf in (buffer-list) (cl-loop with window = nil
with window = nil for buf in (buffer-list)
with last-index = nil
when (and when (and
(not (eq buf helpful-buf)) (not (eq buf helpful-buf))
(eq (buffer-local-value 'major-mode buf) 'helpful-mode)) (eq (buffer-local-value 'major-mode buf) 'helpful-mode))
do do
(when-let (cur-window (get-buffer-window buf nil)) (when-let (cur-window (get-buffer-window buf nil))
(setq window cur-window)) (setq window cur-window))
(when-let (entry (buffer-local-value 'helpful--sym buf))
(setq last-index (seq-position my/helpful-symbol-history entry 'equal)))
(kill-buffer buf) (kill-buffer buf)
finally finally
(when-let ((entry (cons (buffer-local-value 'helpful--sym helpful-buf) (let ((entry (cons (buffer-local-value 'helpful--sym helpful-buf)
(buffer-local-value 'helpful--callable-p (buffer-local-value 'helpful--callable-p
helpful-buf))) helpful-buf))))
((not (seq-contains-p my/helpful-symbol-history entry (unless my/-helpful-inhibit-history
'equal)))) (when-let (from-current-hist
(when last-index (member my/-helpful-last-entry
my/helpful-symbol-history))
(setq my/helpful-symbol-history from-current-hist))
(cl-pushnew entry my/helpful-symbol-history :test 'equal)
(setq my/helpful-symbol-history (setq my/helpful-symbol-history
(seq-drop my/helpful-symbol-history last-index))) (seq-take my/helpful-symbol-history
(push entry my/helpful-symbol-history) my/helpful-symbol-history-size)))
(seq-take my/helpful-symbol-history my/helpful-symbol-history-size)) (setq my/-helpful-last-entry entry))
(if window (if window
(window--display-buffer helpful-buf window 'reuse) (window--display-buffer helpful-buf window 'reuse)
(pop-to-buffer helpful-buf)))) (pop-to-buffer helpful-buf))))
@ -1957,7 +1983,6 @@ one of the normal rainbow-delimiters-depth-N-face faces."
;; page break lines ;; page break lines
(use-package page-break-lines (use-package page-break-lines
:hook (helpful-mode . page-break-lines-mode)
:config :config
(global-page-break-lines-mode 1) (global-page-break-lines-mode 1)
(add-to-list 'page-break-lines-modes 'prog-mode) (add-to-list 'page-break-lines-modes 'prog-mode)