2021-11-09 00:02:13 +00:00
#+TITLE : General Programming Configuration
#+AUTHOR : Howard X. Abrams
#+DATE : 2020-10-26
A literate programming file for helping me program.
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp :exports none
2022-03-09 18:45:37 +00:00
;;; general-programming --- Configuration for general languages. -*- lexical-binding: t; -* -
;;
;; © 2020-2022 Howard X. Abrams
2022-06-18 00:25:47 +00:00
;; Licensed under a Creative Commons Attribution 4.0 International License.
2022-03-09 18:45:37 +00:00
;; See http://creativecommons.org/licenses/by/4.0/
;;
;; Author: Howard X. Abrams <http://gitlab.com/howardabrams >
;; Maintainer: Howard X. Abrams
;; Created: October 26, 2020
;;
;; This file is not part of GNU Emacs.
;;
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
;; ~/other/hamacs/general-programming.org
;; And tangle the file to recreate this one.
;;
;;; Code:
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-09 00:02:13 +00:00
* Introduction
2022-06-18 00:25:47 +00:00
Seems that all programming interfaces and workflows behave similarly. One other helper routine is a =general= macro for org-mode files:
#+begin_src emacs-lisp
2021-11-24 00:34:48 +00:00
(general-create-definer ha-prog-leader
2021-12-08 21:57:42 +00:00
:states '(normal visual motion)
:keymaps 'prog-mode-map
2021-12-14 19:26:11 +00:00
:prefix "SPC m"
:global-prefix "<f17 >"
2021-12-14 19:42:26 +00:00
:non-normal-prefix "S-SPC")
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-09 00:02:13 +00:00
* General
The following work for all programming languages.
2022-08-09 17:49:13 +00:00
** Markdown
All the READMEs and other documentation use [[https://jblevins.org/projects/markdown-mode/ ][markdown-mode ]].
#+begin_src emacs-lisp
(use-package markdown-mode
:mode ("README\\.md\\'" . gfm-mode)
:init (setq markdown-command "multimarkdown")
:general
(:states 'normal :no-autoload t :keymaps 'markdown-mode-map
"SPC m l" '("insert link" . markdown-insert-link)
;; SPC u 3 SPC m h for a third-level header:
"SPC m h" '("insert header" . markdown-insert-header-dwim)
"SPC m e" '("export" . markdown-export)
"SPC m p" '("preview" . markdown-export-and-preview)))
#+end_src
Note that the markdown-specific commands use the ~C-c C-c~ and ~C-c C-s~ prefixes.
2021-11-09 00:02:13 +00:00
** direnv
Farm off commands into /virtual environments/ :
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2021-11-18 16:17:20 +00:00
(use-package direnv
:init
2022-02-26 01:12:18 +00:00
(setq direnv--executable "/usr/local/bin/direnv"
direnv-always-show-summary t
direnv-show-paths-in-summary t)
2021-11-18 16:17:20 +00:00
:config
(direnv-mode))
2022-06-18 00:25:47 +00:00
#+end_src
2021-12-29 19:09:43 +00:00
** Spell Checking Comments
2022-06-16 18:17:54 +00:00
The [[https://www.emacswiki.org/emacs/FlySpell#h5o-2 ][flyspell-prog-mode ]] checks for misspellings in comments.
2021-12-29 19:09:43 +00:00
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2021-12-29 19:09:43 +00:00
(use-package flyspell
:hook (prog-mode . flyspell-prog-mode))
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-09 06:01:19 +00:00
** Flycheck
2022-06-16 18:17:54 +00:00
Why use [[https://www.flycheck.org/ ][flycheck ]] over the built-in =flymake= ? Speed used to be the advantage, but I’ m now pushing much of this to LSP, so speed is less of an issue. What about when I am not using LSP? Also, since I’ ve hooked grammar checkers, I need this with global keybindings.
2022-02-26 01:12:18 +00:00
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-02-26 01:12:18 +00:00
(use-package flycheck
2022-04-09 16:07:47 +00:00
:init
(setq next-error-message-highlight t)
2022-02-26 01:12:18 +00:00
:bind (:map flycheck-error-list-mode-map
("C-n" . 'flycheck-error-list-next-error)
("C-p" . 'flycheck-error-list-previous-error)
("j" . 'flycheck-error-list-next-error)
("k" . 'flycheck-error-list-previous-error))
:config
(flymake-mode -1)
(global-flycheck-mode)
(ha-leader "t c" 'flycheck-mode)
2022-03-09 06:01:19 +00:00
(ha-leader
2022-02-26 01:12:18 +00:00
">" '("next problem" . flycheck-next-error)
"<" '("previous problem" . flycheck-previous-error)
2022-03-09 06:01:19 +00:00
"P" '(:ignore t :which-key "problems")
"P b" '("error buffer" . flycheck-buffer)
"P c" '("clear" . flycheck-clear)
"P n" '("next" . flycheck-next-error)
2022-06-16 18:17:54 +00:00
"P N" '("next" . flycheck-next-error)
2022-03-09 06:01:19 +00:00
"P p" '("previous" . flycheck-previous-error)
2022-06-16 18:17:54 +00:00
"P P" '("previous" . flycheck-previous-error)
2022-03-09 06:01:19 +00:00
"P l" '("list all" . flycheck-list-errors)
"P y" '("copy errors" . flycheck-copy-errors-as-kill)
"P s" '("select checker" . flycheck-select-checker)
"P ?" '("describe checker" . flycheck-describe-checker)
"P h" '("display error" . flycheck-display-error-at-point)
"P e" '("explain error" . flycheck-explain-error-at-point)
"P H" '("help" . display-local-help)
"P i" '("manual" . flycheck-manual)
"P V" '("version" . flycheck-version)
"P v" '("verify-setup" . flycheck-verify-setup)
"P x" '("disable-checker" . flycheck-disable-checker)
"P t" '("toggle flycheck" . flycheck-mode)))
2022-06-18 00:25:47 +00:00
#+end_src
2022-02-23 18:58:49 +00:00
** Documentation
2022-06-16 18:17:54 +00:00
I’ ve used the [[http://kapeli.com/ ][Dash ]] API Documentation browser (an external application) with Emacs, available for Mac.
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp :tangle no
2022-02-23 18:58:49 +00:00
(use-package dash-at-point
:commands (dash-at-point)
2022-05-16 20:34:05 +00:00
:general (:states 'normal "gD" 'dash-at-point))
2022-06-18 00:25:47 +00:00
#+end_src
2022-06-16 18:17:54 +00:00
I’ m interested in using [[https://devdocs.io/ ][devdocs ]] instead, which is similar, but keeps it all /inside/ Emacs (and works on my Linux system). Two Emacs projects compete for this position. The Emacs [[https://github.com/astoff/devdocs.el ][devdocs ]] project is active, and seems to work well. Its advantage is a special mode for moving around the documentation.
2022-02-23 18:58:49 +00:00
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-02-23 18:58:49 +00:00
(use-package devdocs
2022-02-25 22:55:17 +00:00
:after evil
2022-05-16 20:34:05 +00:00
:general (:states 'normal "gD" 'devdocs-lookup)
2022-02-23 18:58:49 +00:00
2022-05-16 20:34:05 +00:00
:config
2022-02-23 18:58:49 +00:00
(ha-prog-leader
"d" '(:ignore t :which-key "docs")
"d d" '("open" . devdocs-lookup)
"d p" '("peruse" . devdocs-peruse)
"d i" '("install" . devdocs-install)
"d u" '("update" . devdocs-update-all)
"d x" '("uninstall" . devdocs-delete)
"d s" '("search" . devdocs-search)))
2022-06-18 00:25:47 +00:00
#+end_src
2022-02-23 18:58:49 +00:00
The [[https://github.com/blahgeek/emacs-devdocs-browser ][devdocs-browser ]] project acts similar, but with slightly different command names. Its advantage is that it allows for downloading docs and having it available offline, in fact, you can’ t search for a function, until you download its pack. This is slightly faster because of this.
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp :tangle no
2022-02-23 18:58:49 +00:00
(use-package devdocs-browser
2022-05-16 20:34:05 +00:00
:general (:states 'normal "gD" 'devdocs-browser-open)
2022-02-23 18:58:49 +00:00
2022-05-16 20:34:05 +00:00
:config
2022-02-23 18:58:49 +00:00
(ha-prog-leader
"d" '(:ignore t :which-key "docs")
"d d" '("open" . devdocs-browser-open)
"d D" '("open in" . devdocs-browser-open-in)
"d l" '("list" . devdocs-browser-list-docs)
"d u" '("update" . devdocs-browser-update-docs)
"d i" '("install" . devdocs-browser-install-doc)
"d x" '("uninstall" . devdocs-browser-uninstall-doc)
"d U" '("upgrade" . devdocs-browser-upgrade-doc)
"d o" '("download" . devdocs-browser-download-offline-data)
"d O" '("remove download" . devdocs-browser-remove-offline-data)))
2022-06-18 00:25:47 +00:00
#+end_src
2022-05-20 03:35:30 +00:00
** Code Folding
2022-06-18 00:25:47 +00:00
While Emacs has options for viewing and moving around code, sometimes, we could /collapse/ all functions, and then start to expand them one at a time. For this, we could enable the built-in [[https://www.emacswiki.org/emacs/HideShow ][hide-show feature ]]:
#+begin_src emacs-lisp :tangle no
2022-05-20 03:35:30 +00:00
(use-package hide-show
:straight (:type built-in)
:init
(setq hs-hide-comments t
hs-hide-initial-comment-block t
hs-isearch-open t)
:hook (prog-mode . hs-minor-mode))
2022-06-18 00:25:47 +00:00
#+end_src
Note that =hide-show= doesn’ t work with complex YAML files. The [[https://github.com/gregsexton/origami.el ][origami ]] mode works better /out-of-the-box/ , as it works with Python and Lisp, but falls back to indents as the format, which works well.
#+begin_src emacs-lisp
2022-05-20 03:35:30 +00:00
(use-package origami
:init
(setq origami-fold-replacement "⤵")
:hook (prog-mode . origami-mode))
2022-06-18 00:25:47 +00:00
#+end_src
2022-05-20 03:35:30 +00:00
To take advantage of this, type:
- ~z m~ :: To collapse everything
- ~z r~ :: To open everything
- ~z o~ :: To open a particular section
- ~z c~ :: To collapse a /section/ (like a function)
- ~z a~ :: Toggles open to close
Note: Yes, we could use [[https://github.com/mrkkrp/vimish-fold ][vimish-fold ]] (and its cousin, [[https://github.com/alexmurray/evil-vimish-fold ][evil-vimish-fold ]]) and we’ ll see if I need those.
2021-11-18 16:17:20 +00:00
** Language Server Protocol (LSP) Integration
2022-03-09 06:01:19 +00:00
The [[https://microsoft.github.io/language-server-protocol/ ][LSP ]] is a way to connect /editors/ (like Emacs) to /languages/ (like Lisp)… wait, no, it was originally designed for VS Code and probably Python, but we now abstract away [[https://github.com/davidhalter/jedi ][Jedi ]] and the [[http://tkf.github.io/emacs-jedi/latest/ ][Emacs integration to Jedi ]] (and duplicate everything for Ruby, and Clojure, and…).
2021-11-18 16:17:20 +00:00
Instead, we install [[https://emacs-lsp.github.io/lsp-mode/ ][LSP Mode ]] (and friends), which simplifies my configuration:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2021-11-18 16:17:20 +00:00
(use-package lsp-mode
2022-02-26 01:12:18 +00:00
:commands lsp
2021-11-18 16:17:20 +00:00
:init
;; Let's make lsp-doctor happy with these settings:
(setq gc-cons-threshold (* 100 1024 1024)
read-process-output-max (* 1024 1024)
company-idle-delay 0.0 ; Are thing fast enough to do this?
lsp-keymap-prefix "s-m")
2022-02-26 01:12:18 +00:00
:hook ((lsp-mode . lsp-enable-which-key-integration)))
2022-06-18 00:25:47 +00:00
#+end_src
2022-02-26 01:12:18 +00:00
I will want to start adding commands under my =SPC m= mode-specific key sequence leader, but in the meantime, all LSP-related keybindings are available under ~⌘-m~ . See [[https://emacs-lsp.github.io/lsp-mode/page/keybindings/ ][this page ]] for the default keybindings.
*** UI
2021-11-18 16:17:20 +00:00
The [[https://github.com/emacs-lsp/lsp-ui ][lsp-ui ]] project offers much of the display and interface to LSP:
2022-02-26 01:12:18 +00:00
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2021-11-18 16:17:20 +00:00
(use-package lsp-ui
:commands lsp-ui-mode
:config
(setq lsp-ui-sideline-ignore-duplicate t
2022-02-26 01:12:18 +00:00
lsp-ui-sideline-show-hover t
2021-11-18 16:17:20 +00:00
lsp-ui-sideline-show-diagnostics t)
2022-02-26 01:12:18 +00:00
:hook (lsp-mode . lsp-ui-mode))
2022-06-18 00:25:47 +00:00
#+end_src
2022-02-26 01:12:18 +00:00
*** Company Completion
2021-11-18 16:17:20 +00:00
The [[https://github.com/tigersoldier/company-lsp ][company-lsp ]] offers a [[http://company-mode.github.io/ ][company ]] completion backend for [[https://github.com/emacs-lsp/lsp-mode ][lsp-mode ]]:
2022-02-26 01:12:18 +00:00
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2021-11-18 16:17:20 +00:00
(use-package company-lsp
:config
(push 'company-lsp company-backends))
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-18 16:17:20 +00:00
To options that might be interesting:
- =company-lsp-async= : When set to non-nil, fetch completion candidates asynchronously.
- =company-lsp-enable-snippet= : Set it to non-nil if you want to enable snippet expansion on completion. Set it to nil to disable this feature.
2022-02-26 01:12:18 +00:00
*** iMenu
The [[https://github.com/emacs-lsp/lsp-ui/blob/master/lsp-ui-imenu.el ][lsp-imenu ]] project offers a =lsp-ui-imenu= function for jumping to functions:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2021-11-18 16:17:20 +00:00
(use-package lsp-ui-imenu
:straight nil
:after lsp-ui
:config
2022-02-26 01:12:18 +00:00
(ha-prog-leader
"g" '(:ignore t :which-key "goto")
"g m" '("imenu" . lsp-ui-imenu))
2021-11-18 16:17:20 +00:00
(add-hook 'lsp-after-open-hook 'lsp-enable-imenu))
2022-06-18 00:25:47 +00:00
#+end_src
2022-02-26 01:12:18 +00:00
*** Treemacs
The [[https://github.com/emacs-lsp/lsp-treemacs ][lsp-treemacs ]] offers a project-specific structure oriented to the code:
2021-11-18 16:17:20 +00:00
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-02-26 01:12:18 +00:00
(use-package lsp-treemacs
:config
(ha-prog-leader
"0" '("treemacs" . lsp-treemacs-symbols)))
2022-06-18 00:25:47 +00:00
#+end_src
2022-03-09 06:01:19 +00:00
*** Origami Folding
The [[https://github.com/emacs-lsp/lsp-origami ][lsp-origami ]] project integrates the [[https://github.com/gregsexton/origami.el ][origami ]] project with LSP for /better code folding/ :
2022-02-26 01:12:18 +00:00
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-03-09 06:01:19 +00:00
(use-package lsp-origami
:hook (lsp-after-open . lsp-origami-try-enable))
2022-06-18 00:25:47 +00:00
#+end_src
2022-02-26 01:12:18 +00:00
*** Debugging
2021-11-18 16:17:20 +00:00
Do we want to use a debugger?
2022-02-26 01:12:18 +00:00
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp :tangle no
2022-02-26 01:12:18 +00:00
(use-package dap-mode
:init
(require 'dap-python))
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-09 00:02:13 +00:00
** Function Call Notifications
As I've mentioned [[http://www.howardism.org/Technical/Emacs/beep-for-emacs.html ][on my website ]], I've created a [[file:~/website/Technical/Emacs/beep-for-emacs.org ][beep function ]] that notifies when long running processes complete.
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2021-12-27 17:34:03 +00:00
(use-package alert
:init
(setq alert-default-style
(if (ha-running-on-macos?)
'osx-notifier
'libnotify)))
2021-11-09 16:21:08 +00:00
(use-package beep
2021-12-27 17:34:03 +00:00
:straight nil ; Already in the load-path
:hook (after-init . (lambda () (beep--when-finished "Emacs has started")))
:config
(dolist (func '(org-publish
org-publish-all
org-publish-project
compile
shell-command))
(advice-add func :around #'beep-when-runs-too-long)))
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-09 00:02:13 +00:00
While that code /advices/ the publishing and compile commands, I may want to add more.
** iEdit
2021-12-30 02:51:25 +00:00
While there are language-specific ways to rename variables and functions, [[https://github.com/victorhge/iedit ][iedit ]] is often sufficient.
2022-03-03 23:19:31 +00:00
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-03-03 23:19:31 +00:00
(use-package iedit
:config
(ha-leader "s e" '("iedit" . iedit-mode)))
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-09 00:02:13 +00:00
** Commenting
I like =comment-dwim= (~M-;~ ), and I like =comment-box= , but I have an odd personal style that I like to codify:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2021-11-09 00:02:13 +00:00
(defun ha-comment-line (&optional start end)
(interactive "r")
(when (or (null start) (not (region-active-p)))
(setq start (line-beginning-position))
(setq end (line-end-position)))
(save-excursion
(narrow-to-region start end)
(upcase-region start end)
(goto-char (point-min))
(insert "------------------------------------------------------------------------\n")
(goto-char (point-max))
(insert "\n------------------------------------------------------------------------")
(comment-region (point-min) (point-max))
(widen)))
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-09 00:02:13 +00:00
And a keybinding:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2021-11-24 00:34:48 +00:00
(ha-prog-leader "c" '("comment line" . ha-comment-line))
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-09 00:02:13 +00:00
** Evaluation
2022-05-11 17:53:20 +00:00
While I like [[help:eval-print-last-sexp ][eval-print-last-sexp ]], I would like a bit of formatting in order to /keep the results/ in the file.
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-05-11 17:53:20 +00:00
(defun ha-eval-print-last-sexp (&optional internal-arg)
"Evaluate the expression located before the point.
The results are inserted back into the buffer at the end
of the line after a comment."
(interactive)
(save-excursion
(eval-print-last-sexp internal-arg))
(end-of-line)
(insert " ")
(insert comment-start)
(insert "⟹ ")
(dotimes (i 2)
(next-line)
(join-line)))
2022-06-18 00:25:47 +00:00
#+end_src
2022-05-11 17:53:20 +00:00
2021-11-09 00:02:13 +00:00
Typical keybindings for all programming modes:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2021-11-24 00:34:48 +00:00
(ha-prog-leader
2021-11-09 00:02:13 +00:00
"e" '(:ignore t :which-key "eval")
"e ;" '("expression" . eval-expression)
"e b" '("buffer" . eval-buffer)
"e f" '("function" . eval-defun)
"e r" '("region" . eval-region)
"e e" '("last s-exp" . eval-last-sexp)
2022-05-11 17:53:20 +00:00
"e p" '("print s-exp" . ha-eval-print-last-sexp))
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-09 00:02:13 +00:00
** Ligatures
2022-04-19 04:55:55 +00:00
The idea of using math symbols for a programming languages keywords is /cute/ , but can be confusing, so I use it sparingly:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-05-11 19:39:14 +00:00
(defun ha-prettify-prog ()
2022-05-11 17:53:20 +00:00
"Extends the `prettify-symbols-alist' for programming."
2022-05-11 19:39:14 +00:00
(mapc (lambda (pair) (push pair prettify-symbols-alist))
2022-05-11 17:53:20 +00:00
'(("lambda" . "𝝀")
(">=" . "≥")
("<=" . "≤")
("!=" . "≠")))
(prettify-symbols-mode))
(add-hook 'prog-mode-hook 'ha-prettify-prog)
2022-06-18 00:25:47 +00:00
#+end_src
2022-05-11 19:39:14 +00:00
Eventually, I want to follow [[https://www.masteringemacs.org/article/unicode-ligatures-color-emoji ][Mickey Petersen's essay ]] on getting full ligatures working, but right now, they don’ t work on the Mac, and that is my current workhorse.
2021-11-09 00:02:13 +00:00
** Task Runner
I've replaced my home-grown compilation list code with a more versatile [[https://github.com/emacs-taskrunner/emacs-taskrunner ][Taskrunner project ]].
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp :tangle no
2021-11-09 00:02:13 +00:00
(setq ivy-taskrunner-notifications-on t
ivy-taskrunner-doit-bin-path "/usr/local/bin/doit")
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-09 00:02:13 +00:00
Doom provides basic support, but we need more keybindings:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp :tangle no
2021-11-09 00:02:13 +00:00
(map! :leader :prefix "p"
:desc "Project tasks" "Z" 'ivy-taskrunner
:desc "Reun last task" "z" 'ivy-taskrunner-rerun-last-command)
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-09 00:02:13 +00:00
While my company is typically using =Rakefile= and =Makefile= in the top-level project, I want to have my personal tasks set per-project as well. For that, I thought about using [[https://pydoit.org/ ][doit ]], where I would just create a =dodo.py= file that contains:
2022-06-18 00:25:47 +00:00
#+begin_src python :tangle no
2021-11-09 00:02:13 +00:00
def hello():
"""This command greets you."""
return {
'actions': [ 'echo hello' ],
}
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-09 00:02:13 +00:00
** Display Configuration
Using the [[https://github.com/seagle0128/doom-modeline ][Doom Modeline ]] to add notifications:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-04-01 18:29:45 +00:00
(use-package doom-modeline
:config
(setq doom-modeline-lsp t
doom-modeline-env-version t))
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-09 00:02:13 +00:00
* Languages
2022-03-09 06:01:19 +00:00
Simple to configure languages go here. More advanced stuff will go in their own files… eventually.
2022-04-12 04:04:41 +00:00
** Ansible
2021-11-09 00:02:13 +00:00
Doing a lot of [[https://github.com/yoshiki/yaml-mode ][YAML work ]], but this project needs a new maintainer.
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2021-11-09 00:02:13 +00:00
(use-package yaml-mode
2022-04-12 04:04:41 +00:00
:mode (rx ".y" (optional "a") "ml" string-end))
2022-06-18 00:25:47 +00:00
#+end_src
2021-12-16 19:35:10 +00:00
2021-11-09 00:02:13 +00:00
Ansible uses Jinja, so we install the [[https://github.com/paradoxxxzero/jinja2-mode ][jinja2-mode ]]:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2021-11-09 00:02:13 +00:00
(use-package jinja2-mode
2022-04-12 04:04:41 +00:00
:mode (rx ".j2" string-end))
2022-06-18 00:25:47 +00:00
#+end_src
2022-04-12 04:04:41 +00:00
Do I consider all YAML files an Ansible file needing [[https://github.com/k1LoW/emacs-ansible ][ansible-mode ]]?
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-04-12 04:04:41 +00:00
(use-package ansible
2022-04-12 17:42:01 +00:00
:init
(setq ansible-vault-password-file "~/.ansible-vault-passfile")
2022-04-12 04:04:41 +00:00
;; :hook (yaml-mode . ansible-mode)
:config
(ha-leader "t y" 'ansible))
2022-06-18 00:25:47 +00:00
#+end_src
2022-04-12 17:42:01 +00:00
The [[help:ansible-vault-password-file ][ansible-vault-password-file ]] variable needs to change /per project/ , so let’ s use the =.dir-locals.el= file, for instance:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp :tangle no
2022-04-12 17:42:01 +00:00
((nil . ((ansible-vault-password-file . "playbooks/.vault-password"))))
2022-06-18 00:25:47 +00:00
#+end_src
2022-04-12 04:04:41 +00:00
2022-04-12 17:42:01 +00:00
However, let’ s have all YAML files able to access Ansible’ s documentation using the [[https://github.com/emacsorphanage/ansible-doc ][ansible-doc ]] project:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-04-12 04:04:41 +00:00
(use-package ansible-doc
:hook (yaml-mode . ansible-doc-mode)
:config
(ha-local-leader :keymaps 'yaml-mode-map
"d" '(:ignore t :which-key "docs")
"d d" 'ansible-doc))
2022-06-18 00:25:47 +00:00
#+end_src
2022-04-12 04:04:41 +00:00
The [[https://github.com/emacsmirror/poly-ansible ][poly-ansible ]] project uses [[https://polymode.github.io/ ][polymode ]], gluing [[https://github.com/paradoxxxzero/jinja2-mode ][jinja2-mode ]] into [[https://github.com/yoshiki/yaml-mode ][yaml-mode ]].
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2022-05-20 03:35:30 +00:00
(use-package polymode)
(use-package poly-ansible
:after polymode
:straight (:host github :repo "emacsmirror/poly-ansible")
:hook ((yaml-mode . poly-ansible-mode)
(poly-ansible-mode . font-lock-update)))
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-09 00:02:13 +00:00
** Shell Scripts
While I don't like writing them, I can't get away from them.
While filename extensions work fine most of the time, I don't like to pre-pend =.sh= to the few shell scripts I write, and instead, would like to associate =shell-mode= with all files in a =bin= directory:
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2021-11-09 00:02:13 +00:00
(use-package sh-mode
2021-11-14 06:18:19 +00:00
:straight (:type built-in)
2021-11-09 00:02:13 +00:00
:mode (rx (or (seq ".sh" eol)
"/bin/ "))
2021-11-12 21:05:31 +00:00
:config
(ha-auto-insert-file (rx (or (seq ".sh" eol)
"/bin/ ")) "sh-mode.sh")
2021-11-09 00:02:13 +00:00
:hook
(after-save . executable-make-buffer-file-executable-if-script-p))
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-09 00:02:13 +00:00
*Note:* we make the script /executable/ by default. See [[https://emacsredux.com/blog/2021/09/29/make-script-files-executable-automatically/ ][this essay ]] for details, but it appears that the executable bit is only turned on if the script has a shebang at the top of the file.
2021-11-10 01:20:36 +00:00
** Fish Shell
2022-06-18 00:25:47 +00:00
#+begin_src emacs-lisp
2021-11-12 21:05:31 +00:00
(use-package fish-mode
:mode (rx ".fish" eol)
:config
2021-11-14 06:14:55 +00:00
(ha-auto-insert-file (rx ".fish") "fish-mode.sh")
2021-11-12 21:05:31 +00:00
:hook
(fish-mode . (lambda () (add-hook 'before-save-hook 'fish_indent-before-save))))
2022-06-18 00:25:47 +00:00
#+end_src
2021-11-09 00:02:13 +00:00
* Technical Artifacts :noexport:
2022-06-18 00:25:47 +00:00
Provide a name to =require= this code.
#+begin_src emacs-lisp :exports none
(provide 'ha-programming)
;;; ha-programming.el ends here
#+end_src
2021-11-09 00:02:13 +00:00
Before you can build this on a new system, make sure that you put the cursor over any of these properties, and hit: ~C-c C-c~
#+DESCRIPTION : A literate programming file for helping me program.
#+PROPERTY : header-args:sh :tangle no
#+PROPERTY : header-args:emacs-lisp yes
#+PROPERTY : header-args :results none :eval no-export :comments no mkdirp yes
#+OPTIONS : num:nil toc:nil todo:nil tasks:nil tags:nil date:nil
#+OPTIONS : skip:nil author:nil email:nil creator:nil timestamp:nil
#+INFOJS_OPT : view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js