Compare commits

...

10 commits

Author SHA1 Message Date
Henrik Lissner
6365309164
tweak: use :tools (lsp +eglot) by default 2025-09-17 15:55:55 -04:00
Henrik Lissner
1b4a629897
perf(tramp): memoize common TRAMP I/O
This is experimental.

Ref: https://coredumped.dev/2025/06/18/making-tramp-go-brrrr.
2025-09-17 15:55:55 -04:00
Henrik Lissner
0fb377c057
fix(tramp): direct-async + lsp-mode/eglot interop
Neither lsp-mode nor eglot work over tramp with direct-async on, but I
don't want to disable direct-async globally just for lsp-mode/eglot
users, so I try to disable it solely for their stdio processes.

More testing is needed to weed out edge cases that may result from this.

Ref: emacs-lsp/lsp-mode#4573
Fix: #8510
2025-09-17 15:55:55 -04:00
Henrik Lissner
b2c9faf345
tweak(tramp): remote-file-name-inhibit-auto-save-visited = t
Less I/O = faster connections.
2025-09-17 15:55:55 -04:00
Henrik Lissner
5217f37703
fix(tramp): magit-tramp-pipe-stty-settings typo
Amend: 71eae252ac
2025-09-17 15:55:55 -04:00
Henrik Lissner
b277d96d3a
nit(tramp): simplify comments
And give credit where it's due.

Also defers connection-local-set-* calls.
2025-09-17 15:55:41 -04:00
Henrik Lissner
6eb467668e
fix(org): update org-babel-python-command-nonsession
Ref: bzg/org-mode@9239b0e8d1
2025-09-17 10:45:14 -04:00
Henrik Lissner
a4526fd10d
refactor(org): remove ob-ditaa fix
The scripts directory was removed from org-contrib back in Org 9.5. Now,
there is no way to resolve the "correct" location of these jar paths
without cloning the entirety of Worg, which is too heavy a dependency to
manage for an unmaintained package.
2025-09-17 10:40:55 -04:00
Henrik Lissner
6a630660ac
fix(org): +jupyter: wrong-number-of-args error
Forgot to remove the extra argument when I converted this from an
:around advice to :before.

Fix: #8509
Amend: 979b3aa8c1
2025-09-17 10:16:53 -04:00
Henrik Lissner
7b35a31322
fix(org): +jupyter: syntax highlighting for remapped modes
Particularly treesit ts-modes.
2025-09-17 10:16:40 -04:00
4 changed files with 99 additions and 28 deletions

View file

