You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
(menu-bar-mode-1)
(tool-bar-mode-1)
(setq inhibit-startup-screen t)
(global-display-line-numbers-mode1)
(setq display-line-numbers 'visual
display-line-numbers-type 'relative)
(add-hook'conf-mode-hook'display-line-numbers-mode)
(add-hook'conf-space-mode-hook'display-line-numbers-mode) ;; it breaks tramp with pipes?
(add-hook'text-mode-hook'display-line-numbers-mode)
(add-hook'prog-mode-hook'display-line-numbers-mode)
(defunmy-mode-line-major-mode ()
"Returns a clean name of the current major mode."
(let ((mode (format"%s" major-mode)))
(replace-regexp-in-string"-mode$""" mode)))
(setq-default mode-line-format
'("%e"
mode-line-front-space
(:eval (if (buffer-file-name)
(abbreviate-file-name (buffer-file-name)) ; Show abbreviated file path"%b")) ; Show buffer name if not a file buffer""
(:eval (my-mode-line-major-mode)) ; Custom major mode display
(:eval (propertize""'display '(space :align-to (- right 12))))
(vc-mode vc-mode))) ; Git branch information
Tabs
(setq tab-bar-tab-name-format-function #'my-tab-bar-vim-name-format-function)
(setq tab-bar-format '(tab-bar-format-tabs tab-bar-separator))
(setq tab-bar-separator "\u200B") ;; Zero width space to fix color bleeding
(setq tab-bar-tab-hints nil) ;; Tab numbers of the left of the label
(setq tab-bar-new-button-show nil)
(setq tab-bar-close-button-show nil)
(setq tab-bar-auto-width nil)
(defunmy-tab-name-format-function (tabi)
(deffacemy-active-tab-face
'((t:background"#2e2c3d":foreground"#e0def4"))
"Face for the active tab.")
(deffacemy-inactive-tab-face
'((t:background"#1d1f21":foreground"#6e6a86"))
"Face for the inactive tab.")
(let ((current-p (eq (car tab) 'current-tab))
(tab-name (format"%d%s" i (alist-get'name (cdr tab)))))
;; Add padding around the tab name
(setq tab-name (format"%s" tab-name)) ;; Add a space before and after the tab name
(if current-p
(propertize tab-name 'face'my-active-tab-face)
(propertize tab-name 'face'my-inactive-tab-face))))
(setq tab-bar-tab-name-format-function #'my-tab-name-format-function)
(dotimes (i 9)
(let ((n (1+ i))) ; Tab numbers start from 1
(global-set-key (kbd (format"M-%d" n))
`(lambda () (interactive) (tab-bar-select-tab ,n)))))
(defunfind-file-check-dir (filename&optionalwildcards)
"Edit file FILENAME. Switch to a buffer visiting file FILENAME, creating one if none already exists. If the directory path does not exist, create it."
(interactive
(find-file-read-args"Find file: "nil))
(let ((dir (file-name-directory filename)))
(when (not (file-exists-p dir))
(make-directory dir t)))
(find-file filename wildcards))
(use-package transient
:ensuret:config;; Define a simple transient for the cp command
(transient-define-prefix my-eshell-cp-transient ()
"Transient for the cp command."
["cp options"
("r""Recursive""-r")
("v""Verbose""-v")
("e""Execute" my-eshell-execute-cp :transientnil)]))
(defunmy-eshell-execute-cp ()
"Function to construct cp command with selected options and insert it into eshell."
(interactive)
(let ((args (transient-args 'my-eshell-cp-transient)))
;; Construct the cp command with selected options
(let ((command (concat"cp " (string-join args ""))))
;; Insert the command into the eshell buffer
(insert command)
;; Optionally, you can also execute the command immediately;; (eshell-send-input)
)))
Xterm-color
;; Disabled it because it renders incorrect output in esheell when i do this:;; (setq mylist '(1 2 3));; (1 2 3);; echo 0 $mylist;; (0 "���");; (use-package xterm-color;; :ensure t);; ;; Breaks rendering inside docker shells entered using 'shell-command'.;; ;; (setq comint-output-filter-functions;; ;; (remove 'ansi-color-process-output comint-output-filter-functions));; ;; (defun my/setup-docker-buffer ();; ;; "Set up a buffer for Docker output.";; ;; (setq-local ansi-color-for-comint-mode t);; ;; (setq-local xterm-color-preserve-properties t);; ;; (font-lock-mode -1) ; Disable font-lock to improve performance;; ;; );; ;; (add-hook 'docker-container-logs-mode-hook #'my/setup-docker-buffer);; (add-hook 'shell-mode-hook;; (lambda ();; ;; Disable font-locking in this buffer to improve performance;; (font-lock-mode -1);; ;; Prevent font-locking from being re-enabled in this buffer;; (make-local-variable 'font-lock-function);; (setq font-lock-function (lambda (_) nil));; (add-hook 'comint-preoutput-filter-functions 'xterm-color-filter nil t)));; ;; Compilation buffers;; (setq compilation-environment '("TERM=xterm-256color"));; (defun my/advice-compilation-filter (f proc string);; (funcall f proc (xterm-color-filter string)));; (advice-add 'compilation-filter :around #'my/advice-compilation-filter)
;; Initializing symex causing troubles with pressing parenthesis in the insert mode;; (use-package symex;; :config;; (symex-initialize);; (global-set-key (kbd "C-;") 'symex-mode-interface)) ; or whatever keybinding you like
(use-package cider
:ensuret:config
(setq cider-eldoc-display-for-symbol-at-point nil)
(setq cider-show-error-buffer nil)
(add-hook'cider-mode-hook (lambda () (eldoc-mode-1))))
(setq eldoc-documentation-function (lambda () nil))
(setq cider-stacktrace-default-filters '(clojure user)) ;; Haven't actually tried. The idea of this parameter is to show more sane error messages.
Project/Projectile
(require'project)
(defcustomproject-root-markers
'("Cargo.toml""compile_commands.json""compile_flags.txt""project.clj"".git""deps.edn""shadow-cljs.edn")
"Files or directories that indicate the root of a project.":type '(repeat string)
:group'project)
(defunproject-root-p (path)
"Check if the current PATH has any of the project root markers."
(catch'found
(dolist (marker project-root-markers)
(when (file-exists-p (concat path marker))
(throw'found marker)))))
(defunproject-find-root (path)
"Search up the PATH for `project-root-markers' with additional conditions."
(cond;; Check if the path is within the specific directory
((string-prefix-p"/home/wurfkreuz/.secret_dotfiles/org" (expand-file-name path))
(cons'transient"/home/wurfkreuz/.secret_dotfiles/org/"))
;; Fall back to the original project root detection
(t (when-let ((root (locate-dominating-file path #'project-root-p)))
(cons'transient (expand-file-name root))))))
(use-package emacs
:custom;; Support opening new minibuffers from inside existing minibuffers.
(enable-recursive-minibufferst)
;; Emacs 28 and newer: Hide commands in M-x which do not work in the current;; mode. Vertico commands are hidden in normal buffers. This setting is;; useful beyond Vertico.
(read-extended-command-predicate #'command-completion-default-include-p)
:init;; Add prompt indicator to `completing-read-multiple'.;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma.
(defuncrm-indicator (args)
(cons (format"[CRM%s] %s"
(replace-regexp-in-string"\\`\\[.*?]\\*\\|\\[.*?]\\*\\'"""
crm-separator)
(car args))
(cdr args)))
(advice-add#'completing-read-multiple:filter-args#'crm-indicator)
;; Do not allow the cursor in the minibuffer prompt
(setq minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt))
(add-hook'minibuffer-setup-hook#'cursor-intangible-mode))
(use-package vertico
:ensuret:custom
(vertico-scroll-margin 0) ;; Different scroll margin;; (vertico-count 20) ;; Show more candidates;; (vertico-resize t) ;; Grow and shrink the Vertico minibuffer
(vertico-cycle t) ;; Enable cycling for `vertico-next/previous':init
(vertico-mode))
(use-package marginalia
:ensuret:init
(marginalia-mode))
(use-package consult
:ensuret)
(use-package embark-consult
:ensuret)
(defunmy-vertico-shell-command-history ()
"Use `completing-read` to search through shell command history and return the selected command."
(let ((history shell-command-history))
(completing-read"Shell command history: " history nilnilnil'shell-command-history)))
(defunmy-insert-selected-command (selected-command)
"Insert the selected command into the minibuffer and print a message."
(when selected-command
(insert selected-command)))
(defunmy-shell-command-history-and-insert ()
"Search shell command history and insert the selected command into the minibuffer."
(interactive)
(let ((selected-command (my-vertico-shell-command-history)))
(my-insert-selected-command selected-command)))
(defunmy-eshell-history-choose ()
"Select an item from eshell history using Vertico and insert it into the eshell prompt."
(interactive)
(let* ((history (ring-elements eshell-history-ring))
(history (delete-dups history))
(command (consult--read history
:prompt"Eshell history: ":sortnil:require-matcht)))
(when command
(eshell-kill-input)
(insert command))))
Ivy/Counsel
(use-package ivy
:ensuret:bind;; ivy-resume resumes the last Ivy-based completion.
(("C-c C-r". ivy-resume)
("C-x B". ivy-switch-buffer-other-window))
:custom
(setq ivy-use-virtual-buffers t)
(setq ivy-count-format "(%d/%d) ")
(setq enable-recursive-minibuffers t))
;; :init;; (ivy-mode))
(use-package swiper
:ensuret)
;; (use-package counsel;; :ensure t;; :after ivy;; :config;; (define-key shell-mode-map (kbd "M-r") 'counsel-shell-history));; :init;; (counsel-mode));; (global-set-key (kbd "C-c C-y") 'cousel-yank-pop);; (defun my-ivy-shell-command-history ();; "Use `ivy-read` to search through shell command history.";; (interactive);; (let ((history (if (eq this-command 'my-async-shell-command);; shell-command-history;; shell-command-history)));; (ivy-read "Shell command history: " history)));; (defun my-shell-command (command &optional output-buffer error-buffer);; "Run shell command with custom history.";; (interactive (list (my-ivy-shell-command-history);; current-prefix-arg;; shell-command-default-error-buffer));; ;; Add the command to the history;; (unless (string= command "");; (add-to-history 'shell-command-history command));; (shell-command command output-buffer error-buffer));; (defun my-async-shell-command (command &optional output-buffer error-buffer);; "Run async shell command with custom history.";; (interactive (list (my-ivy-shell-command-history);; current-prefix-arg;; shell-command-default-error-buffer));; ;; Add the command to the history;; (unless (string= command "");; (add-to-history 'shell-command-history command));; (async-shell-command command output-buffer error-buffer));; (global-set-key (kbd "M-!") 'my-shell-command);; (global-set-key (kbd "M-&") 'my-async-shell-command)
(defunivy-fzf-project ()
"Run a customized `ivy-fzf`-like file selection using `fd` from the current project directory."
(interactive)
(let* ((project (project-currentt))
(default-directory (if project (project-root project) default-directory))
(fzf-command "fd --hidden --exclude .git --exclude .snapshots --exclude opt --exclude lib --exclude lib64 --exclude mnt --exclude proc --exclude run --exclude sbin --exclude srv --exclude sys --exclude tmp --exclude '.config/vivaldi' --exclude snap --hidden"))
(ivy-read "Find file in project: "
(split-string (shell-command-to-string fzf-command) "\n"t)
:action (lambda (f)
(find-file (expand-file-name f default-directory))))))
(defunivy-fzf-home ()
"Run a customized `ivy-fzf`-like file selection using `fd` from START-DIRECTORY."
(interactive)
(let ((default-directory"~/")
(fzf-command "fd --hidden --exclude .git --exclude .snapshots --exclude opt --exclude lib --exclude lib64 --exclude mnt --exclude proc --exclude run --exclude sbin --exclude srv --exclude sys --exclude tmp --exclude '.config/vivaldi' --exclude snap --hidden"))
(ivy-read "Find file: " (split-string (shell-command-to-string fzf-command) "\n")
:action (lambda (f)
(find-file (expand-file-name f default-directory))))))
(defunivy-fzf-current-directory ()
"Run a customized `ivy-fzf`-like file selection using `fd` from the current directory."
(interactive)
(let ((fzf-command "fd --hidden --exclude .git --exclude .snapshots --exclude opt --exclude lib --exclude lib64 --exclude mnt --exclude proc --exclude run --exclude sbin --exclude srv --exclude sys --exclude tmp --exclude '.config/vivaldi' --exclude snap --hidden"))
(ivy-read "Find file: " (split-string (shell-command-to-string fzf-command) "\n")
:action (lambda (f)
(find-file (expand-file-name f default-directory))))))
(defunivy-fzf-root ()
"Run a customized `ivy-fzf`-like file selection using `fd` from START-DIRECTORY."
(interactive)
(let ((default-directory"/")
(fzf-command "fd --hidden --exclude .git --exclude .snapshots --exclude opt --exclude lib32 --exclude lib64 --exclude mnt --exclude proc --exclude run --exclude sbin --exclude srv --exclude sys --exclude tmp --exclude '.config/vivaldi' --exclude snap --type f --hidden"))
(ivy-read "Find file: " (split-string (shell-command-to-string fzf-command) "\n")
:action (lambda (f)
(find-file (expand-file-name f default-directory))))))
(defuninsert-path-from-ivy-fzf-home ()
"Insert the path of a file selected by `ivy-fzf` from the home directory into the current buffer."
(interactive)
(let ((default-directory"~/")
(fzf-command "fd --hidden --exclude .git --exclude .snapshots --exclude opt --exclude lib --exclude lib64 --exclude mnt --exclude proc --exclude run --exclude sbin --exclude srv --exclude sys --exclude tmp --exclude '.config/vivaldi' --exclude snap --type f --hidden"))
(ivy-read "Find file: " (split-string (shell-command-to-string fzf-command) "\n")
:action (lambda (f)
(insert (expand-file-name f default-directory))))))
;; (defun insert-path-from-ivy-fzf-project ();; "Insert the path of a file selected by `ivy-fzf` from a project directory into the current buffer.";; (interactive);; (let ((default-directory (projectile-project-root));; (fzf-command "fd --hidden --exclude .git --exclude .snapshots --exclude opt --exclude lib --exclude lib64 --exclude mnt --exclude proc --exclude run --exclude sbin --exclude srv --exclude sys --exclude tmp --exclude '.config/vivaldi' --exclude snap --type f --hidden"));; (ivy-read "Find file: " (split-string (shell-command-to-string fzf-command) "\n");; :action (lambda (f);; (insert (expand-file-name f default-directory))))))
(defuninsert-path-from-ivy-fzf-root ()
"Insert the path of a file selected by `ivy-fzf` from the root directory into the current buffer."
(interactive)
(let ((default-directory"/")
(fzf-command "fd --hidden --exclude .git --exclude .snapshots --exclude opt --exclude lib32 --exclude lib64 --exclude mnt --exclude proc --exclude run --exclude sbin --exclude srv --exclude sys --exclude tmp --exclude '.config/vivaldi' --exclude snap --type f --hidden"))
(ivy-read "Find file: " (split-string (shell-command-to-string fzf-command) "\n")
:action (lambda (f)
(insert (expand-file-name f default-directory))))))
;; (defun counsel-projectile-find-file-or-dir ();; "Use `counsel-find-file` to find a file or directory in the current projectile project.";; (interactive);; (let ((project-root (projectile-project-root)));; (if project-root;; (counsel-find-file project-root);; (message "Not in a projectile project!"))))
;; For some reason doesn't want to load the downloaded package, so i donwloaded it with the macro, commented it out and then just load manually using add-to-list.;; (use-package emacs-crontab-mode;; :vc (:url "https://gitlab.com/Bacaliu/emacs-crontab-mode";; :rev :newest))
(add-to-list'load-path (expand-file-name"emacs-crontab-mode" user-emacs-directory))
;; (require 'tramp);; ;; (setq tramp-direct-async-process t);; ;; (add-to-list 'tramp-connection-properties;; ;; (list (regexp-quote "/ssh:");; ;; "tramp-direct-async-process" t));; (setq tramp-ssh-controlmaster-options (format "-i %s" "~/.ssh/wireguard2.pem"));; (setq tramp-default-method "ssh") ; Make sure SSH is the default method;; (add-to-list 'tramp-default-user-alist '("sudo" "3.71.6.56" "root"));; ;; ;; cache file-name forever;; ;; (setq remote-file-name-inhibit-cache nil);; ;; ;; make sure vc stuff is not making tramp slower;; ;; (setq vc-ignore-dir-regexp;; ;; (format "%s\\|%s";; ;; vc-ignore-dir-regexp;; ;; tramp-file-name-regexp));; (defun my/disable-lockfiles-for-tramp ();; "Disable lockfiles for tramp.";; (when (and buffer-file-name;; (file-remote-p buffer-file-name));; (setq-local create-lockfiles nil)));; (add-hook 'find-file-hook #'my/disable-lockfiles-for-tramp);; (add-hook 'before-save-hook #'my/disable-lockfiles-for-tramp);; (defun extract-local-path-from-tramp-buffer-and-display ();; (interactive);; "Extract the local part of the path from a TRAMP buffer and display it.";; (let* ((tramp-path (buffer-file-name)) ; Get the current buffer's file name;; (path-components (tramp-dissect-file-name tramp-path)) ; Dissect the TRAMP path;; (local-part (tramp-file-name-localname path-components))) ; Extract the local part;; (message "%s" local-part))) ; Display the local part as a message;; (defun tramp-revert ();; "Extract the local part of the path from a TRAMP buffer and attempt to reopen the file.";; (interactive);; (let* ((tramp-path (buffer-file-name)) ; Get the current buffer's file name;; (path-components (tramp-dissect-file-name tramp-path)) ; Dissect the TRAMP path;; (local-part (tramp-file-name-localname path-components))) ; Extract the local part;; ;; Kill the current buffer before attempting to reopen the file;; (kill-current-buffer);; ;; Attempt to reopen the file with the extracted local path;; (find-file local-part)))
Shells and Terminals
Eshell
(use-package eshell
:ensurenil:hook ((eshell-mode. eshell-specific-outline-regexp))
;; (eshell-directory-change . sync-dir-in-buffer-name);; :custom;; (eshell-input-filter 'my-eshell-input-filter):config
(add-to-list'eshell-modules-list'eshell-elecslash)
(define-key eshell-mode-map (kbd"C-s C-o") 'consult-outline))
(setq eshell-history-append t)
(setq eshell-destroy-buffer-when-process-dies t)
(use-package eshell-syntax-highlighting
:ensuret:after esh-mode ;; don't change to 'eshell-mode':config
(eshell-syntax-highlighting-global-mode +1))
(add-hook'eshell-mode-hook'eshell-hist-mode) ; Enable Eshell history mode;; ;;(add-hook 'eshell-mode-hook 'eshell-toggle-direct-send) ;; !!! very careful !!!
(setq eshell-rc-script (concat user-emacs-directory "eshell/eshelrc")
eshell-history-size 100000
eshell-buffer-maximum-lines 5000;; ;; eshell-save-history-on-exit t
eshell-history-file-name "~/.emacs.d/eshell_history";; eshell-hist-ignoredups t;; eshell-scroll-to-bottom-on-input t
eshell-banner-message ""
eshell-visual-commands'("htop""ssh""top""gpg""paru""ngrok"))
(add-hook'eshell-mode-hook
(lambda ()
(setq-local scroll-margin 0)))
(with-eval-after-load'eshell;; Set eshell-save-history-on-exit to nil
(setq eshell-save-history-on-exit nil)
;; Define eshell-append-history function
(defuneshell-append-history ()
"Call `eshell-write-history' with the `append' parameter set to `t'."
(when eshell-history-ring
(let ((newest-cmd-ring (make-ring1)))
(ring-insert newest-cmd-ring (car (ring-elements eshell-history-ring)))
(let ((eshell-history-ring newest-cmd-ring))
(eshell-write-history eshell-history-file-name t)))))
;; Add eshell-append-history to eshell-pre-command-hook
(add-hook'eshell-pre-command-hook#'eshell-append-history))
(defuneshell-insert-last-argument ()
"Insert the last argument of the previous command."
(interactive)
(let* ((last-command (eshell-previous-input-string 0))
(args (split-string-and-unquote last-command))
(last-arg (car (last args))))
(when last-arg
(insert last-arg))))
(defunsetup-eshell-keys ()
(define-key eshell-mode-map (kbd"M-.") 'eshell-insert-last-argument))
;; (define-key eshell-mode-map (kbd "M-r") 'counsel-esh-history))
(add-hook'eshell-mode-hook'setup-eshell-keys)
(defuneshell/edit (filename)
"Open FILENAME in the current buffer, using the current TRAMP address."
(interactive"sEnter the filename to edit: ")
;; Extract the current TRAMP address from the Eshell buffer's default directory
(let ((tramp-address (file-remote-p default-directory)))
(if tramp-address
;; If we're in a TRAMP directory, use the extracted address
(find-file (concat tramp-address filename))
;; If not in a TRAMP directory, fall back to a default address or prompt the user
(message"Not in a TRAMP directory. Please specify the TRAMP address manually.")
;; Optionally, you can add a fallback mechanism here, e.g., prompting the user for a TRAMP address
)))
(defalias'e'eshell/edit)
(require'em-tramp) ; to load eshell’s sudo;; (setq eshell-prefer-lisp-functions t);; (setq eshell-prefer-lisp-variables t);; (setq password-cache t) ; enable password caching;; (setq password-cache-expiry 10);; (add-hook 'eshell-load-hook (lambda () (add-to-list 'eshell-modules-list 'eshell-tramp)))
(defuneshell-clear-buffer ()
"Clear the current Eshell buffer."
(interactive)
(let ((inhibit-read-onlyt))
(erase-buffer)
;; Move to the beginning of the buffer
(goto-char (point-min))
;; Reinsert the prompt at the correct position
(eshell-reset)))
(defuneshell-new ()
"Create a new Eshell buffer with a unique name and open it in the current window."
(interactive)
(let ((eshell-buffer-name (generate-new-buffer-name"*another eshell buffer*")))
(eshell)
(switch-to-buffer eshell-buffer-name)))
(defuneshell-new-pop ()
"Create a new Eshell buffer with a unique name, open it in the current window, and toggle popper type if popper-mode is active."
(interactive)
(let ((eshell-buffer-name (generate-new-buffer-name"*another eshell buffer*")))
(eshell)
(switch-to-buffer eshell-buffer-name)
;; Check if popper-mode is enabled and popper-toggle-type is available
(when (and (featurep'popper) (bound-and-true-p popper-mode))
(popper-toggle-type eshell-buffer-name))))
(defuneshell-pop ()
"Execute the eshell command and launch eshell as a popper buffer"
(interactive)
(eshell)
(popper-toggle-type))
(defuneshell-expand-filename-at-point ()
"Expand the filename at point to its absolute path in eshell."
(interactive)
(let* ((filename (thing-at-point'filenamet))
(expanded (and filename (expand-file-name filename))))
(if expanded
(let ((bounds (bounds-of-thing-at-point'filename)))
(delete-region (car bounds) (cdr bounds))
(insert expanded))
(message"No valid filename at point!"))))
(connection-local-set-profile-variables'remote-trash-directory
'((trash-directory ."/sudo::~/.local/share/Trash")))
(connection-local-set-profiles
`(:application tramp :protocol"sudo":machine,system-name)
'remote-trash-directory)
;; (defun my/select-man-window (&rest _);; "Select the window displaying the man page.";; (let ((man-window (cl-find-if (lambda (window);; (string-match-p "^\\*Man " (buffer-name (window-buffer window))));; (window-list))));; (when man-window;; (select-window man-window))));; (advice-add 'Man-getpage-in-background :after #'my/select-man-window);; (defvar my-eshell-aliases;; '(("mkdir" "/usr/bin/mkdir $*");; ("kill" "/usr/bin/kill $*");; ("grep" "/usr/bin/grep $*"));; ;; ("ls" "/usr/bin/ls $*"));; "A list of Eshell aliases.");; (defun my-eshell-disable-aliases ();; "Disable Eshell aliases defined in `my-eshell-aliases`.";; (dolist (alias my-eshell-aliases);; (setq eshell-command-aliases-list;; (assq-delete-all (car alias) eshell-command-aliases-list))));; (defun my-eshell-enable-aliases ();; "Enable Eshell aliases defined in `my-eshell-aliases`.";; (dolist (alias my-eshell-aliases);; (add-to-list 'eshell-command-aliases-list alias)));; (defun my-eshell-check-remote-directory ();; "Check if the current directory is remote and disable/enable aliases accordingly.";; (if (file-remote-p default-directory);; (my-eshell-disable-aliases);; (my-eshell-enable-aliases)));; (add-hook 'eshell-directory-change-hook 'my-eshell-check-remote-directory);; (add-hook 'eshell-mode-hook 'my-eshell-enable-aliases)
(defuneshell/cat-with-syntax-highlighting (filename)
"Like cat(1) but with syntax highlighting. Stole from aweshell"
(let ((existing-buffer (get-file-buffer filename))
(buffer (find-file-noselect filename)))
(eshell-print
(with-current-buffer buffer
(if (fboundp'font-lock-ensure)
(font-lock-ensure)
(with-no-warnings
(font-lock-fontify-buffer)))
(let ((contents (buffer-string)))
(remove-text-properties0 (length contents) '(read-only nil) contents)
contents)))
(unless existing-buffer
(kill-buffer buffer))
nil))
(advice-add'eshell/cat:override#'eshell/cat-with-syntax-highlighting)
;; (defun sync-dir-in-buffer-name ();; "Update eshell buffer to show directory path.;; Stolen from aweshell.";; (let* ((root (projectile-project-root));; (root-name (projectile-project-name root)));; (if root-name;; (rename-buffer (format "*eshell %s* %s" root-name (s-chop-prefix root default-directory)) t);; (rename-buffer (format "*eshell %s*" default-directory) t))))
(defuneshell-specific-outline-regexp ()
(setq-local outline-regexp eshell-prompt-regexp))
(defuneshell-redirect-to-buffer (buffer)
"Auto create command for redirecting to buffer."
(interactive (list (read-buffer"Redirect to buffer: ")))
(insert (format" >>> #<%s>" buffer)))
;; ;; Useless;; (defun my-eshell-input-filter (input);; "Do not save on the following:;; - empty lines;; - commands that start with a space, `cd`, `ls`/`l`";; (and;; (eshell-input-filter-default input);; (eshell-input-filter-initial-space input);; (not (string-prefix-p "cd " input));; (not (string-prefix-p "ls " input));; (not (string-prefix-p "la " input))))
(defuneshell-outline-ivy ()
"Show Eshell outline candidates using Ivy."
(interactive)
(let* ((buf (current-buffer))
(candidates (with-current-buffer buf
(save-excursion
(goto-char (point-min))
(let ((outline-regexp eshell-prompt-regexp)
(case-fold-searchnil)
candidates)
(while (re-search-forward outline-regexp nilt)
(push (cons (buffer-substring-no-properties
(line-beginning-position)
(line-end-position))
(point))
candidates))
(nreverse candidates))))))
(ivy-read "Eshell outline: "
candidates
:action (lambda (candidate)
(with-current-buffer buf
(goto-char (cdr candidate)))))))
(defunecho-current-line ()
"Echo the entire current line to the echo area."
(interactive)
(message"%s" (buffer-substring-no-properties
(line-beginning-position)
(line-end-position))))
(defunecho-last-word-of-current-line ()
"Echo the last word of the current line to the echo area and return it."
(interactive)
(let* ((line (buffer-substring-no-properties
(line-beginning-position)
(line-end-position)))
(words (split-string line "[ \t\n]+"t))
(last-word (car (last words))))
(message"%s" last-word)
last-word)) ; Return the last word
(defunfind-file-last-word-of-current-line ()
"Open the file named by the last word of the current line.If the file doesn't exist, display an error message."
(interactive)
(let ((last-word (echo-last-word-of-current-line)))
(if (file-exists-p last-word)
(find-file last-word)
(message"File or directory not found: %s" last-word))))
;; Function to get the last 10 recently visited directories
(defunmy-recent-directories ()
"Get a list of the last 10 recently visited directories."
(let ((dirs (delete-dups
(mapcar'file-name-directory recentf-list))))
(seq-filter#'identity
(cl-remove-if-not#'file-directory-p dirs))))
;; Function to prompt user to select a directory and change to it in Eshell
(defunmy-eshell-change-to-recent-directory ()
"Prompt user to select a recent directory and change to it in Eshell."
(interactive)
(let* ((recent-dirs (my-recent-directories))
(selected-dir (completing-read"Choose recent directory: " recent-dirs nilt)))
(when (and selected-dir (file-directory-p selected-dir))
;; Change directory
(eshell/cd selected-dir)
;; Remove the old prompt
(let ((inhibit-read-onlyt))
(save-excursion
(goto-char (point-max))
;; Move to the previous prompt and delete it
(when (re-search-backward eshell-prompt-regexp nilt)
(delete-region (point) (point-max)))))
;; Display the new prompt
(eshell-emit-prompt))))
Custom commands
(defunFD ()
"Display open files for the current Emacs process.If called from eshell, display in eshell. Otherwise, use a separate buffer."
(interactive)
(let* ((pid (number-to-string (emacs-pid)))
(command (concat"ls -l /proc/" pid "/fd"))
(output (shell-command-to-string command)))
(if (eq major-mode 'eshell-mode)
;; In eshell, print directly to the eshell buffer
(eshell-printn output)
;; Outside eshell, use the original behavior
(with-output-to-temp-buffer"*FD Output*"
(princ output))
(switch-to-buffer-other-window"*FD Output*"))))
(defunmy-previous-history-element (arg)
"Insert the previous history element, moving the cursor to the end."
(interactive"p")
(previous-history-element arg)
(move-end-of-line1))
(defunmy-next-history-element (arg)
"Insert the next history element, moving the cursor to the end."
(interactive"p")
(next-history-element arg)
(move-end-of-line1))
Async shell command
;; Execute async shell command on a current file
(defunasync-shell-command-on-file (command)
"Execute COMMAND asynchronously on the current file."
(interactive (list (read-shell-command
(concat"Async shell command on " (buffer-name) ": "))))
(let ((filename (if (equal major-mode 'dired-mode)
default-directory
(buffer-file-name))))
(async-shell-command (concat command "" filename))))
(defunasync-shell-command-filter-hook ()
"Filter async shell command output via `comint-output-filter'."
(when (equal (buffer-name (current-buffer)) "*Async Shell Command*")
;; When `comint-output-filter' is non-nil, the carriage return characters ^M;; are displayed
(setq-local comint-inhibit-carriage-motion nil)
(when-let ((proc (get-buffer-process (current-buffer))))
(set-process-filter proc 'comint-output-filter))))
(with-eval-after-load'shell
(add-hook'shell-mode-hook'async-shell-command-filter-hook))
Cmd
(defunmy-hoogle-search (query)
"Search Hoogle for QUERY."
(interactive"sHoogle search: ") ; Prompt for the search term
(shell-command (concat"hoogle search " (shell-quote-argument query))))
Database
(setq sql-connection-alist
'((default-postgres
(sql-product 'postgres)
(sql-server "localhost")
(sql-port 5432))))
(defunmy/postgres-list-custom-roles ()
"Return a list of custom PostgreSQL roles, including 'postgres' but excluding other system roles."
(let* ((cmd "psql -Atq -c \"SELECT rolname FROM pg_roles WHERE rolname NOT LIKE 'pg_%' OR rolname = 'postgres';\"")
(output (shell-command-to-string cmd)))
(split-string output "\n"t)))
(defunmy/select-postgres-role ()
"Prompt for a PostgreSQL role with completion and return the selected role."
(let* ((roles (my/postgres-list-custom-roles))
(selected-role (completing-read"Select PostgreSQL role: " roles nilt)))
selected-role))
(defunmy/postgres-list-databases-for-role (role)
"Return a list of PostgreSQL databases owned by the given ROLE."
(let* ((cmd (format"psql -Atq -c \"SELECT datname FROM pg_database WHERE datdba = (SELECT oid FROM pg_roles WHERE rolname = '%s');\"" role))
(output (shell-command-to-string cmd)))
(split-string output "\n"t)))
(defunmy/select-postgres-database (role)
"Prompt for a PostgreSQL database owned by ROLE with completion and return the selected database."
(let* ((databases (my/postgres-list-databases-for-role role))
(selected-database (completing-read"Select PostgreSQL database: " databases nilt)))
selected-database))
(defunmy-custom-sql-postgres (roledatabaseserverport)
"Run psql as an inferior process in Emacs, connecting to a database as a specific role."
(interactive"sRole: \nsDatabase: \nsServer: \nsPort: ")
(let ((sql-connection-alist
`((dynamic-postgres
(sql-product 'postgres)
(sql-user ,role)
(sql-database ,database)
(sql-server ,server)
(sql-port ,(string-to-number port))))))
(sql-connect'dynamic-postgres)))
(defunpsql ()
"Prompt for a PostgreSQL role, a database owned by that role, server, and port, then log into sql-interactive-mode."
(interactive)
(let* ((selected-role (my/select-postgres-role))
(selected-database (my/select-postgres-database selected-role))
(selected-server (read-string"Enter SQL Server (default localhost): "nilnil"localhost"))
(selected-port (read-string"Enter SQL Port (default 5432): "nilnil"5432")))
(my-custom-sql-postgres selected-role selected-database selected-server selected-port)))
(defunpsql-session ()
"Open sql buffer with psql shell and a temporary SQL file for LSP support."
(interactive)
(let* ((temp-dir (concat temporary-file-directory "psql-session/")))
;; Ensure the temporary directory exists
(unless (file-directory-p temp-dir)
(make-directory temp-dir t))
(let* ((temp-sql-file (make-temp-file (concat temp-dir "psql-session-") nil".sql"))
(psql-buffer (save-window-excursion
(call-interactively'psql)
(get-buffer sql-buffer)))
(sql-buffer (find-file-noselect temp-sql-file)))
(when (and psql-buffer sql-buffer)
(delete-other-windows)
(switch-to-buffer sql-buffer)
(sql-mode)
;; (lsp) ; Explicitly start LSP
(split-window-below)
(other-window1)
(switch-to-buffer psql-buffer)
(balance-windows)))))
Sessions
;; (setq desktop-restore-eager 10)
(defvarcurrent-desktop-session-namenil"The name of the currently loaded desktop session.")
(defvardesktop-autosave-timernil"Timer object for desktop autosave, to avoid multiple timers running.")
(defunsave-eshell-buffer (desktop-dirname)
;; Save the current working directory.
default-directory)
(defunrestore-eshell-buffer (_file-namebuffer-namemisc)
"MISC is the value returned by `save-eshell-buffer'. _FILE-NAME is nil."
(let ((default-directory misc))
;; Create an eshell buffer named BUFFER-NAME in directory MISC.
(eshell buffer-name)))
;; Save all eshell-mode buffers.
(add-hook'eshell-mode-hook
(lambda ()
(setq-local desktop-save-buffer #'save-eshell-buffer)))
;; Restore all eshell-mode buffers.
(add-to-list'desktop-buffer-mode-handlers '(eshell-mode. restore-eshell-buffer))
(defunsave-current-desktop-session (&optionalshow-message)
"Save the current desktop session using the current session name.If no session is loaded, prompt to create a new one. SHOW-MESSAGE controls whether a save message is displayed."
(interactive"p") ; "p" passes a prefix argument, which is non-nil when called interactively
(if (and current-desktop-session-name (not (string-empty-p current-desktop-session-name)))
(let ((desktop-dir (concat user-emacs-directory "desktop/" current-desktop-session-name "/")))
(unless (file-exists-p desktop-dir)
(make-directory desktop-dir t))
(desktop-save desktop-dir)
(when (and show-message (or (called-interactively-p'any) (eq show-message 1)))
(message"Session '%s' saved." current-desktop-session-name)))
;; No session is loaded or the session name is empty, prompt to create a new one (only when called interactively)
(when (called-interactively-p'any)
(let ((new-session-name (read-string"Enter new session name: ")))
(if (string-empty-p new-session-name)
(message"Session name cannot be empty.")
(progn
(setq current-desktop-session-name new-session-name)
(let ((new-desktop-dir (concat user-emacs-directory "desktop/" new-session-name "/")))
(make-directory new-desktop-dir t)
(desktop-save new-desktop-dir)
(message"Session '%s' created and saved." new-session-name))))))))
(defunsetup-desktop-autosave-timer ()
"Set up or reset the desktop autosave timer."
(when desktop-autosave-timer
(cancel-timer desktop-autosave-timer))
;; Pass nil to save-current-desktop-session to avoid showing the message during autosaves.
(setq desktop-autosave-timer (run-with-timer3030 (lambda () (save-current-desktop-session nil)))))
(defunload-desktop-session (session-name)
"Load a desktop session by name."
(let ((desktop-dir (concat user-emacs-directory "desktop/")))
(setq current-desktop-session-name session-name)
(desktop-change-dir (concat desktop-dir session-name "/"))
(setup-desktop-autosave-timer)))
(defunload-desktop-with-name ()
"Load a desktop session by name, chosen from available sessions."
(interactive)
(when current-desktop-session-name
;; Save the current session before loading a new one, but only if a session is already loaded.
(save-current-desktop-session))
(let* ((desktop-dir (concat user-emacs-directory "desktop/"))
(session-dirs (directory-files desktop-dir nil"^[^.]")) ; List directories excluding hidden ones
(session-name (completing-read"Choose desktop session: " session-dirs nilt)))
(setq current-desktop-session-name session-name) ; Save the session name globally
(desktop-change-dir (concat desktop-dir session-name "/"))
(setup-desktop-autosave-timer)))
;; Disable the default desktop save mode
(desktop-save-mode0)
(setq desktop-files-not-to-save
(concat"\\(^/[^/:]*:\\|(ftp)$\\)\\|" desktop-files-not-to-save))
(defundelete-desktop-session ()
"Delete a desktop session by name, chosen from available sessions."
(interactive)
(let* ((desktop-dir (concat user-emacs-directory "desktop/"))
(session-dirs (directory-files desktop-dir nil"^[^.]")) ; List directories excluding hidden ones
(session-name (completing-read"Choose desktop session to delete: " session-dirs nilt)))
(when (yes-or-no-p (format"Are you sure you want to delete the '%s' session? " session-name))
(let ((session-path (concat desktop-dir session-name)))
(if (file-directory-p session-path)
(progn
(delete-directory session-path t) ; 't' for recursive delete
(message"Deleted desktop session '%s'." session-name))
(message"No such desktop session '%s'." session-name))))))
(defunrename-desktop-session ()
"Renames the currently loaded desktop session."
(interactive)
;; Check if there's a session loaded.
(if (not current-desktop-session-name)
(message"No desktop session is currently loaded.")
(let* ((new-name (read-string"New session name: "))
(old-dir (concat user-emacs-directory "desktop/" current-desktop-session-name))
(new-dir (concat user-emacs-directory "desktop/" new-name)))
;; Check if the new session name is empty or the session already exists.
(if (or (string-empty-p new-name)
(file-exists-p new-dir))
(message"Invalid new session name or session already exists.")
;; Rename the directory and update the session name.
(rename-file old-dir new-dir)
(setq current-desktop-session-name new-name)
(message"Session renamed to '%s'." new-name)))))
(add-hook'kill-emacs-hook'clean-buffer-list)
(add-hook'kill-emacs-hook'save-current-desktop-session)
Restoration by Tab names
(defundocker-tab-exists-p ()
"Check if a tab named 'docker' exists."
(let ((tabs (funcall tab-bar-tabs-function)))
(cl-some (lambda (tab)
(string= (alist-get'name tab) "docker"))
tabs)))
(defuncheck-and-switch-to-docker-tab ()
"Check if a 'docker' tab exists and switch to it if it does."
(interactive)
(if (docker-tab-exists-p)
(progn
(tab-bar-switch-to-tab "docker")
(message"Switched to Docker tab")
(docker-template))
(message"No Docker tab found")))
;; (defun kubernetes-tab-exists-p ();; "Check if a tab named 'kubernetes' exists.";; (let ((tabs (funcall tab-bar-tabs-function)));; (cl-some (lambda (tab);; (string= (alist-get 'name tab) "kubernetes"));; tabs)));; (defun check-and-switch-to-kubernetes-tab ();; "Check if a 'kubernetes tab exists and switch to it if it does.";; (interactive);; (if (kubernetes-tab-exists-p);; (progn;; (tab-bar-switch-to-tab "kubernetes");; (message "Switched to Kubernetes tab");; (kubernetes-overview));; (message "No Kubernetes tab found")));; (add-hook 'desktop-after-read-hook #'check-and-switch-to-kubernetes-tab);; (add-hook 'desktop-after-read-hook #'check-and-switch-to-docker-tab)
(defunmy-shell-mode-hook ()
(setq-local scroll-margin 0))
(add-hook'shell-mode-hook'my-shell-mode-hook)
(setq explicit-shell-file-name "/usr/bin/zsh") ; your shell path here
(setq explicit-bash-args '("--login""-i"))
(defunmy-shell-mode-hook ()
"Custom shell-mode hook to remove the first line of output."
(let ((inhibit-read-onlyt))
(save-excursion
(goto-char (point-min))
(delete-line))))
(add-hook'shell-mode-hook
(lambda ()
(run-with-timer0.1nil'my-shell-mode-hook)))
Eshell buffer
(defvar
eshell-toggle-window-configuration nil"Variable to store the window configuration before opening eshell.")
(defvareshell-toggle-selected-windownil"Variable to store the selected window before opening eshell.")
(defunSpawnEshellSplitBelow ()
"Open a shell in a small split below or toggle it if already open."
(interactive)
(if (eq major-mode 'eshell-mode)
(progn
(when eshell-toggle-window-configuration
(set-window-configuration eshell-toggle-window-configuration)
(setq eshell-toggle-window-configuration nil))
(when eshell-toggle-selected-window
(select-window eshell-toggle-selected-window)
(setq eshell-toggle-selected-window nil)))
(setq eshell-toggle-window-configuration (current-window-configuration))
(setq eshell-toggle-selected-window (selected-window))
;; Calculate one third of the total window height
(let ((one-third-height (/ (window-total-height) 3)))
;; Ensure the height is at least 1 to avoid errors
(setq one-third-height (max one-third-height 1))
(split-window-below (- one-third-height))
(other-window1)
(open-eshell-in-current-directory))))
(defunopen-eshell-in-current-directory ()
"Open eshell in the directory of the current buffer. If an eshell buffer for the directory already exists, switch to it."
(interactive)
(let* ((buffer-dir (if (buffer-file-name)
(file-name-directory (buffer-file-name))
default-directory))
(eshell-buffer-name (concat"*eshell:" buffer-dir "*"))
(existing-eshell-buffer (get-buffer eshell-buffer-name)))
(if existing-eshell-buffer
(switch-to-buffer existing-eshell-buffer)
(let ((eshell-buffer (eshell'N)))
(with-current-buffer eshell-buffer
(rename-buffer eshell-buffer-name)
(eshell/cd buffer-dir))))))
(defunSpawnEshellInProjectRoot ()
"Open eshell in the project's root directory or toggle it if already open."
(interactive)
(if (eq major-mode 'eshell-mode)
(progn
(when eshell-toggle-window-configuration
(set-window-configuration eshell-toggle-window-configuration)
(setq eshell-toggle-window-configuration nil))
(when eshell-toggle-selected-window
(select-window eshell-toggle-selected-window)
(setq eshell-toggle-selected-window nil)))
(setq eshell-toggle-window-configuration (current-window-configuration))
(setq eshell-toggle-selected-window (selected-window))
;; Calculate one third of the total window height
(let ((one-third-height (/ (window-total-height) 3)))
;; Ensure the height is at least 1 to avoid errors
(setq one-third-height (max one-third-height 1))
(split-window-below (- one-third-height))
(other-window1)
(let ((project-root (projectile-project-root)))
(open-eshell-in-directory project-root)))))
(defunopen-eshell-in-directory (dir)
"Open eshell in the specified directory DIR.If an eshell buffer for the directory already exists, switch to it."
(interactive"DDirectory: ")
(let* ((eshell-buffer-name (concat"*eshell:" dir "*"))
(existing-eshell-buffer (get-buffer eshell-buffer-name)))
(if existing-eshell-buffer
(switch-to-buffer existing-eshell-buffer)
(let ((eshell-buffer (eshell'N)))
(with-current-buffer eshell-buffer
(rename-buffer eshell-buffer-name)
(eshell/cd dir))))))
;; Don't set on 'M-p';; (with-eval-after-load 'evil;; (define-key evil-normal-state-map (kbd "M-p") 'SpawnEshellInProjectRoot))
(defunkill-all-eshell-buffers ()
"Kill all Eshell buffers."
(interactive)
(dolist (buffer (buffer-list))
(when (string-match-p"^\\*eshell\\*" (buffer-name buffer))
(kill-buffer buffer))))
(defvarmy-saved-tab-configurations (make-hash-table:test'equal)
"Hash table to store the saved window configurations per tab name.")
(defvarmy-fullscreen-eshell-activenil"Flag to indicate if we're currently in a fullscreen Eshell.")
(defunmy-current-tab-name ()
"Get the current tab's name."
(alist-get'name (tab-bar--current-tab)))
(defunmy-eshell-fullscreen ()
"Replace the current window layout with a fullscreen Eshell for the current tab."
(interactive)
(let* ((tab-name (my-current-tab-name))
(eshell-buffer-name (format"*eshell<%s>*" tab-name)))
(if tab-name
(if my-fullscreen-eshell-active
(message"Already in fullscreen Eshell. Use M-j to restore previous layout.")
(progn
(puthash tab-name (current-window-configuration) my-saved-tab-configurations)
;; (message "Saved window configuration for tab: %s" tab-name)
(delete-other-windows)
;; Switch to or create the Eshell buffer
(if (get-buffer eshell-buffer-name)
(switch-to-buffer eshell-buffer-name)
(progn
(switch-to-buffer (get-buffer-create eshell-buffer-name))
(eshell)))
(setq my-fullscreen-eshell-active t)))
(message"Failed to get tab name. Is the tab-bar-mode enabled?"))))
(defunmy-restore-window-configuration ()
"Restore the previously saved window configuration for the current tab."
(interactive)
(let* ((tab-name (my-current-tab-name))
(config (gethash tab-name my-saved-tab-configurations)))
(if config
(progn
(set-window-configuration config)
(setq my-fullscreen-eshell-active nil))
;; (message "Restored window configuration for tab: %s" tab-name))
(message"No saved window configuration for this tab: %s" tab-name))))
(global-set-key (kbd"M-k") 'my-eshell-fullscreen)
(global-set-key (kbd"M-j") 'my-restore-window-configuration)
(defundisplay-current-tab-name ()
"Display the name of the current tab in tab-bar-mode."
(interactive)
(let ((tab-name (alist-get'name (tab-bar--current-tab))))
(if tab-name
(message"Current tab name: %s" tab-name)
(message"Current tab has no name"))))
Transpose frame
(use-package transpose-frame
:ensuret)
Popper
(defunmy/show-popper-echo-line ()
"Briefly toggle popper to show the echo line."
(interactive)
;; Ensure popper-mode and popper-echo-mode are active
(when (and popper-mode popper-echo-mode)
;; Toggle a popper window and immediately toggle it back
(popper-toggle-latest)
(popper-toggle-latest)))
(use-package popper
:ensuret:bind (("M-`". my/show-popper-echo-line))
;; ("M-f" . popper-toggle));; ("M-~" . popper-cycle)):init
(setq popper-window-height 0.33)
(setq popper-reference-buffers
'("\\*Messages\\*""Output\\*$""\\*Async Shell Command\\*""*Flymake diagnostics.*";; "*Flycheck errors.*""*Python.*""\\* docker container logs .*\\*""\\* docker inspect .*\\*";; "\\*daemons-output for .*\\*""\\*kubernetes logs.*\\*""\\*compilation\\*";; "\\*eshell\\*.*""\\*persistent-shell\\*.*""\\*cider-repl.*""\\*cider-doc.*""\\*cider-error.*";; "\\*helpful.*";; "\\*man.*""\\*grep.*";; "\\*eshell:.*""\\*Warnings\\*";; "\\*xref\\*";; "\\*Backtrace\\*";; "\\*eldoc\\*";; "\\*Ement Notifications\\*";; "Output\\*$";; "\\*Dtache Shell Command\\*";; "\\*mu4e-update\\*";; help-mode
compilation-mode))
(popper-mode +1)
(popper-echo-mode +1))
(use-package shackle
:ensuret:config
(shackle-mode 1))
(defunmy-buffer-is-popper-popup-p ()
"Check if the current buffer is considered a Popper popup."
(and (boundp'popper-popup-status)
(buffer-local-value'popper-popup-status (current-buffer))))
(defunmy-check-current-buffer-popper-status ()
"Print whether the current buffer is a Popper popup."
(interactive)
(if (my-buffer-is-popper-popup-p)
(message"Current buffer IS a Popper popup.")
(message"Current buffer is NOT a Popper popup.")))
;; (define-advice popper-raise-popup (:override (&optional buffer) switch-and-stay);; (when-let ((buf (get-buffer (or buffer (current-buffer)))));; (with-current-buffer buf;; (if (popper-popup-p buf);; (setq popper-popup-status 'raised);; (setq popper-popup-status nil));; (setq mode-line-format (default-value 'mode-line-format)))))
(defadvicepopper-raise-popup (around switch-and-stay (&optional buffer) activate)
"Advice to modify popper-raise-popup behavior."
(when-let ((buf (get-buffer (or buffer (current-buffer)))))
(with-current-buffer buf
(if (popper-popup-p buf)
(setq popper-popup-status 'raised)
(setq popper-popup-status nil))
(setq mode-line-format (default-value'mode-line-format)))))
(defunpopper-toggle-type-original ()
"Run popper-toggle-type with the original behavior by temporarily disabling the advice."
(interactive)
(ad-disable-advice'popper-raise-popup'around'switch-and-stay)
(ad-activate'popper-raise-popup)
(unwind-protect
(call-interactively'popper-toggle-type)
(ad-enable-advice'popper-raise-popup'around'switch-and-stay)
(ad-activate'popper-raise-popup)))
;; (global-set-key (kbd "M-f") 'm-f-toggle-or-forward-word)
(global-set-key (kbd"M-f") 'popper-toggle)
(defunpopper-flymake-diagnostics ()
"Popper window specifically for Flymake diagnostics buffer."
(interactive)
(if (string-match-p"\\*.*Flymake diagnostics.*\\*" (buffer-name))
(popper-toggle)
(flymake-show-buffer-diagnostics)))
(defunpopper-flycheck-diagnostics ()
"Popper window specifically for Flycheck errors buffer."
(interactive)
(if (string-match-p"\\*Flycheck errors\\*" (buffer-name))
(popper-toggle)
(flycheck-list-errors)))
;; (defun fix-cycle ();; (interactive);; (popper-cycle 1));; (defun fix-cycle-backwards ();; (interactive);; (popper-cycle-backwards -1))
;; (use-package flymake;; :ensure t;; :config;; ;; Define a function to enable flymake-mode in dockerfile-mode;; (defun enable-flymake-mode ();; "Enable flymake-mode in dockerfile-mode.";; (if (string-equal major-mode "dockerfile-mode");; (flymake-mode 1)));; (setq flymake-show-diagnostics-at-end-of-line t)
(defunenable-flymake-mode ()
"Enable flymake-mode in dockerfile-mode."
(if (string-equal major-mode "dockerfile-mode")
(flymake-mode1)))
;; ;; Add the hook to enable flymake-mode when entering dockerfile-mode
(add-hook'dockerfile-mode-hook'enable-flymake-mode)
(use-package flymake-hadolint
:ensuret)
(add-hook'dockerfile-mode-hook#'flymake-hadolint-setup)
;; If i need to run hadolint with dockerfile-ts-mode;; (defun my/dockerfile-ts-mode-setup ();; "Setup for dockerfile-ts-mode with flymake-hadolint.";; (message "Running dockerfile-ts-mode setup");; (flymake-hadolint-setup);; (flymake-mode 1));; (add-hook 'dockerfile-mode-hook #'flymake-hadolint-setup);; (add-hook 'dockerfile-ts-mode-hook #'my/dockerfile-ts-mode-setup);; ;; Optional: Ensure flymake is enabled;; (add-hook 'dockerfile-ts-mode-hook 'flymake-mode)
(use-package flymake-shellcheck
:ensuret:commands flymake-shellcheck-load
:init
(add-hook'sh-mode-hook'flymake-shellcheck-load))
Modes
(use-package raku-mode
:ensuret)
(use-package go-mode
:ensuret)
(use-package lua-mode
:ensuret)
(use-package terraform-mode
:ensuret)
(use-package dockerfile-mode
:ensuret)
(use-package haskell-mode
:ensuret)
(use-package yaml-mode
:ensuret)
(use-package nix-mode
:ensuret)
;; (use-package markdown-mode ;; can't be found by the package installer;; :ensure t)
(when (require'dockerfile-modenil'noerror)
;; Add a hook to automatically use dockerfile-mode for Dockerfiles
(add-to-list'auto-mode-alist '("Dockerfile\\'". dockerfile-mode)))
;; yaml-ts doesn't work because of this hook?;; (use-package ansible;; :config;; (add-hook 'yaml-ts-mode-hook '(lambda () (ansible 1))))
(require'compile)
(add-to-list'compilation-error-regexp-alist'yaml)
(add-to-list'compilation-error-regexp-alist-alist
'(yaml "^\\(.*?\\):\\([0-9]+\\)"12)
)
; Replace make -k with ansible-lint, with an UTF-8 locale to avoid crashes
(defunansible-lint-errors ()
(make-local-variable'compile-command)
(let ((ansiblelint_command "ansible-lint ") (loc "LANG=C.UTF-8 "))
(setq compile-command (concat loc ansiblelint_command buffer-file-name)))
)
(add-hook'yaml-ts-mode-hook'ansible-lint-errors)
;; (use-package markdown-mode;; :ensure t;; :mode ("README\\.md\\'" . gfm-mode);; :init (setq markdown-command "multimarkdown");; :bind (:map markdown-mode-map;; ("C-c C-e" . markdown-do)))
(add-to-list'auto-mode-alist '("\\.hs\\'". haskell-mode))
(add-to-list'auto-mode-alist '("\\.hls\\'". haskell-mode))
(add-to-list'auto-mode-alist '("\\.cabal\\'". haskell-cabal-mode))
Flycheck
(defunmy/set-flycheck-faces ()
(with-eval-after-load'flycheck;; Customize Flycheck error face
(set-face-attribute'flycheck-errornil:underline `(:style line :color"#e0def4")) ; rose-pine-gold;; Customize Flycheck warning face
(set-face-attribute'flycheck-warningnil:underline `(:style line :color"#f6c177")) ; rose-pine-gold;; Customize Flycheck info (note) face
(set-face-attribute'flycheck-infonil:underline `(:style line :color"#c4a7e7")))) ; rose-pine-iris
(add-hook'after-init-hook'my/set-flycheck-faces)
;; (use-package tempel;; :ensure t;; :init;; ;; Setup completion at point;; (defun tempel-setup-capf ();; ;; Add the Tempel Capf to `completion-at-point-functions'.;; ;; `tempel-expand' only triggers on exact matches. Alternatively use;; ;; `tempel-complete' if you want to see all matches, but then you;; ;; should also configure `tempel-trigger-prefix', such that Tempel;; ;; does not trigger too often when you don't expect it. NOTE: We add;; ;; `tempel-expand' *before* the main programming mode Capf, such;; ;; that it will be tried first.;; (setq-local completion-at-point-functions;; (cons #'tempel-expand;; completion-at-point-functions)));; (add-hook 'conf-mode-hook 'tempel-setup-capf);; (add-hook 'prog-mode-hook 'tempel-setup-capf);; (add-hook 'text-mode-hook 'tempel-setup-capf);; ;; Optionally make the Tempel templates available to Abbrev,;; ;; either locally or globally. `expand-abbrev' is bound to C-x '.;; ;; (add-hook 'prog-mode-hook #'tempel-abbrev-mode);; ;; (global-tempel-abbrev-mode);; );; (use-package tempel-collection;; :ensure t)
Org Mode
General
(setq org-edit-src-content-indentation 0)
;; (use-package org;; :config;; (setq org-edit-src-content-indentation 0))
(defunorg-insert-top-level-heading ()
"Insert a new top-level heading with two empty lines before it."
(interactive)
(end-of-line)
(insert"\n\n\n* ")
(end-of-line))
(define-key org-mode-map (kbd"M-o M-h") 'org-insert-top-level-heading)
(defuncreate-list-in-region ()
"Convert the highlighted text into a single org-mode list item, properly formatting multiline text."
(interactive)
(if (use-region-p)
(let* ((beg (region-beginning))
(end (region-end))
;; Adjust `end` to exclude the newline at the end of the selection if present.
(end (if (and (> end beg)
(save-excursion
(goto-char end)
(beginning-of-line)
(<= (point) end)))
(progn
(goto-char end)
(backward-char)
(point))
end))
(region-text (buffer-substring beg end))
(lines (split-string region-text "\n")))
(delete-region beg end)
(when lines
(insert (concat"- " (car lines)))
(dolist (line (cdr lines))
(insert (concat"\n" line)))))
(message"No region active")))
Org capture
;; Set the path to your Org notes file
(setq org-default-notes-file "/home/wurfkreuz/.secret_dotfiles/org/notes/quick_notes.org")
(setq org-capture-templates
'(("n""Note" plain (file org-default-notes-file)
"%?\nEntered on %U\n":appendt:empty-lines-before1)))
(defunorg-insert-row-with-floor ()
"Insert a new row with a 'floor' above in an Org mode table."
(interactive)
(org-table-next-field)
(beginning-of-line)
(insert"|-")
(org-table-align)
(org-return))
;; (define-key org-mode-map (kbd "C-c f") 'org-insert-row-with-floor)
(defunFormatToThreshold (char-threshold)
"Formats the selected text to not exceed CHAR-THRESHOLD characters per line."
(interactive"nCharacter Threshold: ")
(let ((start (region-beginning))
(end (region-end))
all-text words formatted-text)
(save-excursion
(setq all-text (buffer-substring start end))
(setq words (split-string all-text))
(let ((current-line"")
(current-length 0))
(dolist (word words)
(if (> (+ current-length (length word) 1) char-threshold)
(progn
(setq formatted-text (concat formatted-text current-line "\n"))
(setq current-line word)
(setq current-length (length word)))
(progn
(setq current-line (if (string="" current-line)
word
(concat current-line "" word)))
(setq current-length (+ current-length (length word) 1)))))
(setq formatted-text (concat formatted-text current-line)))
(delete-region start end)
(goto-char start)
(insert formatted-text))))
(defunmy-org-beginning-of-block ()
"Move to the beginning of the current block and then one line down."
(interactive)
(let ((element (org-element-at-point)))
(when (memq (org-element-type element) '(src-block quote-block example-block center-block special-block))
(goto-char (org-element-property :begin element))
(forward-line)))) ; Added this line to move one line down
(defunmy-org-end-of-block ()
"Move to the end of the current block and then two lines up."
(interactive)
(let ((element (org-element-at-point)))
(when (memq (org-element-type element) '(src-block quote-block example-block center-block special-block))
(goto-char (org-element-property :end element))
(forward-line-3)))) ; Changed -1 to -3 to move two lines up
(defuncopy-buffer-to-new-buffer ()
"Create a copy of the current buffer, placing the contents in a new named buffer."
(interactive)
(let ((content (buffer-string)) ; Get the content of the current buffer
(name (generate-new-buffer-name"BufferCopy"))) ; Generate a new buffer name
(switch-to-buffer name) ; Create and switch to the new buffer
(insert content) ; Insert the original content into the new buffer
(set-buffer-major-mode (other-buffer)) ; Set the major mode based on the original buffer
(message"Buffer copied to %s" name)))
(defunprint-commands-starting-with (input)
"Print all Emacs commands starting with INPUT to a scratch buffer."
(interactive"sInput: ")
(let ((command-list (apropos-internal input 'commandp))
(output-buffer (get-buffer-create"*Commands*")))
(with-current-buffer output-buffer
(erase-buffer)
(insert (format"Commands starting with '%s':\n\n" input))
(dolist (command command-list)
(insert (format"%s\n" command)))
(goto-char (point-min)))
(display-buffer output-buffer)))
;; Increment
(defunmy/increment-number-at-point (&optionalincrement)
"Increment number at point like vim's C-a"
(interactive"p")
(my/change-number-at-point '+ (or increment 2)))
;; Decrement
(defunmy/decrement-number-at-point (&optionalincrement)
"Decrement number at point like vim's C-x"
(interactive"p")
(my/change-number-at-point '- (or increment 1)))
(defunrun-ansible-check-and-lint ()
"Run ansible-lint and ansible-playbook --check on the current file."
(interactive)
(let ((filename (buffer-file-name)))
(if filename
(progn
(async-shell-command (format"ansible-lint %s" filename))
(async-shell-command (format"ansible-playbook --check %s" filename)))
(message"No file associated with this buffer"))))
(defunmy-eshell-snippet-files ()
(interactive)
"Return a list of file names (not directories) in '~/.emacs.d/snippets/eshell-mode/eshell' and print it."
(let* ((snippet-dir (expand-file-name"~/.emacs.d/snippets/eshell-mode/eshell"))
(snippet-files (directory-files snippet-dir tnilnil)))
(setq snippet-files (mapcar'file-name-nondirectory snippet-files))
(setq snippet-files (remove-if (lambda (file) (member file '("."".."))) snippet-files)) ; Remove "." and ".."
(message"Snippet files: %s" snippet-files)
snippet-files))
(defunmy-eshell-current-input ()
(interactive)
"Return the current characters written before the cursor in Eshell and print it."
(let ((input (if (eq major-mode 'eshell-mode)
(buffer-substring-no-properties (line-beginning-position) (point))
"")))
(message"Current input: %s" input)
input)) ; Still return the input for programmatic use if needed
(defunmy-completion-preview-insert ()
"Completes the previewed suggestion and deletes the trailing whitespace."
(interactive)
(completion-preview-insert)
(delete-backward-char1))
(defunscroll-up-and-recenter (arg)
"Scroll up ARG lines and recenter."
(interactive"P")
(scroll-up-command arg)
(recenter))
(defunscroll-down-and-recenter (arg)
"Scroll down ARG lines and recenter."
(interactive"P")
(scroll-down-command arg)
(recenter))
Wrap edit
(defvar-local my-edit-long-lines-region nil"Stores the region (beg . end) that was filled when `my-edit-long-lines-mode` was activated.")
(defunmy-fill-region (begend)
"Fill the region between BEG and END."
(interactive"r")
(fill-region beg end))
(defununfill-region (startend)
"Unfill the region, joining text paragraphs into a single line."
(interactive"r")
(let ((fill-column (point-max)))
(fill-region start end nil)))
(defunwrap-edit-exit ()
"Exit `wrap-edit-mode`, unfill the region, and save the buffer."
(interactive)
(when wrap-edit-region
(unfill-region (car wrap-edit-region) (cdr wrap-edit-region)))
(save-buffer)
(wrap-edit-mode -1))
(global-set-key (kbd"C-c g e") 'wrap-edit-mode)
Custom commands
(defunCp ()
"Copy the full path of the current buffer's file to the clipboard (or appropriate path)."
(interactive)
(let ((path-to-copy nil))
(cond
((eq major-mode 'dired-mode) ; Dired buffer
(setq path-to-copy (if (dired-get-file-for-visit)
(expand-file-name (dired-get-file-for-visit))
(expand-file-name default-directory))))
((eq major-mode 'eshell-mode) ; Eshell buffer
(setq path-to-copy (eshell/pwd)))
(t; Default: Regular File buffer
(setq path-to-copy (buffer-file-name))))
(if path-to-copy
(progn
(kill-new path-to-copy)
(message"Copied path '%s' to the clipboard." path-to-copy))
(message"Current buffer has no associated path to copy.")))) ;
(defunz (q)
"Query zoxide and launch dired or change directory in Eshell."
(interactive"sZoxide: ")
(if-let
((zoxide (executable-find"zoxide"))
(target
(with-temp-buffer
(if (=0 (call-process zoxide niltnil"query" q))
(string-trim (buffer-string))))))
(if (derived-mode-p'eshell-mode)
(eshell/cd target)
(funcall-interactively#'dired target))
(unless zoxide (error"Install zoxide"))
(unless target (error"No Match"))))
;; Creats errors sometimes in emacs launch for some reason;;(defun push ();; "Execute git add, commit, and push in sequence asynchronously.";; (interactive);; ;; Execute 'push' asynchronously and display output in a separate buffer.;; (async-shell-command "push"))
(defunpush-all ()
"Execute git add, commit, and push in sequence asynchronously."
(interactive)
;; Execute 'push' asynchronously and display output in a separate buffer.
(async-shell-command"push -a"))
(defuns ()
"Reload the ~/.zshrc file in the current shell."
(interactive)
(call-process-shell-command"source ~/.zshrc"nil0))
(defunhome ()
"Open a specific file."
(interactive)
(find-file"~/"))
(defunalias ()
"Open a specific file."
(interactive)
(find-file"~/.emacs.d/eshell/alias"))
(defunroot ()
"Open a specific file."
(interactive)
(find-file"/"))
(defuntheme ()
"Open a specific file."
(interactive)
(find-file"~/.emacs.d/themes/rose-pine-theme.el"))
(defuntrash ()
"Open a specific file."
(interactive)
(find-file"~/.local/share/trash"))
(defunngrok ()
"Open a terminal and execute 'ngrok http http://localhost:8080'."
(interactive)
(let ((term-buffer-name "*ngrok-http-8080*"))
;; Check if the buffer already exists
(if (get-buffer term-buffer-name)
;; If it does, switch to it
(switch-to-buffer term-buffer-name)
;; Otherwise, create a new terminal and execute the command
(progn
(ansi-term"/bin/bash""ngrok-http-8080")
(rename-buffer term-buffer-name)
(comint-send-stringnil"ngrok http http://localhost:8080\n")
(popper-toggle-type)))))
(defunbin ()
"Open a specific file."
(interactive)
(find-file"/usr/local/bin"))
(defunbooks ()
"Open a specific file."
(interactive)
(find-file"~/Downloads/books"))
(defunD ()
"Open a specific file."
(interactive)
(find-file"~/Downloads"))
(defunbackup ()
"Open a specific file."
(interactive)
(find-file"~/.backups/"))
(defunbackup ()
"Open a specific file."
(interactive)
(find-file"~/.secret_dotfiles/org/projects"))
(defundot ()
"Open a specific file."
(interactive)
(find-file"~/.dotfiles"))
(defunetc ()
"Open a specific file."
(interactive)
(find-file"/etc"))
(defunsnip ()
"Open a specific file."
(interactive)
(find-file"~/.emacs.d/snippets/"))
;; When i had this function as 'log', i had an unexplained org mode bug.
(defunlogs ()
"Open a specific file."
(interactive)
(find-file"/var/log"))
(defunsource ()
"Open a specific file."
(interactive)
(find-file"~/.source"))
(defuncolors ()
"Open a specific file."
(interactive)
(list-faces-display))
(defuntmp ()
"Open a specific file."
(interactive)
(find-file"/tmp"))
(defunpasswd ()
"Open a specific file."
(interactive)
(find-file"/etc/passwd"))
(defunservice ()
"Open a specific file."
(interactive)
(find-file"/etc/systemd/system"))
(defunadd-execute-permissions-to-current-file ()
"Add execute permissions to the file associated with the current buffer."
(interactive)
(when buffer-file-name
(let ((filename (file-truename buffer-file-name)))
(shell-command (concat"chmod +x " (shell-quote-argument filename)))
(message"Execute permissions added to %s" filename))))
(defunadd-write-permissions-to-current-file ()
"Add execute permissions to the file associated with the current buffer."
(interactive)
(when buffer-file-name
(let ((filename (file-truename buffer-file-name)))
(shell-command (concat"chmod +w " (shell-quote-argument filename)))
(revert-buffer)
(message"Write permissions added to %s" filename))))
(defuncrontab-edit ()
"Run `crontab -e' in a emacs buffer."
(interactive)
(with-editor-async-shell-command "crontab -e"))
(defunsway ()
"Open sway config file."
(interactive)
(find-file (expand-file-name"~/.dotfiles/sway")))
(defunnix ()
"Open sway config file."
(interactive)
(find-file (expand-file-name"~/.dotfiles/nix")))
(defundate ()
"Display the current date and time in the minibuffer using the shell's 'date' command."
(interactive)
(let ((date-output (shell-command-to-string"date")))
(message (string-trim date-output))))
(defunoff ()
"Shutdown the system."
(interactive)
(call-process"poweroff"))
(defuninit ()
"Shutdown the system."
(interactive)
(find-file (expand-file-name"~/.emacs.d/init.el")))
(defunreboot ()
"Reboot the system."
(interactive)
(call-process"reboot"))
(defunnotes ()
"Open org notes directory."
(interactive)
(find-file (expand-file-name"~/.secret_dotfiles/org")))
(defunorg ()
"Open org notes directory."
(interactive)
(find-file (expand-file-name"~/.secret_dotfiles/org")))
(defundrill ()
"Open org notes directory."
(interactive)
(find-file (expand-file-name"~/.secret_dotfiles/org/drill")))
(defuncards ()
"Open org notes directory."
(interactive)
(find-file (expand-file-name"~/.secret_dotfiles/org/drill/general.org")))
(defunnvm ()
"Open org notes directory."
(interactive)
(find-file (expand-file-name"~/.dotfiles/nvim/lua/user/")))
(defunemc ()
"Open a specific file."
(interactive)
(find-file"~/.emacs.d/config.org"))
(defunalc ()
"Open a specific file."
(interactive)
(find-file"~/.dotfiles/zellij/config.kdl"))
(defunzsh ()
"Open a specific file."
(interactive)
(find-file"~/.dotfiles/zsh/.zshrc"))
(defunbsh ()
"Open a specific file."
(interactive)
(find-file"~/.dotfiles/bash/.bashrc"))
(defunscr ()
"Open a specific file."
(interactive)
(find-file"~/.secret_dotfiles"))
(defunssh ()
"Open a specific file."
(interactive)
(find-file"~/.ssh"))
(defunszsh ()
"Open a specific file."
(interactive)
(find-file"~/.secret_dotfiles/zsh/.zshrc"))
(defunscripts ()
"Open a specific file."
(interactive)
(find-file"~/.dotfiles/scripts/"))
(defunsdot ()
"Open a specific file."
(interactive)
(find-file"~/.secret_dotfiles/"))
(defunmanager ()
"Open a specific file."
(interactive)
(find-file"~/.dotfiles/nix/home.nix"))
(defunnix ()
"Open a specific file."
(interactive)
(find-file"/etc/nixos/configuration.nix")
(tramp-revert-buffer-with-sudo))
(defunso ()
"Reload the Emacs configuration."
(interactive)
(load-file"~/.emacs.d/init.el")
(load-file"~/.emacs.d/init.el"))