complete-computing-environment/emacs_shell_mode_is_good_en...

52 lines
2.4 KiB
Org Mode

:PROPERTIES:
:ID: cce/emacs_shell_mode_is_good_enough
:END:
#+TITLE: Emacs Shell-Mode is Good Enough
#+PROPERTY: header-args :mkdirp yes :results none
#+PROPERTY: header-args:emacs-lisp :tangle shell-mode.el
#+PROPERTY: header-args:yaml :tangle roles/endpoint/tasks/shell-mode.yml
#+ARCOLOGY_KEY: cce/shell-mode
#+ARCOLOGY_ALLOW_CRAWL: t
#+ARROYO_EMACS_MODULE: shell-mode
#+ARROYO_MODULE_WANTS: cce/configure_packaging.org
#+ARROYO_HOME_MODULE: hm/shell-helpers.nix
Emacs has Shell Mode, a simple =comint-mode= backed shell that lets me do simple crap that don't need =ncurses= or anything like that. It uses bash and works sanely with pipelines, unlock =eshell= and doesn't eat my keybindings like =ansi-term= and =term=. This mode is, really, good for maybe 95% of the time I need to do interactive terminal work, and it's in fact better than a dedicated terminal emulator like Konsole or =URXVT= -- I can drop to normal mode to copy command output; in fact, hitting enter on any line will send that line as terminal input, so when a command says I used it wrong and demands I try unambiguous things again [[[id:250d219b-e6bc-468f-9b88-b2c572cc036a][Trust Unambiguous Inputs]]], I can copy the suggestion or run it directly.
=shell-mode= displays buffers in a new window when I do =M-x shell= which is almost always *not* what I want, instead opting for them to always appear in the same window as my cursor.
#+BEGIN_SRC emacs-lisp
(add-to-list 'display-buffer-alist
`(,(rx bos "*shell") (display-buffer-same-window)))
#+END_SRC
When in shell-mode, things like =ls= on remote systems expect tabs to be 8 characters unless I configure remote systems differently. Doing it here is easier than trying to clean that shit up and it makes things so much more legible and easy to digest.
#+BEGIN_SRC emacs-lisp
(add-hook 'shell-mode-hook (lambda () (setq-local tab-width 8)))
#+END_SRC
I have a simple command I use in lieu of =watch= for making sure a command succeeds. If there is a flaky download or test suite, I can say =please !!= and bash will reattempt the last command until it succeeds.
#+NAME: please-function
#+BEGIN_SRC shell :tangle bashrc.d/99-commands.sh :mkdirp yes
function please () {
until $@; do sleep 0.5; done
}
#+END_SRC
#+begin_src nix :tangle ~/arroyo-nix/hm/shell-helpers.nix :noweb yes
{ ... }:
{
programs.bash.profileExtra = ''
<<please-function>>
'';
}
#+end_src
#+begin_src emacs-lisp
(provide 'cce/shell-mode)
#+end_src