Compare commits
10 commits
2cf9421c22
...
b162327c7d
Author | SHA1 | Date | |
---|---|---|---|
|
b162327c7d | ||
|
c2009b56ec | ||
|
67cbe9883e | ||
|
3042ffe460 | ||
|
85a7613f69 | ||
|
24d13c1a07 | ||
|
f1fa3742a0 | ||
|
285bf2d86c | ||
|
086725397a | ||
|
bcb28ef821 |
20 changed files with 221 additions and 129 deletions
|
@ -141,7 +141,7 @@ And let’s see the results:
|
|||
** My Code Location
|
||||
Much of my more complicated code comes from my website essays and other projects. The destination shows up here:
|
||||
#+begin_src emacs-lisp
|
||||
(add-to-list 'load-path (expand-file-name "~/.emacs.d/elisp"))
|
||||
(add-to-list 'load-path (expand-file-name "elisp" user-emacs-directory))
|
||||
#+end_src
|
||||
|
||||
Hopefully, this will tie me over while I transition.
|
||||
|
@ -227,12 +227,12 @@ With this function, we can test/debug/reload any individual file, via:
|
|||
"Load or reload an org-mode FILE containing literate
|
||||
Emacs configuration code."
|
||||
(interactive (list (completing-read "Org file: "
|
||||
(ha-hamacs-files :all))))
|
||||
(ha-hamacs-files :all))))
|
||||
;; TODO: Replace concat here:
|
||||
(let ((full-file (file-name-concat hamacs-source-dir file)))
|
||||
(when (file-exists-p full-file)
|
||||
(ignore-errors
|
||||
(org-babel-load-file full-file)))))
|
||||
(ignore-errors
|
||||
(org-babel-load-file full-file)))))
|
||||
#+end_src
|
||||
|
||||
** Tangling the Hamacs
|
||||
|
|
|
@ -22,6 +22,11 @@ A literate programming file for configuring Emacs.
|
|||
;; ~/other/hamacs/ha-config.org
|
||||
;; Using `find-file-at-point', and tangle the file to recreate this.
|
||||
;;
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; Basic configuration of Emacs. Should be executed early in the
|
||||
;; loading sequence.
|
||||
;;
|
||||
;;; Code:
|
||||
#+end_src
|
||||
* Basic Configuration
|
||||
|
@ -59,6 +64,7 @@ Emacs has some new code to display line-numbers, and the =visual= value works we
|
|||
But sometimes we want to jump to /absolute/ line numbers, so I have a toggling function:
|
||||
#+begin_src emacs-lisp
|
||||
(defun ha-toggle-relative-line-numbers ()
|
||||
"Change line numbering from relative to visual to off."
|
||||
(interactive)
|
||||
(cond
|
||||
((null display-line-numbers) (display-line-numbers-mode))
|
||||
|
@ -120,14 +126,13 @@ I’ve often called =imenu= to easily jump to a function definition in a file (o
|
|||
(imenu-add-menubar-index)
|
||||
(setq-local imenu-auto-rescan t)
|
||||
(when (derived-mode-p 'prog-mode)
|
||||
(setq-local imenu-sort-function #'imenu--sort-by-name))))
|
||||
(setq-local imenu-sort-function 'imenu--sort-by-name))))
|
||||
|
||||
(add-hook 'org-mode-hook 'ha-imenu-setup)
|
||||
(add-hook 'markdown-mode-hook 'ha-imenu-setup)
|
||||
(add-hook 'prog-mode-hook 'ha-imenu-setup)
|
||||
(add-hook 'makefile-mode-hook 'ha-imenu-setup)
|
||||
#+end_src
|
||||
|
||||
** File Access
|
||||
*** Remote Files
|
||||
To speed up TRAMP access, let’s disabled lock files, you know, the ones that have the =#= surrounding characters:
|
||||
|
@ -139,7 +144,8 @@ What do I think about [[elisp:(describe-variable 'remote-file-name-inhibit-auto-
|
|||
During remote access, TRAMP can slow down performing Git operations. Let’s turn that off as well:
|
||||
#+begin_src emacs-lisp
|
||||
(defun turn-off-vc-for-remote-files ()
|
||||
"Disable"
|
||||
"Disable version control for remote files.
|
||||
Use with the `find-file-hook'."
|
||||
(when (file-remote-p (buffer-file-name))
|
||||
(setq-local vc-handled-backends nil)))
|
||||
|
||||
|
@ -200,10 +206,11 @@ The [[help:version-control][version-control]] variable affect backups (not some
|
|||
Save the file whenever I move away from Emacs (see [[https://irreal.org/blog/?p=10314][this essay]]):
|
||||
#+begin_src emacs-lisp
|
||||
(defun save-all-buffers ()
|
||||
"Saves all buffers, because, why not?"
|
||||
"Save all buffers, because, why not?"
|
||||
(interactive)
|
||||
(save-some-buffers t))
|
||||
|
||||
;; See 'after-focus-change -hook?
|
||||
(add-hook 'focus-out-hook 'save-all-buffers)
|
||||
#+end_src
|
||||
*** Download Files via URL
|
||||
|
@ -357,7 +364,7 @@ Since I seldom remember keybindings, or even function names, for major-modes, I
|
|||
#+begin_src emacs-lisp
|
||||
(use-package major-mode-hydra
|
||||
:config
|
||||
(global-set-key (kbd "s-,") #'major-mode-hydra)
|
||||
(global-set-key (kbd "s-,") 'major-mode-hydra)
|
||||
|
||||
(setq major-mode-hydra-title-generator
|
||||
'(lambda (mode)
|
||||
|
@ -478,14 +485,17 @@ Using [[https://github.com/joaotavora/yasnippet][yasnippet]] to expand templates
|
|||
(expand-file-name "snippets" user-emacs-directory))
|
||||
(yas-global-mode +1))
|
||||
#+end_src
|
||||
|
||||
Check out [[http://joaotavora.github.io/yasnippet/][the documentation]] for writing them.
|
||||
|
||||
Since I have troubles installing Doom’s [[https://github.com/hlissner/doom-snippets][collection of snippets]], lets use the [[http://github.com/AndreaCrotti/yasnippet-snippets][yasnippet-snippets]] package:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package yasnippet-snippets)
|
||||
#+end_src
|
||||
*** Auto Insert Templates
|
||||
The [[https://www.emacswiki.org/emacs/AutoInsertMode][auto-insert]] feature is a wee bit complicated. All I want is to associate a filename regular expression with a YASnippet template. I'm stealing some ideas from Henrik Lissner's [[https://github.com/hlissner/doom-emacs/blob/develop/modules/editor/file-templates/autoload.el][set-file-template!]] macro, but simpler?
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package autoinsert
|
||||
:init
|
||||
|
@ -500,20 +510,20 @@ Since auto insertion requires entering data for particular fields, and for that
|
|||
#+begin_src emacs-lisp
|
||||
(defun ha-autoinsert-yas-expand()
|
||||
"Replace text in yasnippet template."
|
||||
(let ((orig-mode major-mode)
|
||||
(auto-insert-query nil)
|
||||
(let ((auto-insert-query nil)
|
||||
(yas-indent-line nil))
|
||||
(yas/minor-mode 1)
|
||||
(yas-minor-mode +1)
|
||||
(when (fboundp 'evil-insert-state)
|
||||
(evil-insert-state))
|
||||
(yas-expand-snippet (buffer-string) (point-min) (point-max))))
|
||||
#+end_src
|
||||
|
||||
And since I'll be associating snippets with new files all over my configuration, let's make a helper function:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(defun ha-auto-insert-file (filename-re snippet-name)
|
||||
"Autofill file buffer matching FILENAME-RE regular expression.
|
||||
The contents inserted from the YAS SNIPPET-NAME."
|
||||
The contents inserted from the YAS SNIPPET-NAME."
|
||||
;; The define-auto-insert takes a regular expression and an ACTION:
|
||||
;; ACTION may also be a vector containing successive single actions.
|
||||
(define-auto-insert filename-re
|
||||
|
@ -523,7 +533,7 @@ And since I'll be associating snippets with new files all over my configuration,
|
|||
As an example of its use, any Org files loaded in /this project/ should insert my config file:
|
||||
#+begin_src emacs-lisp
|
||||
(ha-auto-insert-file (rx "hamacs/" (one-or-more any) ".org" eol) "hamacs-config")
|
||||
(ha-auto-insert-file (rx ".dir-locals.el") "dir-locals.el")
|
||||
(ha-auto-insert-file (rx ".dir-locals.el") "dir-locals")
|
||||
#+end_src
|
||||
** Additional Global Packages
|
||||
*** Function Call Notifications
|
||||
|
@ -626,6 +636,8 @@ If you hit the following keys /before/ you select a target, you get special acti
|
|||
- ~i~ :: =ispell= … fix spelling from a distance.
|
||||
- ~z~ :: =zap-to-char= … kill from current point to the target
|
||||
I’m not thinking of ideas of what would be useful, e.g. ~v~ to highlight from cursor to target, etc.
|
||||
|
||||
Want to know something amazing. In a Terminal, like =vterm= or =eshell=, I run ~s-g~ and pinpoint the UUID in the output of a long command. Then type ~y~ and then ~C-y~ to paste that ID without even moving the mouse.
|
||||
**** Link Hint, the Link Jumper
|
||||
The [[info:emacs#Goto Address mode][Goto Address]] mode (see this [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Goto-Address-mode.html][online link]]) turns URLs into clickable links. Nice feature and built into Emacs, but it requires using the mouse or moving to the URL and hitting ~Return~ (if you like this idea, check out [[https://xenodium.com/actionable-urls-in-emacs-buffers/][Álvaro Ramírez's configuration]] for this).
|
||||
|
||||
|
@ -650,6 +662,7 @@ Can I open a link in another window? The idea with this is that I can select a l
|
|||
|
||||
#+begin_src emacs-lisp
|
||||
(defun link-hint-open-link-ace-window ()
|
||||
"Select link via avy, and open link in other window."
|
||||
(interactive)
|
||||
(link-hint-copy-link)
|
||||
(ace-select-window)
|
||||
|
@ -683,7 +696,7 @@ I like ~C-a~ to go to the beginning of the line, but what about getting to the b
|
|||
|
||||
#+begin_src emacs-lisp
|
||||
(defun ha-beginning-of-line (&optional n)
|
||||
"Toggles between the beginning of line and first of text."
|
||||
"Toggle between the beginning of line and first of text."
|
||||
(interactive "^p")
|
||||
(if (= (point) (line-beginning-position))
|
||||
(beginning-of-line-text n)
|
||||
|
@ -731,8 +744,8 @@ To do this, we need a way to generate a string of the perspectives in alphabetic
|
|||
|
||||
#+begin_src emacs-lisp
|
||||
(defun ha--persp-label (num names)
|
||||
"Return string of numbered elements. NUM is the starting
|
||||
number and NAMES is a list of strings."
|
||||
"Return string of numbered elements.
|
||||
NUM is the starting number and NAMES is a list of strings."
|
||||
(when names
|
||||
(concat
|
||||
(format " %d: %s%s" ; Shame that the following doesn't work:
|
||||
|
@ -779,7 +792,7 @@ Build the hydra as well as configure the =perspective= project.
|
|||
("9" (persp-switch-by-number 9))
|
||||
("0" (persp-switch-by-number 0))
|
||||
("n" ha-project-persp)
|
||||
("N" ha-new-persp)
|
||||
("N" persp-switch)
|
||||
("]" persp-next :color pink)
|
||||
("[" persp-prev :color pink)
|
||||
("d" persp-kill)
|
||||
|
@ -857,7 +870,7 @@ Given a list of information about project-workspaces, can we create them all?
|
|||
|
||||
(defun ha-workspace-initialize (&optional projects)
|
||||
"Precreate workspace projects from a PROJECTS list.
|
||||
Each entry in the list is a list containing:
|
||||
Each entry in the list is a list containing:
|
||||
- name (as a string)
|
||||
- project root directory
|
||||
- a optional list of files to display"
|
||||
|
@ -866,7 +879,7 @@ Given a list of information about project-workspaces, can we create them all?
|
|||
(setq projects ha-workspace-projects-personal))
|
||||
|
||||
(dolist (project projects)
|
||||
(-let (((name root files) project))
|
||||
(seq-let (name root files) project
|
||||
(unless (ha-persp-exists? name)
|
||||
(message "Creating workspace: %s (from %s)" name root)
|
||||
(ha-project-persp root name files))))
|
||||
|
@ -888,23 +901,19 @@ Often, but not always, I want a perspective based on an actual Git repository, e
|
|||
(setq name (f-filename project)))
|
||||
(persp-switch name)
|
||||
|
||||
;; Unclear if the following is actually necessary.
|
||||
(ignore-errors
|
||||
(project-remember-project root)
|
||||
(project-switch-project root))
|
||||
|
||||
(let ((recent-files (thread-last recentf-list
|
||||
(--filter (s-starts-with? project it))
|
||||
(-take 3)))
|
||||
(readme-org (f-join project "README.org"))
|
||||
(readme-org (f-join project "README.md"))
|
||||
(readme-md (f-join project "README.rst")))
|
||||
(readme-md (f-join project "README.md"))
|
||||
(readme-rst (f-join project "README.rst")))
|
||||
(cond
|
||||
(files (ha--project-show-files project files))
|
||||
(recent-files (ha--project-show-files project recent-files))
|
||||
((f-exists? readme-org) (find-file readme-org))
|
||||
((f-exists? readme-md) (find-file readme-md))
|
||||
(t (dirvish project))))))
|
||||
((f-exists? readme-rst) (find-file readme-rst))
|
||||
(t (dired project))))))
|
||||
#+end_src
|
||||
|
||||
When starting a new perspective, and I specify more than one file, this function splits the window horizontally for each file.
|
||||
|
@ -925,16 +934,6 @@ When starting a new perspective, and I specify more than one file, this function
|
|||
(ha--project-show-files root more)))))
|
||||
#+end_src
|
||||
|
||||
The =persp-switch= allows me to select or create a new project, but what if we insisted on a new workspace?
|
||||
#+begin_src emacs-lisp
|
||||
(defun ha-new-persp (name)
|
||||
(interactive "sNew Workspace: ")
|
||||
(persp-switch name)
|
||||
(cond
|
||||
((s-ends-with? "mail" name) (notmuch))
|
||||
((s-starts-with? "twit" name) (twit))))
|
||||
#+end_src
|
||||
Once we create the new perspective workspace, if it matches a particular name, I pretty much know what function I would like to call.
|
||||
* Pretty Good Encryption
|
||||
For details on using GnuPG in Emacs, see Mickey Petersen’s [[https://www.masteringemacs.org/article/keeping-secrets-in-emacs-gnupg-auth-sources][GnuPG Essay]].
|
||||
|
||||
|
|
|
@ -384,10 +384,12 @@ Oh, and turn off the line highlighting:
|
|||
(global-hl-line-mode -1)
|
||||
#+end_src
|
||||
|
||||
And of course, the default is /inside/ where it is dark and safe:
|
||||
And of course, the default is /inside/ where it is dark and safe. Let’s also wait til the world settles down before calling this.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(laptop-inside)
|
||||
(progn
|
||||
(sit-for 2)
|
||||
(laptop-inside))
|
||||
#+end_src
|
||||
** Highlight Task Labels
|
||||
In code, if you drop a specific /text/ labels, we can highlight them with [[https://github.com/tarsius/hl-todo][hl-todo package]]:
|
||||
|
|
100
ha-eshell.org
100
ha-eshell.org
|
@ -97,11 +97,24 @@ In short, use parens to limit the files, for instance:
|
|||
ls *.sh(*) # List shell scripts that are executable
|
||||
ls *(/) # List directories (recursively)
|
||||
#+end_src
|
||||
|
||||
And parens with a colon character transform the filename, useful with =for=:
|
||||
|
||||
#+begin_src sh
|
||||
for F in *.org(:r) { mv $F.org $F.el }
|
||||
#+end_src
|
||||
|
||||
Keep in mind that the predicates are somewhat finicky. For instance, the following doesn’t work:
|
||||
#+begin_src sh
|
||||
mv $f $f(:r).txt
|
||||
#+end_src
|
||||
|
||||
But you could call this:
|
||||
|
||||
#+begin_src sh
|
||||
mv $f $f(:s/org$/txt/)
|
||||
#+end_src
|
||||
|
||||
The =T= predicate filter allows me to limit file results that have internal =org-mode= tags.
|
||||
#+begin_src sh
|
||||
$ ls *.org(T'org')
|
||||
|
@ -193,7 +206,40 @@ I have also had a lot of trouble getting aliases to work, for instance =dired= w
|
|||
alias less view-file $1
|
||||
alias d dired $1
|
||||
#+end_src
|
||||
To work around this, I create functions instead.
|
||||
|
||||
To work around this, I create functions instead. For instance …
|
||||
|
||||
The =basename= shell command strips off a parent, and can strip off the extension. However, you have to specify the extension. Why not take advantage of Emacs’ =file-name-base= to strip it off without needing to specify it.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(defalias 'eshell/base 'file-name-base)
|
||||
#+end_src
|
||||
|
||||
However, the following doesn’t work as expected:
|
||||
|
||||
#+begin_example
|
||||
$ set f some-file.org # usually this is from a 'for' loop
|
||||
$ mv $f {base $f}.txt
|
||||
#+end_example
|
||||
|
||||
While the sequence ={base $f}= works, the =.txt= without a space screws it up, creating a list. So I create this simple function:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(defun eshell/newbase (file newbase)
|
||||
(unless (string-match (rx bos ".") newbase)
|
||||
(setq newbase (concat "." newbase)))
|
||||
(concat (file-name-base file) newbase))
|
||||
#+end_src
|
||||
|
||||
Which works as expected:
|
||||
|
||||
#+begin_example
|
||||
$ echo {newbase $f txt}
|
||||
some-file.txt
|
||||
#+end_example
|
||||
|
||||
A better approach, however, is to take advantage of [[*Predicate Filters and Modifiers][modifiers]].
|
||||
|
||||
* Eshell Functions
|
||||
Any function that begins with =eshell/= is available as a command (with the remaining letters). For instance:
|
||||
#+begin_src emacs-lisp
|
||||
|
@ -394,15 +440,41 @@ Let’s make some test examples:
|
|||
(should (bufferp (second parms))))))
|
||||
#+end_src
|
||||
** Setting Variables
|
||||
To set a variable in Eshell, you use good ol’ =setq=, but that would create global variables. We can make a version for Eshell, that makes buffer-local variables.
|
||||
To set a variable in Eshell, you use good ol’ =setq=, but that would create global variables. We can make a version for Eshell, that makes buffer-local variables. While we are at it, let’s set it as environment variables too. Then everyone can pick it up:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(defun eshell/set (&rest args)
|
||||
"Creates a buffer local variables."
|
||||
(dolist (arg-pair (seq-partition args 2))
|
||||
(seq-let (var val) arg-pair
|
||||
(let ((var-sym (make-symbol var)))
|
||||
(set (make-local-variable var-sym) val)))))
|
||||
"Creates a buffer local variable.
|
||||
The first parameters of ARGS is the name of the variable.
|
||||
The other parameters are the values. If not given, the
|
||||
variable is deleted."
|
||||
(let* ((var (car args))
|
||||
(var-sym (make-symbol var))
|
||||
;; Convert value to a string
|
||||
(val (pcase (seq-length (cdr args))
|
||||
(0 nil)
|
||||
(1 (format "%s" (cadr args)))
|
||||
(_ (thread-last (cdr args)
|
||||
(seq-map 'eshell-stringify)
|
||||
(s-join " "))))))
|
||||
(if val
|
||||
(progn
|
||||
(set (make-local-variable var-sym) val)
|
||||
(setenv var val))
|
||||
|
||||
;; If we don't get both a variable and a value, let's try to
|
||||
;; delete the variable:
|
||||
(makunbound var-sym)
|
||||
(setenv var))))
|
||||
#+end_src
|
||||
|
||||
Something like:
|
||||
|
||||
#+begin_example
|
||||
$ set a 42 b 7
|
||||
#+end_example
|
||||
|
||||
Would create a single variable, =a=, set to the value of the string, =42 b 7= which is similar to how the Fish shell works.
|
||||
** Less and More
|
||||
While I can type =find-file=, I often use =e= as an alias for =emacsclient= in Terminals, so let’s do something similar for =eshell=:
|
||||
Also note that we can take advantage of the =eshell-fn-on-files= function to expand the [[help:find-file][find-file]] (which takes one argument), to open more than one file at one time.
|
||||
|
@ -1248,7 +1320,7 @@ And finally, add our new functions to [[elisp(describe-variable 'eshell-virtual-
|
|||
* EAT and Eshell
|
||||
The [[https://codeberg.org/akib/emacs-eat][Emulate a Terminal]] project provides flicker-free, perfect display, of visual commands in Eshell, eliminating one of my primary issue with using Eshell all the time. (Check out Akib Azmain Turja’s [[https://emacsconf.org/2023/talks/eat/][talk at EmacsConf2023]]).
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
#+begin_src emacs-lisp :tangle no
|
||||
(use-package eat
|
||||
:after eshell
|
||||
:straight (:repo "https://codeberg.org/akib/emacs-eat")
|
||||
|
@ -1651,14 +1723,10 @@ Sometimes you need to change something about the current file you are editing...
|
|||
chmod a+x
|
||||
|
||||
Works as expected. We replace the special variable `$$' with the
|
||||
filename of the buffer. Note that `eshell-command' executes this
|
||||
command, so eshell modifiers are available, for instance:
|
||||
filename of the buffer. So:
|
||||
|
||||
mv $$ $$(:r).txt
|
||||
|
||||
Will rename the current file to now have a .txt extension.
|
||||
See `eshell-display-modifier-help' for details on that."
|
||||
(interactive "sExecute command on File Buffer: ")
|
||||
mv $$ `basename $$`.txt"
|
||||
(interactive (list (read-shell-command "Execute command on File Buffer: ")))
|
||||
(let* ((file-name (buffer-file-name))
|
||||
(full-cmd (cond ((string-match (rx "$$") cmd)
|
||||
(replace-regexp-in-string (rx "$$") file-name cmd))
|
||||
|
@ -1667,7 +1735,7 @@ Sometimes you need to change something about the current file you are editing...
|
|||
(t
|
||||
(concat cmd " " file-name)))))
|
||||
(message "Executing: %s" full-cmd)
|
||||
(eshell-command full-cmd)))
|
||||
(shell-command full-cmd)))
|
||||
#+end_src
|
||||
* Configuration
|
||||
Here is where we associate all the functions and their hooks with =eshell=, through the magic of =use-package=.
|
||||
|
|
|
@ -849,6 +849,7 @@ Unfilling a paragraph joins all the lines in a paragraph into a single line. Tak
|
|||
* Help Operations
|
||||
While the ~C-h~ is easy enough, I am now in the habit of typing ~SPC h~ instead.
|
||||
Since I tweaked the help menu, I craft my own menu:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(ha-leader
|
||||
"h" '(:ignore t :which-key "help")
|
||||
|
@ -881,6 +882,11 @@ Since I tweaked the help menu, I craft my own menu:
|
|||
"h C-g" '(keyboard-escape-quit :which-key t))
|
||||
#+end_src
|
||||
|
||||
Some of these call the [[file:ha-programming-elisp.org::*Helpful Functions][Helpful]] package:
|
||||
#+begin_src emacs-lisp
|
||||
(use-package helpful)
|
||||
#+end_src
|
||||
|
||||
Remember these keys in the *Help* buffer:
|
||||
- ~s~ :: view source of the function
|
||||
- ~i~ :: view info manual of the function
|
||||
|
|
|
@ -58,7 +58,7 @@ In normal Org file, I like large headers, but in my Journal, where each task is
|
|||
But new files could use /my formatting/ (which is different than the options available in the project):
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(ha-auto-insert-file (rx "journal/" (zero-or-more any) (= 8 digit)) "journal")
|
||||
(ha-auto-insert-file (rx "journal/" (zero-or-more any) (= 8 digit)) "journal")
|
||||
#+end_src
|
||||
|
||||
This depends on the following [[file:~/.doom.d/snippets/org-journal-mode/__journal][snippet/template file]]:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#+author: Howard Abrams
|
||||
#+date: 2024-07-07
|
||||
#+filetags: emacs hamacs
|
||||
#+lastmod: [2024-07-25 Thu]
|
||||
#+lastmod: [2024-07-26 Fri]
|
||||
|
||||
A literate programming file for literate programming in Emacs Org Files.
|
||||
|
||||
|
@ -210,7 +210,7 @@ This helper function does the work of calling =ripgrep=, parsing its output, and
|
|||
(seq-filter 'identity))))
|
||||
#+end_src
|
||||
|
||||
Note: the =processor= function creates an =xref= object, described below. See =ha-literate—process-rg-line=.
|
||||
Note: the =processor= function creates an =xref= object, described below. See =ha-literate--process-rg-line=.
|
||||
|
||||
The output from =ripgrep= goes through a couple of transformation functions listed here:
|
||||
|
||||
|
@ -406,10 +406,10 @@ To finish the connections, we need to create a /hook/ that I only allow to turn
|
|||
|
||||
#+begin_src emacs-lisp
|
||||
(defun ha-literate-xref-activate ()
|
||||
"Function to activate org-based literate backend.
|
||||
Add this function to `xref-backend-functions' hook. "
|
||||
(when (eq major-mode 'org-mode)
|
||||
'org-babel))
|
||||
"Function to activate org-based literate backend.
|
||||
Add this function to `xref-backend-functions' hook. "
|
||||
(when (eq major-mode 'org-mode)
|
||||
'org-babel))
|
||||
|
||||
(add-hook 'xref-backend-functions #'ha-literate-xref-activate)
|
||||
#+end_src
|
||||
|
|
23
ha-org.org
23
ha-org.org
|
@ -3,7 +3,7 @@
|
|||
#+date: 2020-09-18
|
||||
#+tags: emacs org
|
||||
#+startup: inlineimages
|
||||
#+lastmod: [2024-06-02 Sun]
|
||||
#+lastmod: [2024-08-08 Thu]
|
||||
|
||||
A literate programming file for configuring org-mode and those files.
|
||||
|
||||
|
@ -547,8 +547,10 @@ Not sure if anyone has made a /package/, so we need to download and build locall
|
|||
#+end_src
|
||||
|
||||
Of course, since we are dealing with Emacs, any good idea will be assimilated. Johann Klähn created [[https://github.com/kljohann/pikchr-mode][pikchr-mode]]:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package pikchr-mode
|
||||
:straight (:local-repo "~/other/pikchr-mode")
|
||||
:custom
|
||||
(pikchr-executable "~/bin/pikchr"))
|
||||
#+end_src
|
||||
|
@ -696,7 +698,7 @@ Bindings specific to org files:
|
|||
Limit the number of exporters to the ones that I would use:
|
||||
#+name: ox-exporters
|
||||
#+begin_src emacs-lisp
|
||||
(setq org-export-backends '(ascii html icalendar md odt))
|
||||
(setq org-export-backends '(ascii html md texinfo odt))
|
||||
#+end_src
|
||||
|
||||
I have a special version of tweaked [[file:elisp/ox-confluence.el][Confluence exporter]] for my org files:
|
||||
|
@ -711,15 +713,16 @@ I have a special version of tweaked [[file:elisp/ox-confluence.el][Confluence ex
|
|||
|
||||
And Graphviz configuration using [[https://github.com/ppareit/graphviz-dot-mode][graphviz-dot-mode]]:
|
||||
#+begin_src emacs-lisp
|
||||
(use-package graphviz-dot-mode
|
||||
:mode "\\.dot\\'"
|
||||
:init
|
||||
(setq tab-width 4
|
||||
graphviz-dot-indent-width 2
|
||||
graphviz-dot-auto-indent-on-newline t
|
||||
graphviz-dot-auto-indent-on-braces t
|
||||
graphviz-dot-auto-indent-on-semi t))
|
||||
(use-package graphviz-dot-mode
|
||||
:mode "\\.dot\\'"
|
||||
:init
|
||||
(setq tab-width 4
|
||||
graphviz-dot-indent-width 2
|
||||
graphviz-dot-auto-indent-on-newline t
|
||||
graphviz-dot-auto-indent-on-braces t
|
||||
graphviz-dot-auto-indent-on-semi t))
|
||||
#+end_src
|
||||
|
||||
*** HTML Style
|
||||
|
||||
I’m not afraid of HTML, but I like the idea of doing my HTML work in a Lisp-like way using the [[https://github.com/tonyaldon/jack][jack-html project]]:
|
||||
|
|
|
@ -33,25 +33,25 @@ Moving by lines is our default navigation mode, but for Yaml and Python, that do
|
|||
|
||||
The obvious keybindings are ~M-h/j/k/l~ … but that is used … well, somewhat. In org files, this is a way to move the outline of subtrees around. Useful, and =spatial-navigate= wouldn’t be helpful in org files anyway.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package spatial-navigate
|
||||
:straight (:repo "https://codeberg.org/ideasman42/emacs-spatial-navigate")
|
||||
:config
|
||||
(pretty-hydra-define spatial-navigate (:color amaranth :quit-key "q")
|
||||
("Box"
|
||||
(("k" spatial-navigate-backward-vertical-box "up")
|
||||
("j" spatial-navigate-forward-vertical-box "Down")
|
||||
("h" spatial-navigate-backward-horizontal-box "Down")
|
||||
("l" spatial-navigate-forward-horizontal-box "Down"))
|
||||
"Bar"
|
||||
(("K" spatial-navigate-backward-vertical-bar "up")
|
||||
("J" spatial-navigate-forward-vertical-bar "Down")
|
||||
("H" spatial-navigate-backward-horizontal-bar "Down")
|
||||
("L" spatial-navigate-forward-horizontal-bar "Down")))))
|
||||
#+begin_src emacs-lisp :tangle no
|
||||
(use-package spatial-navigate
|
||||
:straight (:repo "https://codeberg.org/ideasman42/emacs-spatial-navigate")
|
||||
:config
|
||||
(pretty-hydra-define spatial-navigate (:color amaranth :quit-key "q")
|
||||
("Box"
|
||||
(("k" spatial-navigate-backward-vertical-box "up")
|
||||
("j" spatial-navigate-forward-vertical-box "Down")
|
||||
("h" spatial-navigate-backward-horizontal-box "Down")
|
||||
("l" spatial-navigate-forward-horizontal-box "Down"))
|
||||
"Bar"
|
||||
(("K" spatial-navigate-backward-vertical-bar "up")
|
||||
("J" spatial-navigate-forward-vertical-bar "Down")
|
||||
("H" spatial-navigate-backward-horizontal-bar "Down")
|
||||
("L" spatial-navigate-forward-horizontal-bar "Down")))))
|
||||
#+end_src
|
||||
|
||||
And we can attach this menu to the “g” section:
|
||||
#+begin_src emacs-lisp
|
||||
#+begin_src emacs-lisp :tangle no
|
||||
(use-package spatial-navigate
|
||||
:general
|
||||
(:states '(normal visual motion operator)
|
||||
|
@ -115,9 +115,6 @@ Doing a lot of [[https://github.com/yoshiki/yaml-mode][YAML work]], but the =ya
|
|||
("h" ha-yaml-prev-section "Previous"))))))
|
||||
#+end_src
|
||||
|
||||
#+RESULTS:
|
||||
: major-mode-hydras/yaml-ts-mode/body
|
||||
|
||||
Allow this mode in Org blocks:
|
||||
#+begin_src emacs-lisp :results silent
|
||||
(add-to-list 'org-babel-load-languages '(yaml-ts . t))
|
||||
|
@ -202,12 +199,20 @@ I adapted this code from the [[https://github.com/emacsmirror/poly-ansible][poly
|
|||
#+end_src
|
||||
|
||||
We need to make sure the =mixed-pitch-mode= doesn’t screw things up.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(add-hook 'poly-yaml-jinja2-mode-hook (lambda () (mixed-pitch-mode -1)))
|
||||
|
||||
;; (add-hook 'yaml-ts-mode-hook 'poly-yaml-jinja2-mode)
|
||||
#+end_src
|
||||
#+begin_src yaml-ts
|
||||
|
||||
We /can/ hook this up to Org, via:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(add-to-list 'org-babel-load-languages '(poly-yaml-jinja2 . t))
|
||||
#+end_src
|
||||
|
||||
Now we can use either =yaml-ts= or =poly-yaml-jinja2= (which perhaps we should make an alias?):
|
||||
|
||||
#+begin_src poly-yaml-jinja2 :tangle no
|
||||
---
|
||||
# Let's see how this works
|
||||
- name: Busta move
|
||||
|
@ -244,6 +249,7 @@ The YAML files get access Ansible’s documentation using the [[https://github.c
|
|||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package ansible-doc
|
||||
:after yaml-ts-mode
|
||||
:hook (yaml-ts-mode . ansible-doc-mode)
|
||||
:config
|
||||
;; (add-to-list 'exec-path (expand-file-name "~/.local/share/mise/installs/python/3.10/bin/ansible-doc"))
|
||||
|
|
|
@ -46,7 +46,7 @@ Show code examples with the [[https://github.com/xuchunyang/elisp-demos][elisp-d
|
|||
:config
|
||||
(advice-add 'describe-function-1 :after #'elisp-demos-advice-describe-function-1))
|
||||
#+end_src
|
||||
** Better Function Help
|
||||
** Helpful Functions
|
||||
Let’s take advantage of [[https://github.com/Wilfred/helpful][helpful]] package for getting more information into the =describe-function= call.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
|
|
|
@ -213,6 +213,7 @@ Why use [[https://www.flycheck.org/][flycheck]] over the built-in =flymake=? Spe
|
|||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package flycheck
|
||||
:straight (:host github :repo "flycheck/flycheck")
|
||||
:init
|
||||
(setq next-error-message-highlight t)
|
||||
:bind (:map flycheck-error-list-mode-map
|
||||
|
@ -280,7 +281,7 @@ I’m interested in using [[https://devdocs.io/][devdocs.io]] instead, which is
|
|||
|
||||
The =devdocs-lookup= command attempts to guess which documentation it should display based on the mode, but if I’m editing YAML files, I actually want to pull up the Ansible documentation, and probably the Jinja ones too.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
#+begin_src emacs-lisp :tangle no
|
||||
(defun ha-devdocs-major-mode ()
|
||||
"My mapping of major mode to Devdocs slug."
|
||||
(interactive)
|
||||
|
@ -1115,7 +1116,6 @@ Most project =README= files and other documentation use [[https://jblevins.org/p
|
|||
Also, I like Markdown is look like a word processor, similarly to my org files:
|
||||
#+begin_src emacs-lisp
|
||||
(use-package markdown-mode
|
||||
:straight (:host github :repo "jrblevin/markdown-mode")
|
||||
:mode ((rx ".md" string-end) . gfm-mode)
|
||||
:init (setq markdown-command (expand-file-name "markdown" "~/bin")
|
||||
markdown-open-command (expand-file-name "markdown-open" "~/bin")
|
||||
|
@ -1135,38 +1135,25 @@ Also, I like Markdown is look like a word processor, similarly to my org files:
|
|||
", e" '("export" . markdown-export)
|
||||
", p" '("preview" . markdown-preview)))
|
||||
#+end_src
|
||||
|
||||
Note that the markdown-specific commands use the ~C-c C-c~ and ~C-c C-s~ prefixes.
|
||||
|
||||
With the =markdown-header-scaling= set, we no longer need to color the headers in Markdown, nor many of the /garish/ colors.
|
||||
Let’s make sure that [[https://www.flycheck.org/en/latest/languages.html#markdown][markdown]] is proper using [[https://pypi.org/project/pymarkdownlnt/][PyMarkdown]]. First, get the script installed globally:
|
||||
|
||||
#+begin_src sh
|
||||
pip install pymarkdown
|
||||
#+end_src
|
||||
|
||||
And then we can use it. For some reason, the =pymarkdown= (which I need to use from work) doesn’t seem to be part of the version of Flycheck available on Melpa, so…
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package markdown-mode
|
||||
:after org
|
||||
:after flycheck
|
||||
:config
|
||||
(let ((default-color (face-attribute 'default :foreground)))
|
||||
(set-face-attribute 'markdown-italic-face nil :foreground nil)
|
||||
(set-face-attribute 'markdown-bold-face nil :foreground nil)
|
||||
(set-face-attribute 'markdown-pre-face nil
|
||||
:foreground (face-attribute 'org-code :foreground))
|
||||
(set-face-attribute 'markdown-code-face nil
|
||||
:background (face-attribute 'org-block :background))
|
||||
(set-face-attribute 'markdown-language-keyword-face nil
|
||||
:foreground (face-attribute 'org-block-begin-line :foreground))
|
||||
(set-face-attribute 'markdown-url-face nil
|
||||
:foreground (face-attribute 'font-lock-comment-face :foreground))
|
||||
(set-face-attribute 'markdown-header-face nil
|
||||
:font ha-variable-header-font
|
||||
:foreground default-color)
|
||||
(when window-system
|
||||
(dolist (level '(1 2 3 4))
|
||||
(let ((md-level (make-face (make-symbol (format "markdown-header-face-%d" level))))
|
||||
(org-level (nth (1- level) org-level-faces)))
|
||||
(message "Setting %s size %.1f to %s" org-level (face-attribute org-level :height) md-level)
|
||||
(print `(set-face-attribute ,md-level nil
|
||||
:height ,(face-attribute org-level :height)))
|
||||
(set-face-attribute md-level nil :foreground default-color
|
||||
:height (face-attribute org-level :height)))))))
|
||||
|
||||
(setq flycheck-markdown-pymarkdown-config ".pymarkdown.yml")
|
||||
(flycheck-may-enable-checker 'markdown-pymarkdown))
|
||||
|
||||
;; defcustom flycheck-markdown-pymarkdown-config
|
||||
#+end_src
|
||||
|
||||
Both the =markdown-command= and the =markdown-open-command= variables are called to render (and preview) a Markdown file (~C-c C-c o~), and calls the following scripts (which in turn, call =pandoc= as I depend on this for other org-related features):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- mode: snippet -*-
|
||||
# name: code-block
|
||||
# key: <s
|
||||
# key: #s
|
||||
# --
|
||||
#+begin_src $1
|
||||
$0
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- mode: snippet -*-
|
||||
# name: emacs-lisp-code
|
||||
# key: <sl
|
||||
# key: #sl
|
||||
# --
|
||||
#+begin_src emacs-lisp
|
||||
$0
|
||||
|
|
8
snippets/org-mode/emacs-lisp-defun
Normal file
8
snippets/org-mode/emacs-lisp-defun
Normal file
|
@ -0,0 +1,8 @@
|
|||
# -*- mode: snippet -*-
|
||||
# name: emacs-lisp-test
|
||||
# key: #elt
|
||||
# --
|
||||
#+begin_src emacs-lisp
|
||||
(ert-deftest $1-test ()
|
||||
(should (= $0)))
|
||||
#+end_src
|
6
snippets/org-mode/emacs-lisp-defvar
Normal file
6
snippets/org-mode/emacs-lisp-defvar
Normal file
|
@ -0,0 +1,6 @@
|
|||
# key: slv
|
||||
# name: emacs-lisp-defvar
|
||||
# --
|
||||
+begin_src emacs-lisp
|
||||
(defvar ${1:symbol} ${2:initvalue} "${3:docstring}")
|
||||
#+end_src
|
7
snippets/org-mode/emacs-lisp-test
Normal file
7
snippets/org-mode/emacs-lisp-test
Normal file
|
@ -0,0 +1,7 @@
|
|||
# key: #elt
|
||||
# name: emacs-lisp-test
|
||||
# --
|
||||
#+begin_src emacs-lisp :tangle no
|
||||
(ert-deftest $1-test ()
|
||||
(should (= $0)))
|
||||
#+end_src
|
|
@ -1,6 +1,6 @@
|
|||
# -*- mode: snippet -*-
|
||||
# name: example-block
|
||||
# key: <e
|
||||
# key: #e
|
||||
# --
|
||||
#+begin_example
|
||||
$0
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- mode: snippet -*-
|
||||
# name: quote-block
|
||||
# key: <q
|
||||
# key: #q
|
||||
# --
|
||||
#+begin_quote
|
||||
$0
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- mode: snippet -*-
|
||||
# name: shell-script-code
|
||||
# key: <ss
|
||||
# key: #ss
|
||||
# --
|
||||
#+begin_src sh
|
||||
$0
|
||||
|
|
Loading…
Reference in a new issue