Better distrobox and sudo tramp support

This commit is contained in:
2025-02-17 21:21:52 -08:00
parent 6ea87de1b5
commit b1d77b0f5d
3 changed files with 282 additions and 207 deletions

165
init.el
View File

@ -227,12 +227,32 @@ Interactively, force the recompile if called with a prefix."
(use-package tramp
:ensure nil
:config
(add-to-list 'tramp-connection-properties
(list (rx bos "/" (or "podman" "docker") ":")
"direct-async-process" t))
(add-to-list 'tramp-connection-properties
(list (rx bos "/" (or "ssh" "sshx") ":")
"direct-async-process" t))
(add-to-list 'tramp-connection-properties
(list (rx bos "/" (or "sudo" "su" "doas"
"sudoedit")
":")
"direct-async-process" t))
(connection-local-set-profile-variables
'remote-direct-async-process
'((tramp-direct-async-process . t)))
'error-only
'((tramp-verbose . 1)))
(connection-local-set-profiles
'(:protocol "ssh")
'remote-direct-async-process))
'(:method "sudo")
'error-only)
(connection-local-set-profiles
'(:method "doas")
'error-only)
(connection-local-set-profiles
'(:method "su")
'error-only)
(connection-local-set-profiles
'(:method "sudoedit")
'error-only))
(use-package midnight
:ensure nil
@ -1762,9 +1782,6 @@ otherwise, call `bibtex-find-text'."
(use-package pyvenv)
(use-package pyenv-mode)
;; My dev environment for ROS2
(require 'arch-ros2)
;; java-ts-mode
(use-package java-ts-mode
:hook ((java-ts-mode . trusted-files-eglot-ensure-if-safe)
@ -2464,7 +2481,7 @@ argument."
:hook ((eshell-load . eat-eshell-visual-command-mode)
(eshell-mode . eat-eshell-mode)
(eshell-mode . my/-eshell-mode-setup)
(eshell-directory-change . my/-eshell-maybe-setup-remote-aliases))
(eshell-directory-change . my/-eshell-maybe-setup-remote))
:bind (:map eshell-mode-map
("TAB" . completion-at-point)
("<tab>" . completion-at-point))
@ -2479,14 +2496,73 @@ argument."
(or " " eos))
(cl-second elt))))
eshell-command-aliases-list))
(defun my/-eshell-maybe-setup-remote-aliases ()
(if (file-remote-p default-directory)
(setq-local eshell-command-aliases-list (my/-eshell-filter-alias-list))
(kill-local-variable 'eshell-command-aliases-list)))
(defun my/-eshell-container-p (&optional dir)
(member (file-remote-p default-directory 'method)
'("docker" "podman")))
(defun my/-eshell-distrobox-p (&optional dir)
(and (my/-eshell-container-p dir)
(let ((default-directory (or dir default-directory)))
(executable-find "distrobox-host-exec" t))))
(defun my/-eshell-sudo-p (&optional dir)
(member (file-remote-p (or dir default-directory) 'method)
'("sudo" "doas" "su" "sudoedit")))
(defun my/-eshell-really-remote-p (&optional dir)
(and (file-remote-p (or dir default-directory))
(not (my/-eshell-distrobox-p dir))
(not (my/-eshell-sudo-p dir))))
(defun eshell/-captive-cd (&optional dir &rest _)
(cond
((not dir)
(eshell/-captive-cd "~"))
((or (not (file-remote-p default-directory))
(file-remote-p dir))
(eshell/cd dir))
((file-name-absolute-p dir)
(eshell/cd (concat (file-remote-p default-directory) dir)))
(t
(eshell/cd dir))))
(defvar-local my/-eshell-last-remote-system nil)
(defun my/-eshell-maybe-setup-remote (&optional force)
(when (or force (not (equal my/-eshell-last-remote-system
(file-remote-p default-directory))))
(kill-local-variable 'eshell-syntax-highlighting-highlight-in-remote-dirs)
(if (my/-eshell-really-remote-p)
(setq-local eshell-command-aliases-list (my/-eshell-filter-alias-list))
(setq-local eshell-command-aliases-list
(default-toplevel-value 'eshell-command-aliases-list)))
(setq-local eshell-command-aliases-list
(copy-tree eshell-command-aliases-list))
(when (file-remote-p default-directory)
(add-to-list 'eshell-command-aliases-list '("cd" "-captive-cd $1") t))
(when (or (my/-eshell-distrobox-p)
(my/-eshell-sudo-p))
(setq-local eshell-syntax-highlighting-highlight-in-remote-dirs t)
(setf (alist-get "pwd" eshell-command-aliases-list nil nil 'equal)
'("(directory-file-name (file-remote-p default-directory 'localname))")))
(when (my/-eshell-distrobox-p)
(unless (executable-find "eza" t)
(if (executable-find "exa" t)
(setf (alist-get "ls" eshell-command-aliases-list nil nil 'equal)
'("exa -F $*"))
(setf (alist-get "ls" eshell-command-aliases-list nil t 'equal)
nil)))
(unless (executable-find "trash-put" t)
(setf (alist-get "tp" eshell-command-aliases-list nil t 'equal) nil
(alist-get "trr" eshell-command-aliases-list nil t 'equal) nil
(alist-get "tre" eshell-command-aliases-list nil t 'equal) nil
(alist-get "trm" eshell-command-aliases-list nil t 'equal) nil
(alist-get "rm" eshell-command-aliases-list nil t 'equal) nil))
(setf (alist-get "ldg" eshell-command-aliases-list nil t 'equal) nil)))
(setq-local my/-eshell-last-remote-system
(file-remote-p default-directory)))
(defun my/-eshell-mode-setup ()
"Setup function run from `eshell-mode-hook'"
(setq-local corfu-auto nil)
(my/-eshell-maybe-setup-remote-aliases))
(my/-eshell-maybe-setup-remote t))
(setq-default eshell-command-aliases-list
'(("clear" "clear t")
("e" "find-file $1")
@ -2507,10 +2583,10 @@ argument."
("tp" "trash-put $*")
("trr" "trash-restore $*")
("tre" "trash-empty $*")
("tre" "trash-empty $*")
("trm" "trash-rm $*")
("rm" "echo 'rm: I''m unsafe! Don''t use me.'; false")
("\\rm" "eshell/rm")))
(defvar my/eshell-bm-auto-ls t
"Weather or not to run ls after `eshell/bm'")
(defun eshell/bm (&optional name)
@ -2518,10 +2594,61 @@ argument."
If no name is given, list all bookmarks instead."
(if name
(progn
(eshell/cd (bookmark-get-filename name))
(when my/eshell-bm-auto-ls
(eshell/ls)))
(eshell-print (string-join (bookmark-all-names) " ")))))
(string-match (rx bos (group (* (not "/"))) (* "/") (group (* any)))
name)
(let* ((bm-name (match-string 1 name))
(after-path (match-string 2 name))
(bm-path (bookmark-get-filename bm-name))
(full-path (expand-file-name after-path bm-path)))
(when (my/-eshell-distrobox-p)
(setq full-path (concat (file-remote-p default-directory)
full-path)))
(if (not (file-directory-p full-path))
(progn
(find-file full-path)
(goto-char (bookmark-get-position bm-name)))
(eshell/cd full-path)
(when my/eshell-bm-auto-ls
(eshell/ls)))))
(bookmark-maybe-load-default-file)
(eshell-print
(mapconcat (lambda (record)
(let ((name (bookmark-name-from-full-record record))
(file (bookmark-get-filename record)))
(format "%s => %s"
(propertize name 'face '(:foreground "deep sky blue"
:weight bold))
(if (file-directory-p file)
(file-name-as-directory file)
(directory-file-name file)))))
bookmark-alist
"\n"))))
(defun pcomplete/bm ()
"Completions for `bm'."
(let ((arg (pcomplete-arg)))
(if (not (cl-find ?/ arg))
(pcomplete-here (mapcar (##concat % "/") (bookmark-all-names)))
(when (string-match (rx bos (group (+ (not "/"))) (+ "/") (group (* any)))
arg)
(let ((bm-name (match-string 1 arg))
(after-path (match-string 2 arg)))
(when-let ((base (ignore-errors (bookmark-get-filename bm-name)))
((file-directory-p base))
(abs-path (expand-file-name after-path base))
(dir-path (if (string-empty-p after-path)
abs-path
(file-name-directory abs-path)))
(path-end (if (string-empty-p after-path)
""
(file-name-nondirectory abs-path))))
(pcomplete-here
(mapcan (lambda (entry)
(unless (member (car entry) '(".." "."))
(if (eq t (file-attribute-type (cdr entry)))
(list (concat (car entry) "/"))
(list (car entry)))))
(directory-files-and-attributes dir-path))
path-end))))))))
(use-package esh-help
:hook (eshell-mode . my/-setup-eshell-help-func)
:init
@ -2547,7 +2674,7 @@ If `default-directory' is remote, call `my/project-eat-or-default'. Otherwise,
call `my/project-eshell-or-default'. ARG is the same as for either of the above
functions (only eshell uses it at the time of writing)."
(interactive "P")
(if (file-remote-p default-directory)
(if (my/-eshell-really-remote-p)
(my/project-eat-or-default)
(my/project-eshell-or-default arg)))
(keymap-global-set "C-c v" #'my/open-shell-dwim)