reddit / emacs

One of the most useful small lisp functions in my config?

Icy_Egg9244 · 2022-01-25 18:34
Today while cleaning my config (instead of working, ha!), I stumbled upon a very short allotment of lisp that has proven very useful for me and wanted to share it; It's a function that allows you to generate functions that have \_run or raise\_ behavior for buffers: (defun make-toggle-function (buffer-name buffer-create-fn &optional switch-cont) "Makes a toggle-function to have raise-or-create behaviour. Creates a toggle-function that executes BUFFER-CREATE-FN if a buffer named BUFFER-NAME doesn't exist, switches to the buffer named BUFFER-NAME if it exists, and switches to the previous buffer if we are currently visiting buffer BUFFER-NAME. The SWITCH-CONT argument is a function which, if given, is called after the buffer has been created or switched to. This allows running further actions that setup the state of the buffer or modify it." (lambda () (interactive) (let ((target-buf (get-buffer buffer-name))) (if target-buf (if (eq (current-buffer) target-buf) (progn (message "switching to other buffer") (switch-to-buffer nil)) (progn (message "switching back...") (switch-to-buffer buffer-name) (when switch-cont (funcall switch-cont)))) (message "creating buffer...") (funcall buffer-create-fn) (when switch-cont (funcall switch-cont)))))) For instance, if you do: (global-set-key (kbd "C-h C-SPC") (make-toggle-function "*scratch*" (lambda ()))) Then a `C-h C-SPC` quickly gets you to the scratch buffer, and a second one dismisses it. The *run* part is useful with something like eshell: ``` (global-set-key (kbd "s-s") (make-toggle-function "*eshell*" (lambda () (progn (eshell) (end-of-buffer))) (lambda () (progn (eshell/cd (default-directory)) ‏‏‎ (end-of-buffer))))) ``` Here, a super-s (I use EXWM so super is always available) gets you to an eshell buffer, creating if it didn't exist, and switches the dir to the cwd. Speaking of EXWM, this is *very* useful to use on your programs in EXWM. For instance I have Firefox bound to one of the Fn keys via a make-toggle-function. That's all! Nothing revolutionary but it has saved me a lot of time and workflow disruption by not fumbling through my buffers ;-)
crawsphi · 2022-01-25 18:51
You might consider using `cond` instead of nested `if`: (let ((target-buf (get-buffer buffer-name))) (cond ((eq (current-buffer) target-buf) (message "switching to other buffer") (switch-to-buffer nil)) ((null target-buf) (message "creating buffer...") (funcall buffer-create-fn) (when switch-cont (funcall switch-cont))) (t (message "switching back...") (switch-to-buffer buffer-name) (when switch-cont (funcall switch-cont))))) Also be aware that `switch-to-buffer` will _create_ a buffer if you give it a name that doesn't currently exist. That might simplify.
a-c-d-w · 2022-01-25 21:00
*I cleaned up and re-formatted your post so I could read it better* --- Today while cleaning my config (instead of working, ha!), I stumbled upon a very short allotment of lisp that has proven very useful for me and wanted to share it; It's a function that allows you to generate functions that have _run or raise_ behavior for buffers: (defun make-toggle-function (buffer-name buffer-create-fn &optional switch-cont) "Makes a toggle-function to have raise-or-create behaviour. Creates a toggle-function that executes BUFFER-CREATE-FN if a buffer named BUFFER-NAME doesn't exist, switches to the buffer named BUFFER-NAME if it exists, and switches to the previous buffer if we are currently visiting buffer BUFFER-NAME. The SWITCH-CONT argument is a function which, if given, is called after the buffer has been created or switched to. This allows running further actions that setup the state of the buffer or modify it." (lambda () (interactive) (let ((target-buf (get-buffer buffer-name))) (if target-buf (if (eq (current-buffer) target-buf) (progn (message "switching to other buffer") (switch-to-buffer nil)) (progn (message "switching back...") (switch-to-buffer buffer-name) (when switch-cont (funcall switch-cont)))) (message "creating buffer...") (funcall buffer-create-fn) (when switch-cont (funcall switch-cont)))))) For instance, if you do: (global-set-key (kbd "C-h C-SPC") (make-toggle-function "scratch" (lambda ()))) Then a C-h C-SPC quickly gets you to the scratch buffer, and a second one dismisses it. The run part is useful with something like eshell: (global-set-key (kbd "s-s") (make-toggle-function "*eshell*" (lambda () (progn (eshell) (end-of-buffer))) (lambda () (progn (eshell/cd (default-directory)) ;;‏‏‎ (end-of-buffer) )))) Here, a super-s (I use EXWM so super is always available) gets you to an eshell buffer, creating if it didn't exist, and switches the dir to the cwd. Speaking of EXWM, this is very useful to use on your programs in EXWM. For instance I have Firefox bound to one of the Fn keys via a make-toggle-function. That's all! Nothing revolutionary but it has saved me a lot of time and workflow disruption by not fumbling through my buffers ;-)
arthurno1 · 2022-01-27 07:22
https://github.com/amno1/emacs-term-toggle/blob/master/term-toggle.el
deaddyfreddy · 2022-01-27 07:43
and here we go again https://github.com/4DA/eshell-toggle