@ -10,36 +10,51 @@
(after! tramp
(setq remote-file-name-inhibit-cache 60
remote-file-name-inhibit-locks t
remote-file-name-inhibit-auto-save-visited t
tramp-copy-size-limit (* 1024 1024) ; 1mb
tramp-use-scp-direct-remote-copying t
tramp-completion-reread-directory-timeout 60
tramp-backup-directory-alist backup-directory-alist
tramp-auto-save-directory (concat doom-cache-dir "tramp-autosave/"))
;; the ssh method is faster tha nthe default ssh on Windows
(unless (featurep :system 'windows)
(setq tramp-default-method "ssh")))
(setq tramp-default-method "ssh"))) ; faster than scp on Windows
;; PERF: When creating a new process in Emacs, you have two options: synchronous
;; or asynchronous. Async processes have historically been really slow over
;; TRAMP, because it has to create a new connection for every async process.
;; However recent version of TRAMP have added a feature called direct async
;; process that makes this significantly faster. This feature alone will take
;; many packages (like magit or git-gutter) from completely unusable to
;; bearable over TRAMP. Here is how you configure it with TRAMP 2.7.
(connection-local-set-profile-variables
'remote-direct-async-process
'((tramp-direct-async-process . t)))
;; See https://coredumped.dev/2025/06/18/making-tramp-go-brrrr.
(after! files-x
(connection-local-set-profile-variables
'remote-direct-async-process
'((tramp-direct-async-process . t)))
(connection-local-set-profiles
`(:application tramp :protocol "scp")
'remote-direct-async-process)
(connection-local-set-profiles
`(:application tramp :protocol "scp")
'remote-direct-async-process))
;;;###package lsp-mode
;; HACK: lsp-mode over TRAMP doesn't work with direct async, so force it off for
;; LSP stdio connections.
(defadvice! +tramp--disable-direct-async-for-lsp-stdio-a (plist)
:filter-return #'lsp-stdio-connection
(let ((connect-fn (plist-get plist :connect)))
(plist-put plist :connect
(lambda (&rest args)
(letf! ((#'tramp-direct-async-process-p #'ignore))
(apply connect-fn args))))))
;;;###package eglot
;; HACK: Same deal with eglot.
(defadvice! +tramp--disable-direct-async-for-eglot-a (fn &rest args)
:around #'eglot--connect
(letf! ((#'tramp-direct-async-process-p #'ignore))
(apply fn args)))
;; See magit/magit#5220
(after! magit
(setq magit-tramp-pipe-stty-setings 'pty))
(setq magit-tramp-pipe-stty-settings 'pty))
;; PERF: Newer versions of TRAMP will use SSH connection sharing for much faster
@ -48,3 +63,48 @@
;; back on.
(after! (tramp compile)
(remove-hook 'compilation-mode-hook #'tramp-compile-disable-ssh-controlmaster-options))
;;
;;; Memoization
;; PERF: Calls over TRAMP are expensive, so reduce the number of calls by more
;; aggressively caching some common data. Inspired by
;; https://coredumped.dev/2025/06/18/making-tramp-go-brrrr.
(defun +tramp--memoize (key cache fn &rest args)
"Memoize a value if the key is a remote path."
(if (and key (file-remote-p key))
(if-let* ((current (assoc key (symbol-value cache))))
(cdr current)
(let ((current (apply fn args)))
(set cache (cons (cons key current) (symbol-value cache)))
current))
(apply fn args)))
;;;###package magit
(defvar +tramp--magit-toplevel-cache nil)
(defadvice! +tramp--memoized-magit-toplevel-a (orig &optional directory)
:around #'magit-toplevel
(+tramp--memoize (or directory default-directory)
'+tramp--magit-toplevel-cache orig directory))
;;;###package project
(defvar +tramp--project-current-cache nil)
(defadvice! +tramp--memoized-project-current (fn &optional prompt directory)
:around #'project-current
(+tramp--memoize (or directory
project-current-directory-override
default-directory)
'+tramp--project-current-cache fn prompt directory))
;;;###package vc-git
(defvar +tramp--vc-git-root-cache nil)
(defadvice! +tramp--memoized-vc-git-root-a (fn file)
:around #'vc-git-root
(let ((value
(+tramp--memoize (file-name-directory file)
'+tramp--vc-git-root-cache fn file)))
;; sometimes vc-git-root returns nil even when there is a root there
(unless (cdar +tramp--vc-git-root-cache)
(setq +tramp--vc-git-root-cache (cdr +tramp--vc-git-root-cache)))
value))

View file

@ -286,21 +286,15 @@ Also adds support for a `:sync' parameter to override `:async'."
(end (progn (goto-char beg) (forward-line) (org-babel-result-end))))
(org-display-inline-images nil nil (min beg end) (max beg end)))))))
(after! python
(unless org-babel-python-command
(setq org-babel-python-command
(after! ob-python
(when (equal org-babel-python-command-nonsession "python")
(setq org-babel-python-command-nonsession
(string-trim
(concat python-shell-interpreter " "
(if (string-match-p "\\<i?python[23]?$" python-shell-interpreter)
(replace-regexp-in-string
"\\(^\\| \\)-i\\( \\|$\\)" " " python-shell-interpreter-args)
python-shell-interpreter-args))))))
(after! ob-ditaa
;; TODO Should be fixed upstream
(let ((default-directory (org-find-library-dir "org-contribdir")))
(setq org-ditaa-jar-path (expand-file-name "scripts/ditaa.jar")
org-ditaa-eps-jar-path (expand-file-name "scripts/DitaaEps.jar")))))
python-shell-interpreter-args)))))))
(defun +org-init-babel-lazy-loader-h ()

View file

@ -5,6 +5,23 @@
(use-package! jupyter-repl
:defer t
:config
;; HACK: Don't use treesit ts-modes for syntax highlighting (is brittle).
(defadvice! +org-jupyter--suppress-major-mode-remapping-a (fn &rest args)
:around #'jupyter-kernel-language-mode-properties
(let (major-mode-remap-alist major-mode-remap-defaults)
(apply fn args)))
;; HACK: And un-remap the major mode when associating a repl with the current
;; buffer, otherwise it will fail with any treesit-enabled (or otherwise
;; remapped) modes.
(defadvice! +org-jupyter--unremap-major-mode-when-associating-buffer-a (fn &rest args)
:around #'jupyter-repl-associate-buffer
(let ((major-mode
(or (car (rassq major-mode (append major-mode-remap-alist
major-mode-remap-defaults)))
major-mode)))
(apply fn args)))
;; HACK: If the user is anywhere but the last prompt, typing should move them
;; there instead of unhelpfully spewing read-only errors at them.
;; REVIEW: Upstream this (maybe?)
@ -35,7 +52,7 @@
;; HACK: ob-juypter don't support ob-async and handles async itself, so
;; piggyback off of `org-babel-jupyter-make-language-alias' to disable it
;; for every current and future kernel language.
(defadvice! +org-jupyter--suppress-ob-async-a (fn _kernel lang)
(defadvice! +org-jupyter--suppress-ob-async-a (_kernel lang)
:before #'org-babel-jupyter-make-language-alias
(with-eval-after-load 'ob-async
(add-to-list 'ob-async-no-async-languages-alist (concat "jupyter-" lang))))

View file

@ -99,7 +99,7 @@
(eval +overlay) ; run code, run (also, repls)
lookup ; navigate your code and its documentation
;;llm ; when I said you needed friends, I didn't mean...
;;lsp ; M-x vscode
;;(lsp +eglot) ; M-x vscode
magit ; a git porcelain for Emacs
;;make ; run make tasks from Emacs
;;pass ; password manager for nerds