NOTE: GPG Certificate errors?? Try: M-x package-refresh-contents
and restart!!
My main .emacs file.
NOTE: For built-in packages, check out the emacs manual via: C-h r!
Install via ansible with the following command, which will prompt for sudo
password (pacman package installation) due to the -K or --ask-become-pass
flag:
cd ansible/ansible-playbook main.yml -K
You can add -i hosts if you want to run against remote hosts instead of
locally.
NOTE: Hard-coded to ArchLinux and my own needs.
- GNU: Where do I put my init file?:
- Either:
c:\<init.el> - Or:
c:\Users\<user>\AppData\Roaming\<init.el>- for Work laptops with locked downC:drives!! - Ignore: Registry key editing.
- NOTE: May need to run
CMDas Administrator.
- Either:
C:\Windows\System32>mklink c:\.emacs c:\src\org\dot_emacs\.emacs symbolic link created for c:\.emacs <<===>> c:\src\org\dot_emacs\.emacs C:\Windows\System32>mklink c:\config.org c:\src\org\dot_emacs\config.org symbolic link created for c:\config.org <<===>> c:\src\org\dot_emacs\config.org C:\Windows\System32>
To unset a key binding: ~M-x global-unset-key~y
To remove all hooks from a mode during testing, evaulate: (setq <mode-hook>
nil). As per:
https://www.gnu.org/software/emacs/manual/html_node/emacs/Hooks.html
(use-package compile
:ensure t
:custom
(compilation-ask-about-save nil "Auto save before compiling.")
(compilation-scroll-output t "Scroll output and don't stop on errors.")
(process-adaptive-read-buffering nil "Don't buffer command output in compilation window - keep up with rapidly noisy commands")
)(setq debug-on-error t)(use-package bug-hunter
:ensure t
:defer t)To start Esup, run M-x esup, and watch the magic happen.
By default, Esup will profile user-init-file. To profile a custom file, call
esup with a prefix argument. That is, C-u M-x esup.
(use-package esup
:ensure t
:defer t
:defer
:config
;; Work around a bug where esup tries to step into the byte-compiled
;; version of `cl-lib', and fails horribly.
;; See; https://github.com/jschaf/esup/issues/85
(setq esup-depth 0)
)#+BEGIN _SRC emacs-lisp (setq diary-file “~/org/diary”)
(use-package dired
:custom
(dired-async-mode t)
(dired-listing-switches "-alFh")
(dired-dwim-target t) ;; Guess target for operations.
)- Decompress archive(s):
Zdecompress to a folder named after archive.! <RETURN>to decompress to current folder.
- Rename files/folders:
C-xC-q(M-x dired-toggle-read-only) buffer editing.C-cC-ccommit changes to disk.
(use-package doc-view
:ensure-system-package ((gs . ghostscript))
)editorconfig-mode (EditorConfig):
(use-package editorconfig
:custom
(editorconfig-mode t)
)Eglot (Github: joaotavora/eglot) is the built-in, streamlined LSP (Language Server Protocol) client for emacs, to talk to LSP Servers with. it is the alternative to the external,feature-rich package: lsp-mode.
NOTE: Currently transitioning over to eglot from: lsp-mode, as part of
trying to slim down config and use more built-ins.
(use-package eglot
;; TODO: Raise bug about how this `:after` call breaks `eglot` automatically
;; running.
;; :after (company-mode)
:hook (
(eglot-mode . global-company-mode)
;; NOTE: `prog-mode` covers too many non-lsp modes. Tired of constant
;; errors, so going back to explicitly enabling eglot on each mode!
;; (prog-mode . eglot-ensure)
)
:ensure t)Breadcrumb is a mode that fell out of the wish for eglot Users to have the same
breadcrumb as seen in lsp-ui. See: Github: joaotavora/eglot - Breadcrumb
feature (can eglot support headerline like lsp-mode does?) #988.
This is external to eglot, but placing here just because of the link.
(use-package breadcrumb
:vc (:url "https://github.com/joaotavora/breadcrumb"
:rev :newest)
:ensure t
:config
(breadcrumb-mode)
)(use-package eww
:bind (("<f4>" . eww))
;; FIXME: eww is okay, but for things like google account redirects, we need
;; a real browser.
:config
(setq eww-bookmarks-directory "~/org/personal/")
;; (progn
;; (setq
;; browse-url-browser-function (quote eww-browse-url)
;; )
;; )
)
'(browse-url-browser-function (quote browse-url-default-browser)) ; Use system default browser instead of eww.
;; bound this to Darwin only.
;; (cond
;; ((string-equal system-type "darwin")
;; (setq browse-url-browser-function (quote browse-url-default-browser))));;'browse-url-generic
;; browse-url-generic-program "/Applications/Opera.app/Contents/MacOS/Opera")))Here’s a quick’n’dirty command to generate an org-mode rendering of an eww page, taking into account not only links (as the built-in
org-eww-copy-for-org-modedoes), but also headings, italic and bold faces.I am pretty sure it’s full of corner cases and rough edges, but it’s working for me as a starting point.
TODO:
- Handle conversion of:
<code>...</code>to=%s =. - Handle conversion of:
<pre>...</pre>to codeblocks, with potential fishing out of thesrc <lang>from aclass, if it exists.
(defun jao-eww-to-org (&optional dest)
"Render the current eww buffer using org markup.
If DEST, a buffer, is provided, insert the markup there."
(interactive)
(unless (org-region-active-p)
(let ((shr-width 80)) (eww-readable)))
(let· ((start (if (org-region-active-p) (region-beginning) (point-min)))
(end (if (org-region-active-p) (region-end) (point-max)))
(buff (or dest (generate-new-buffer "·eww-to-org·")))
(link (eww-current-url))
(title (or (plist-get eww-data :title) "")))
(with-current-buffer buff
(insert "#+title: " title "\n#+link: " link "\n\n")
(org-mode))
(save-excursion
(goto-char start)
(while (< (point) end)
(let· ((p (point))
(props (text-properties-at p))
(k (seq-find (lambda (x) (plist-get props x))
'(shr-url image-url outline-level face)))
(prop (and k (list k (plist-get props k))))
(next (if prop
(next-single-property-change p (car prop) nil end)
(next-property-change p nil end)))
(txt (buffer-substring (point) next))
(txt (replace-regexp-in-string "\\·" "·" txt)))
(with-current-buffer buff
(insert
(pcase prop
((and (or `(shr-url ,url) `(image-url ,url))
(guard (string-match-p "^http" url)))
(let ((tt (replace-regexp-in-string "\n\\([^$]\\)" " \\1" txt)))
(org-link-make-string url tt)))
(`(outline-level ,n)
(concat (make-string (- (· 2 n) 1) ?·) " " txt "\n"))
('(face italic) (format "/%s/ " (string-trim txt)))
('(face bold) (format "·%s· " (string-trim txt)))
(_ txt))))
(goto-char next))))
(pop-to-buffer buff)
(goto-char (point-min))))(use-package language-detection
; https://github.com/andreasjansson/language-detection.el
:ensure t
:defer t
)
(require 'cl-lib)
(defun eww-tag-pre (dom)
"See: https://github.com/andreasjansson/language-detection.el.
DOM - web dom."
(let ((shr-folding-mode 'none)
(shr-current-font 'default))
(shr-ensure-newline)
(insert (eww-fontify-pre dom))
(shr-ensure-newline)))
(defun eww-fontify-pre (dom)
"See: https://github.com/andreasjansson/language-detection.el.
DOM - web dom."
(with-temp-buffer
(shr-generic dom)
(let ((mode (eww-buffer-auto-detect-mode)))
(when mode
(eww-fontify-buffer mode)))
(buffer-string)))
(defun eww-fontify-buffer (mode)
"See: https://github.com/andreasjansson/language-detection.el.
MODE - ??"
(delay-mode-hooks (funcall mode))
(font-lock-default-function mode)
(font-lock-default-fontify-region (point-min)
(point-max)
nil))
(defun eww-buffer-auto-detect-mode ()
"See: https://github.com/andreasjansson/language-detection.el."
(let* ((map '((ada ada-mode)
(awk awk-mode)
(c c-mode)
(cpp c++-mode)
(clojure clojure-mode lisp-mode)
; (csharp csharp-mode java-mode)
(css css-mode)
(dart dart-mode)
(delphi delphi-mode)
(emacslisp emacs-lisp-mode)
(erlang erlang-mode)
(fortran fortran-mode)
(fsharp fsharp-mode)
(go go-mode)
(groovy groovy-mode)
(haskell haskell-mode)
(html html-mode)
(java java-mode)
(javascript javascript-mode)
(json json-mode javascript-mode)
(latex latex-mode)
(lisp lisp-mode)
(lua lua-mode)
(matlab matlab-mode octave-mode)
(objc objc-mode c-mode)
(perl perl-mode)
(php php-mode)
(prolog prolog-mode)
(python python-mode)
(r r-mode)
(ruby ruby-mode)
(rust rust-mode)
(scala scala-mode)
(shell shell-script-mode)
(smalltalk smalltalk-mode)
(sql sql-mode)
(swift swift-mode)
(visualbasic visual-basic-mode)
(xml sgml-mode)))
(language (language-detection-string
(buffer-substring-no-properties (point-min) (point-max))))
(modes (cdr (assoc language map)))
(mode (cl-loop for mode in modes
when (fboundp mode)
return mode)))
(message (format "%s" language))
(when (fboundp mode)
mode)))
(setq shr-external-rendering-functions
'((pre . eww-tag-pre)))FIXME: flymake: temp disable due to noise from legacy init mode:
(error "Can’t find a suitable init function").
Doesn’t appear when flymake is started by eglot in a mode that has an lsp.
(use-package flymake
:bind (:map flymake-mode-map
("C-c e" . flymake-show-buffer-diagnostics)
("C-c p" . flymake-show-project-diagnostics)
("C-c j" . flymake-goto-next-error)
)
;; :hook (
;; (prog-mode . flymake-mode)
;; (text-mode . flymake-mode)
;; )
:config
(progn
(set-face-attribute 'flymake-error nil :background "DarkRed")
(set-face-attribute 'flymake-warning nil :background "DarkBlue")
(set-face-attribute 'flymake-note nil :background "DarkGreen")
)
)- Don’t prompt to kill processes on exit.
(setq confirm-kill-processes nil)
- Global defaults:
(setq-default tab-width 4)
- Fuzzy completions (just like
idowith fuzzy matching set +smex) and Save history in minibuffers.(fido-mode t) (savehist-mode t) (setq savehist-additional-variables '(search-ring regexp-search-ring))
- Bookmarks:
(setq bookmark-default-file "~/org/personal/bookmarks")
- Highlights:
(global-hl-line-mode 1) ;; horizontal highlighted line on cursor. ;; Highlight current line in the line number column/fringe (set-face-attribute 'line-number-current-line nil :background "goldenrod" :foreground "black") ;; http://www.emacswiki.org/emacs/EmacsNiftyTricks ;; http://emacs-fu.blogspot.com/2008/12/highlighting-todo-fixme-and-friends.html (defun my_highlighted_words () "Highlight specific words in the buffer." (interactive) (font-lock-add-keywords nil '(("\\<\\(Note\\|NOTE\\|FIXME\\|Todo\\|TODO\\|BUG\\|Bug\\):" 1 '(:foreground "red" :weight bold) t))))
;; backup files - https://www.emacswiki.org/emacs/BackupDirectory
(setq
backup-by-copying t ; don't clobber symlinks
backup-directory-alist
'(("." . "~/.emacs.d/.backups/")) ; don't litter my fs tree
delete-old-versions t
kept-new-versions 6
kept-old-versions 2
version-control t) ; use versioned backups
(make-directory "~/.emacs.d/.backups/" t)
;; https://emacs.stackexchange.com/questions/17210/how-to-place-all-auto-save-files-in-a-directory
(setq auto-save-file-name-transforms
`(
("\\`/[^/]*:\\([^/]*/\\)*\\([^/]*\\)\\'" "/tmp/\\2" t)
(".*" "~/.emacs.d/.auto-saves/" t)
)
)
(make-directory "~/.emacs.d/.auto-saves/" t)
;; Don't save lock files by files - https://www.emacswiki.org/emacs/LockFiles.
(setq create-lockfiles nil)Auto save all open files in current session and reload on startup.
(use-package desktop
:ensure t
:defer t
:init (desktop-save-mode)
:config
(progn
;; Don't autosave desktops, it's too expensive. Desktops aren't
;; that precious, and Emacs will save the desktop on exit anyway.
(setq
desktop-restore-eager t
desktop-load-locked-desktop t
desktop-auto-save-timeout nil
desktop-path '("~/")
desktop-dirname "~/")
(dolist (mode '(magit-mode git-commit-mode))
(add-to-list 'desktop-modes-not-to-save mode))))Use the C-based line numbers instead of the slower lisp (`linum`). https://www.emacswiki.org/emacs/LineNumbers#h5o-1
(use-package display-line-numbers
:hook (
(conf-mode . 'display-line-numbers)
(prog-mode . 'display-line-numbers)
(text-mode . 'display-line-numbers)
(org-mode . (lambda () (display-line-numbers-mode -1)))
)
:custom-face
(line-number ((t (:inherit (shadow default) :background "grey10"))))
)Allow `Alt+3` on a Mac to be `#`:
- https://stackoverflow.com/questions/1704119/carbon-emacs-re-enable-hash-key
- https://stackoverflow.com/questions/3977069/emacs-question-hash-key
(global-set-key (kbd "M-3") '(lambda () (interactive) (insert "#")))
(define-key isearch-mode-map (kbd "M-3") '(lambda () (interactive) (isearch-process-search-char ?\#)))which-key integration, to show keyboard shortcuts.
(use-package which-key
:ensure t
:config
(which-key-mode))Highlight white-space (eg. tabs) in the buffer.
(use-package whitespace
:ensure t
:config
(global-whitespace-mode)
(setq whitespace-style (quote (face trailing tabs)))
)Load extra dot files (if they exist).
(make-directory "~/org/emacs" t)
(use-package cus-edit
:custom (custom-file "~/org/emacs/custom_set_variables.el" "Moved custom-set-variables to it's own file")
)
(let () (dolist (dot_emacs '("~/org/emacs/custom_set_variables.el"
"~/org/emacs/private_dot_emacs.el"
"~/org/emacs/unstable_config_dot_emacs.el"
"~/org/emacs/work_specific_dot_emacs.el"))
"Loading my extra emacs dot files if they exist."
(when (file-exists-p dot_emacs)
(message (concat "Loading external dot file: " dot_emacs))
(load-file dot_emacs))))The gutter bar at the bottom of the emacs window/frame.
(setq column-number-mode t)See:
(set-face-attribute 'mode-line-active nil
:foreground "black" :background "goldenrod" :box '(:line-width 1 :color "black"))smart mode line wraps up a lot of nice tweaks in one package.
NOTE: Trialling the stock mode-line for a bit to see if I can live without smart-mode-line.
(use-package smart-mode-line
;; :ensure t
:disabled t
:defer t
:init
(setq
sml/no-confirm-load-theme t
sml/theme 'dark
sml/mode-width `full
)
(sml/setup)
(column-number-mode t)
)Don’t load outdated byte code.
(setq load-prefer-newer t)SO: How do I byte compile everything?
;; (byte-recompile-directory (expand-file-name "~/.emacs.d") 0)Log but don’t pop up Warnings buffer for all native compilation warnings.
(setq native-comp-async-report-warnings-errors 'silent)I’ve used projectile for years, but giving project a go. Only ever used:
| Commands | Projectile | Project |
|---|---|---|
| Fuzzy search for files | C-c p f | C-x p f |
| Grep project | C-c g | C-x p g |
| Switch buffers in project | C-x p b | |
| Switch Project | C-c p p | C-c p p |
Going to try project for a bit and see how it goes.
(use-package project
:ensure t)Historical notes:
Been getting more annoyed at not using daemon mode on my main box and
connecting with emacsclients. Due to work, I use quite a few git-worktree’s
of the same repo. The problem would be accidentally cross editing files
across the different worktree’s (Hence not using daemon mode, and instead
just running up multiple emacs --debug-init sessions for each worktree.
Let’s have a go at banishing this behaviour:
- Projectile: Allows for project focus (git repo), whilst also doing fuzzy file searching across the entire project (Nice!)
- Perspective: Allows for workspaces that when switched to, return the
buffers to their original state. Also focuses down the
idobuffer to the open buffers in that workspace (Nice!) - persp-projectile: Combines Projectile and Perspective so that switching projects gives you the Perspective buffer change behaviour (Much nicer than Projectile’s insistence that you want to always open a new file but also keep old buffers hanging around).
NOTE: Projectile state is not saved in desktop-save.
NOTE: Perspective mode with IDO only show’s files in project, so have to use
ibuffer to get full list.
- https://github.com/bbatsov/projectile
- https://github.com/nex3/perspective-el
- https://github.com/bbatsov/persp-projectile
(use-package projectile
:disabled
;; :ensure t
;; :defer t
:bind ("C-c p" . 'projectile-command-map)
:init
(progn
(projectile-mode)
(recentf-mode) ; enables projectile-recentf mode for recent files.
; https://github.com/bbatsov/projectile/issues/1183
; Projectile now scrapes all files to discover project type for modeline.
; This is calculated on every cursor movement, so lags emacs like crazy.
; Below is the workaround to disable this until it is fixed.
(setq projectile-mode-line
'(:eval (format " Projectile[%s]"
(projectile-project-name))))
)
)(use-package server
:ensure t
:after (exec-path-from-shell)
:config
;; https://wiki.archlinux.org/title/Emacs#Multiplexing_emacs_and_emacsclient
(unless (server-running-p)
(server-start))
)See: Github: purcell/exec-path-from-shell & Yi Tang: Managing Emacs Server as Systemd Service for notes on using the environment variables:
Environment Variables
The customised shell configuration in .bashrc are loaded when opening an interactive shell session. So the Emacs server managed by systemd would not have the environment variables, alias, functions or whatever defined in .bashrc.
This stackoverflow post provides the rationale and how to tweak the unit file so systemd would load .bashrc.
This problem can solved a lot easier on the Emacs side, by using exec-path-from-shell package. It will ensure the environment variables inside Emacs are the same as in the user’s interactive shell.
Simply put the following in your .emacs would do the trick.
(exec-path-from-shell-initialize)
(use-package exec-path-from-shell
:ensure t
:config
(exec-path-from-shell-initialize)
)Lookup dictionary definitions.
See: https://emacsredux.com/blog/2023/04/11/looking-up-words-in-a-dictionary/,
for details as well as installing the dictionary service as an alternative
to: dict.org.
M-x dictionary-searchlook up word definition.M-x dictionary-lookup-definitionto do a lookup at point.
(use-package dictionary
:ensure t
:defer t
:config (setq dictionary-server "dict.org")
)See: EmacsWiki: FlySpell Performance about disabling
flyspell-issue-message-flag to greatly speed up flyspell-buffer.
(use-package flyspell
:ensure t
:hook (
(prog-mode . flyspell-prog-mode)
(text-mode . flyspell-mode)
)
:config (setq flyspell-issue-message-flag nil)
)M-x flyspell-buffer
ispell is the built in spell checker, but aspell is better (multiple
dictionaries). See: http://www.emacswiki.org/emacs/InteractiveSpell#toc6
(use-package ispell
:ensure-system-package (aspell)
:custom
(ispell-list-command "list")
(ispell-personal-dictionary "~/org/ispell_personal_dict")
(ispell-program-name "aspell")
(ispell-silently-savep t) ;; No confirmation on saving to personal dictionary.
)Either:
M-$ i.C-c $and then clickSave wordin GUI drop-down.
Steps:
- Pull welsh dictionary from; https://ftp.gnu.org/gnu/aspell/dict/cy/.
- Un-tar, build and install dictionary:
./configure && make && sudo make install. - Set file local variable to set the Welsh dictionary:
M-x add-file-local-variable <ret>ispell-local-dictionary<ret>"cy"<ret>. - Revert buffer and verify spellings:
M-x flyspell-buffer.
The tab-bar package creates tabs like a browser. Each tab can maintain it’s
layout. Seems to hook into desktop-save to restore on restarts.
(use-package tab-bar
:ensure t
:defer t
:after (hydra)
:bind ("C-x t" . 'hydra-tab-bar/body)
:config
;; https://github.com/abo-abo/hydra/wiki/Emacs-27-tab-bar-mode
;; https://github.com/abo-abo/hydra/wiki/Binding-Styles
(defhydra hydra-tab-bar (:color amaranth)
"Tab Bar Operations"
("t" tab-new "Create a new tab" :column "Creation")
("c" tab-new "Create a new tab")
("d" dired-other-tab "Open Dired in another tab")
("f" find-file-other-tab "Find file in another tab")
("0" tab-close "Close current tab")
("k" tab-close "Close current tab")
("m" tab-move "Move current tab" :column "Management")
("r" tab-rename "Rename Tab")
("n" tab-bar-select-tab-by-name "Select tab by name" :column "Navigation")
("s" tab-bar-select-tab-by-name "Select tab by name")
("j" tab-previous "Previous Tab")
("l" tab-next "Next Tab")
(";" tab-next "Next Tab")
("q" nil "Exit" :exit t)
)
)Treesit uses the tree-sitter grammars to provide faces/fontifying/structures to text by an AST instead of a regex (ie. fast, accurate, works during editing).
Automatically install tree-sitter grammars.
(use-package treesit-auto
:ensure t
:demand t
:config
(setq
treesit-auto-install t
)
(global-treesit-auto-mode)
)(global-auto-revert-mode t)
(put 'downcase-region 'disabled nil) ; allow downcase-region without the disabled feature warning.
(put 'upcase-region 'disabled nil) ; allow upcase-region without the disabled feature warning.
(setq calendar-week-start-day 1)
(menu-bar-mode -1) ;; Disable Menu Bar
(tool-bar-mode -1) ;; Disable tool Bar
(fset 'yes-or-no-p 'y-or-n-p) ;; yes/no -> y/n
(load-theme 'wombat t)
; (display-time) ;; Time in modeline. Un-comment to enable.
(display-battery-mode t) ;; Battery in modeline. Un-comment to enable.
(setq large-file-warning-threshold (* 1024 1024 1024)) ;; large files shouting from 1GB.
;; http://pragmaticemacs.com/emacs/dired-human-readable-sizes-and-sort-by-size/
(setq dired-listing-switches "-alh")Builtin method of moving between windows with (default) Shift+<arrow>. See:
PragmaticEmacs: Whizz between windows with windmove.
(use-package windmove
:ensure t
:config (windmove-default-keybindings)
)(defun go-to-column (column)
"GoTo column.
Was getting annoyed seeing errors that point to a COLUMN number;
so grabbed this code:
- http://emacsredux.com/blog/2013/07/09/go-to-column/"
(interactive "nColumn: ")
(move-to-column column t))
(global-set-key (kbd "M-g M-c") 'go-to-column)(defun my-programming-defaults-config ()
"All of my programming defaults in one place."
(interactive)
(whitespace-mode) ;; highlights whitespace.
(my_highlighted_words) ;; highlights specific words in red & bold.
(display-fill-column-indicator-mode) ;; adds fill column indicator.
;; (auto-fill-mode nil) ;; disables auto fill at column.
(setq indent-tabs-mode nil) ;; spaces instead of tabs
(setq tab-width 4) ;; 4 spaces per tab key press.
;; TODO: raise a bug on which-function-mode breaking in python when opening a
;; triple double-qoute (`"""`) docstring in a function and then emacs
;; freezes. Replicated on work files with: `emacs -q`, but failed to
;; replicate so far on a quickly mocked up file in /tmp/.
;;
;; (which-function-mode) ;; Display current function in mode line. (http://emacsredux.com/blog/2014/04/05/which-function-mode/)
(my_highlighted_words) ;; highlight specific words
(show-paren-mode 1) ;; highlight matching brackets
(setq tags-revert-without-query t)
)
(add-hook 'prog-mode-hook 'my-programming-defaults-config)
;; Don't line-wrap in html files.
;; https://stackoverflow.com/questions/9294437/emacs-disable-wordwrapping-in-html-mode
(add-hook 'html-mode-hook (lambda () (auto-fill-mode -1)))(defun revert-all-buffers ()
"Refreshes all open buffers from their respective files."
(interactive)
(dolist (buf (buffer-list))
(with-current-buffer buf
(when (and (buffer-file-name) (file-exists-p (buffer-file-name)) (not (buffer-modified-p)))
(revert-buffer t t t) )))
(message "Refreshed open files.") )(defun my-scratch-mode-config ()
"Disabling config for *scratch* buffer."
(interactive)
(display-fill-column-indicator-mode -1)
(auto-fill-mode -1)
)
(add-hook 'lisp-interaction-mode-hook 'my-scratch-mode-config)Here’s a simple defun to show non-ascii characters of current buffer in an Occur buffer http://www.emacswiki.org/emacs/FindingNonAsciiCharacters
(defun occur-non-ascii ()
"Find any non-ascii characters in the current buffer."
(interactive)
(occur "[^[:ascii:]]"))(defun my-text-mode-config ()
"All of my `text-mode` config in one place."
(interactive)
(whitespace-mode) ;; highlights whitespace.
(my_highlighted_words) ;; highlights specific words in red & bold.
(display-fill-column-indicator-mode) ;; adds fill column indicator.
(auto-fill-mode) ;; wraps at auto fill column.
(my_highlighted_words) ;; highlight specific words
(setq indent-tabs-mode nil) ;; spaces instead of tabs
)
(add-hook 'text-mode-hook 'my-text-mode-config) ;; singular text-mode-hook
(add-hook 'conf-mode-hook 'my-text-mode-config) ;; *.conf(defun comment-or-uncomment-region-or-line ()
"Un/Comments the region or the current line if there's no active region."
(interactive)
(let (beg end)
(if (region-active-p)
(setq beg (region-beginning) end (region-end))
(setq beg (line-beginning-position) end (line-end-position)))
(comment-or-uncomment-region beg end)))
(global-set-key (kbd "C-c '") 'comment-or-uncomment-region-or-line)- Expose all open tabs:
- Chrome:
chrome://inspect/#pages
- Chrome:
- Copy & paste into an org buffer.
- Remove any initial Groups.
- go to first description and run macro.
C-u<number>M-x <macro>to run X times.
Before:
.NET 9 - Goodbye sln! https://bartwullems.blogspot.com/2025/03/net-9-goodbye-sln.html 🚀 Getting Started | LazyVim https://www.lazyvim.org/ A 10x Faster TypeScript - TypeScript https://devblogs.microsoft.com/typescript/typescript-native-port/
After:
** [[https://bartwullems.blogspot.com/2025/03/net-9-goodbye-sln.html][.NET 9 - Goodbye sln!]] ** [[https://www.lazyvim.org/][🚀 Getting Started | LazyVim]] ** [[https://devblogs.microsoft.com/typescript/typescript-native-port/][A 10x Faster TypeScript - TypeScript]]
Macro:
(defalias 'my-clean-up-chrome-open-tabs-dumped-list
(kmacro "C-k <kp-delete> * * SPC [ [ C-e ] [ C-y ] ] <down> <kp-delete>"))NOTE: Created from a keyboard macro then named and saved.
This code runs a command and prints out the hooks to *Messages*:
(defun my/call-logging-hooks (command &optional verbose)
"Call COMMAND, reporting every hook run in the process.
Interactively, prompt for a command to execute.
Return a list of the hooks run, in the order they were run.
Interactively, or with optional argument VERBOSE, also print a
message listing the hooks.
Stolen from:
https://emacs.stackexchange.com/questions/19578/list-hooks-that-will-run-after-command "
(interactive "CCommand to log hooks: \np")
(let* ((log nil)
(logger (lambda (&rest hooks)
(setq log (append log hooks nil)))))
(my/with-advice
((#'run-hooks :before logger))
(call-interactively command))
(when verbose
(message
(if log "Hooks run during execution of %s:"
"No hooks run during execution of %s.")
command)
(dolist (hook log)
(message "> %s" hook)))
log))
(defmacro my/with-advice (adlist &rest body)
"Execute BODY with temporary advice in ADLIST.
Each element of ADLIST should be a list of the form
(SYMBOL WHERE FUNCTION [PROPS])
suitable for passing to `advice-add'. The BODY is wrapped in an
`unwind-protect' form, so the advice will be removed even in the
event of an error or nonlocal exit.
Stolen from:
https://emacs.stackexchange.com/questions/19578/list-hooks-that-will-run-after-command"
(declare (debug ((&rest (&rest form)) body))
(indent 1))
`(progn
,@(mapcar (lambda (adform)
(cons 'advice-add adform))
adlist)
(unwind-protect (progn ,@body)
,@(mapcar (lambda (adform)
`(advice-remove ,(car adform) ,(nth 2 adform)))
adlist))))This is largely the fault of some bad defaults on MacOS.
For starters, the default size of a pty buffer on MacOS is a pitiful 1024 bytes. This means that any processes started in emacs via
start-processwithprocess-connection-typeset toptyare going to be extremely slow: on my machine, this is on the order of 10x. Basically any elisp that interacts with things outside emacs calls this function (magit, dired, compilation-mode, eglot, etc) so this is the root of a lot of performance woes. You can fix this on an ad-hoc basis adding the following advice to functions that callstart-process:(defun start-process@use-pipe (fn &rest args) ;; checkdoc-params: (fn args) "Advice to ensure that `start-process' uses a pipe rather than a pty for the compilation command. This increases performance on OSX by a factor of 10, as the default pty size is a pitiful 1024 bytes." (let ((process-connection-type nil)) (apply fn args)))For
magit, you can avoid using this hack by just settingmagit-process-connection-typetonil.The performance of
gititself on MacOS also leaves a lot to be desired. This is a combination of spotlight indexing causing large branch switches to be slower, and some more bad defaults. Disabling spotlight indexing in git repos and settingcore.fswatchtotruein my git config sped things up quite a bit, but there’s further performance tuning that I haven’t looked into deeply…
Q. Just out of curiosity, why is
setq process-connection-type nilnot sufficient?A. This does work, but isn’t as fine-grained as adding advice on a per-case basis. In particular, this will break
trampintegration for things that sloppily callstart-processwithout checking if the command they will call is located on a remote machine.…
emacs-plus has a patch to bypass the 1024 pty buffer limit
…
In addition to the other good recommendations, I always suggest to review macOS default settings:
# "Set a blazingly fast keyboard repeat rate, " defaults write NSGlobalDomain KeyRepeat -int 1 # "Set a shorter Delay until key repeat" defaults write NSGlobalDomain InitialKeyRepeat -int 9 # Log out or reboot afterThat sets the keyboard rate beyond what’s possible in System Settings UI and greatly reduces the latency, navigating and typing in Emacs noticeably gets faster. You have to remember though never to change these values in the System Settings UI.
Additionally you may want to:
# Disable long-press accents defaults write -g ApplePressAndHoldEnabled -bool false # Increase the Dock show/hide speed defaults write com.apple.dock autohide -bool true defaults write com.apple.dock autohide-time-modifier -float 0.5 killall Dock # 'Are you sure you want to open this application?' defaults write com.apple.LaunchServices LSQuarantine -bool false
(defun start-process@use-pipe (fn &rest args)
;; checkdoc-params: (fn args)
"Advice to ensure that `start-process' uses a pipe rather than
a pty for the compilation command. This increases performance on OSX
by a factor of 10, as the default pty size is a pitiful 1024 bytes."
(let ((process-connection-type nil))
(apply fn args)))Fill Column is used to reflow text automatically & highlight margins, as well as show a hard column line. See: Emacs Wiki: FillColumnIndicator. I changed the column fill to be a double pipe. See unicode table.
(use-package fill-column-indicator
:ensure t
:defer t
:config
(progn
(setq-default fci-rule-column 79)
(setq fci-rule-character ?\u2016)
;; automatically wrap to 100 (Less pedantic about enforcing classic terminal widths) ~79~ characters.
(setq-default fill-column 100)
(setq-default git-commit-fill-column 79))
)Useful package when paired with a presentation mode like: [[*\[\[https://github.com/takaxp/org-tree-slide\]\[org-tree-slide\]\]:][org-tree-slide]], give a fullscreen (distraction-free) presentation. See: YouTube: Emacs Tips - How to Give Presentations with Org Mode (Questions).
(use-package hide-mode-line :ensure t)NOTE: Seeing LSP and other packages blowing up on this missing requirement.
(use-package treemacs
:ensure t
:defer t
:custom
(treemacs-project-follow-mode t)
)Disabled, since I don’t like the additional padding around each row + middle placement of the icons.
;; (use-package treemacs-icons-dired
;; :hook (dired-mode . treemacs-icons-dired-enable-once)
;; :ensure t)NOTE: Kept getting locks where CPU would spike from this pegging magit loads, with half of profiled CPU taken up by this package.
;; (use-package treemacs-magit
;; :after (treemacs magit)
;; :ensure t)(use-package treemacs-tab-bar ;;treemacs-tab-bar if you use tab-bar-mode
:after (treemacs)
:ensure t
:config (treemacs-set-scope-type 'Tabs))Centre buffers, example for presentations
(use-package visual-fill-column
:ensure t
:custom
(visual-fill-column-width 110)
(visual-fill-column-center-text t)
)(use-package alert
;; TODO: Check if Mac can work with libnotify. It works on Linux.
;; Still not working + libnotify keeps being reinstalled by brew due to
;; different name.
;; :ensure-system-package (libnotify)
:ensure t
:commands (alert)
:init
(if (eq system-type 'darwin)
(setq alert-default-style 'terminal-notifier)
(setq alerqt-default-style 'libnotify)
)
(setq
alert-fade-time 15
)
)Notifications from scheduled items in the Org Agenda. Builds off: [[*\[\[https://github.com/jwiegley/alert\]\[alert\]\]:][alert]].
NOTE: On Mac’s I am using an Alert notification for terminal-notifier, so
that notifications have to be explicitly closed.
(use-package org-alert
;; https://github.com/julienXX/terminal-notifier/issues/292 - No Notification in macOS12.1 #292
;; https://github.com/julienXX/terminal-notifier
;; TODO: Check if Mac can work with libnotify. It works on Linux.
;; :ensure-system-package terminal-notifier
:ensure t
;; :disabled t ;; Why is this blowing up??
:after (org)
:config
(setq
alert-default-style 'libnotify
org-alert-notify-cutoff 5
org-alert-notify-after-event-cutoff 1
)
(org-alert-enable)
)Very old way of doing custom notification pop-ups:
- http://emacs-fu.blogspot.com/2009/11/showing-pop-ups.html
- https://www.gnu.org/software/emacs/manual/html_node/elisp/Desktop-Notifications.html, since this would be nicer to move to a standardised package.
;; TODO: figure out why the built in `notifications` package doesn't play
;; sounds:
(defun djcb-popup (title msg &optional timeout icon sound)
"Show a popup if we're on X, or echo it otherwise;
TITLE is the title of the message, MSG is the context.
Optionally, you can provide a TIMEOUT (milliseconds, default=5000) an ICON and
a SOUND to be played (default=/../alert.wav)"
(interactive)
(shell-command
(concat "mplayer -really-quiet "
(if sound sound "/usr/share/sounds/purple/alert.wav")
" 2> /dev/null"))
;; Removed `(if (eq window-system 'x))` check since it wasn't doing the
;; notify-send on my terminal emacs session nested in tmux in a terminal
;; under cinnamon.
(shell-command (concat "notify-send"
(if icon (concat " -i " icon) "")
(if timeout (concat " -t " timeout) " -t 5000")
" '" title "' '" msg "'"))
;; text only version
(message (concat title ": " msg)))Run example:
(djcb-popup "Warning" "The end is near"
nil
"/usr/share/icons/gnome/128x128/apps/libreoffice-base.png"
"/usr/share/sounds/purple/alert.wav")
VC config (VC is built in version control package. Magit is an enhanced git VC package).
(setq vc-follow-symlinks t)magit - a pretty good git package with more features than the built in emacs “vc” package.
magit-svn (legacy):
Used this years ago when SVN and git-svn where part of my daily work routine. Haven’t needed to touch SVN in years, but keeping here for legacy reasons.
(use-package magit-svn
:ensure t
:defer t
:after (magit)
)magit-popup (legacy):
magit/magit#3749 magit moved to using transient
but some packages (magithub -
vermiculus/magithub#402) haven’t updated, hence
explicit definition of magit-popup
(use-package magit-popup
:ensure t
:after (magit)
)Builds on top of Magit to interact with VCS’s so that you can create/edit Issues/PR’s.
Replacement for magithub, which works with Gitlab/Github. See old commits for
my old magithub config.
(use-package forge
;; https://www.reddit.com/r/emacs/comments/fe165f/pinentry_problems_in_osx/
;; to fix GPG timeouts due to no password provided/asked.
;; NOTE: for emacsclients, it asks in the main instance window.
:if (not (eq system-type 'windows-nt)) ;; FIXME: Needs `cc` compiler defined.
:ensure t
:after (magit)
:config
(add-to-list 'magit-section-initial-visibility-alist '(issues . show))
(add-to-list 'magit-section-initial-visibility-alist '(pullreqs . show))
)Code Review is a package that builds on top of Magit, but supports interacting with PR’s to do code reviews (comments, diff view, approvals, etc).
M-x code-review-forge-pr-at-pointon forge PR line.rfor transient menu in acode-reviewbuffer.
(use-package code-review
:ensure t
:defer t
:after (magit forge)
;; pull maintained fork
:vc (:url "https://github.com/doomelpa/code-review.git" :rev :newest)
:config
(setq
code-review-auth-login-marker 'forge
code-review-bitbucket-host "bitbucket.eigen.live/rest/api/1.0"
code-review-gitlab-host "gitlab.eigen.live/api"
code-review-gitlab-graphql-host "gitlab.eigen.live/api"
;; Dump requests into the logs for debugging. eg.
;; https://github.com/wandersoncferreira/code-review/issues/195.
;;
;; code-review-log-raw-request-responses t
)
)A GNU Emacs major mode for keeping notes, authoring documents, computational notebooks, literate programming, maintaining to-do lists, planning projects, and more — in a fast and effective plain text system.
NOTE: Broken apart org mode config via: Github: jwiegley/use-package/issues/662 - Calling use-package multiple times on the same package #662.
See: http://cestlaz.github.io/posts/using-emacs-26-gcal/
(use-package calfw
:ensure t
:defer t
:after (org)
:bind
(
("<f8>" . cfw:open-org-calendar)
)
:config
(progn
(use-package calfw-gcal
;; FIXME: 10year old package with deprecated `cl` requirement.
;; TODO: replace for: https://github.com/myuhe/org-gcal.el.
:ensure t
:defer t)
(use-package calfw-ical
:ensure t
:defer t)
(use-package calfw-org
:ensure t
:defer t)
)
;; FIXME: what does this do??
(setq cfw:org-overwrite-default-keybinding t)
)(use-package org
;; NOTE: ~ox-confluence~ from ~org-contrib~ never worked well, compared to
;; the exports listed in: ~config.org~. Disabling for now.
;; https://emacs.stackexchange.com/questions/7890/org-plus-contrib-and-org-with-require-or-use-package
;; https://emacs.stackexchange.com/questions/70081/how-to-deal-with-this-message-important-please-install-org-from-gnu-elpa-as-o
;; :ensure org-contrib
:ensure t
:bind (
("C-c l" . org-store-link)
("C-c a" . org-agenda)
("C-c c" . org-capture))
:init
(progn
(setq
org-directory "~/org/"
;; org-agenda-files (list "~/org/" "~/org/personal/" "~/org/programming_notes/")
org-agenda-files (apply 'append
(mapcar
(lambda (directory)
(directory-files-recursively
directory org-agenda-file-regexp))
'("~/org/")))
org-default-notes-file "~/org/notes.org"
;; refile level.
;; http://www.millingtons.eclipse.co.uk/glyn/dotemacs.html
org-refile-targets (quote
((org-agenda-files :maxlevel . 5)
("~/org/personal/projects.org" :maxlevel . 2)
("~/org/programming_notes/notes.org" :maxlevel . 5)))
;; Allow refiling to a file to support moving up to heading level 1
org-refile-use-outline-path 'file
;; FIXME: Something has changed to the point where I can no longer refile
;; to headings in a file after the file selection part. Changing the
;; outline path option below allows me to do it, but it is super laggy
;; from all of the headings it is fuzzy searching through.
;;
;; I may have to give up on refiling to the top heading in a file with the
;; ~org-refile-use-outline-path 'file~ change above.
org-outline-path-complete-in-steps nil
org-log-done t
;; https://kundeveloper.com/blog/org-capture-3/ for `org-capture-templates` ideas.
org-capture-templates '(
("t" "Todo" entry (file+headline "~/org/todo.org" "UNSORTED")
"* TODO %? %^G\n %U - %i\n %a")
("p" "Projects" entry (file+headline "~/org/personal/projects.org" "UNSORTED")
"* TODO %?\n %U - %i\n %a")
("b" "Buy" entry (file+headline "~/org/personal/buy.org" "UNSORTED")
"* TODO %?\n %U - %i\n %a")
("i" "Inbox - Dumping ground" entry (file "~/org/inbox.org") "* %?\n")
("n" "Notes" entry (file+headline "~/org/programming_notes/notes.org" "UNSORTED")
"* TODO %?\n %U - %i\n %a")
("y" "YouTube: Watch List.\n\t\t*Link is pulled from X Clipboard!!*\n\t\t*NOTE:* if this is a Playlist;\n\t\t- manually delete ~v=<id>&~.\n\t\t- keep: ~list=<id>~!" entry (file+headline "~/org/personal/personal_todos.org" "YouTube Watch list:")
"* [[shell:mpv %x &][YouTube: %?]] :WATCH:")
)
)
(global-set-key "\C-cr" (lambda () (interactive) (org-capture nil "t")))
(global-set-key "\C-cn" (lambda () (interactive) (org-capture nil "n")))
)
:config
;; ;; Explicit requires from the `org-contrib` package.
;; (require 'ox-confluence) ;; FIXME: wrong type arguments error!
(setq
org-insert-heading-respect-content t ;; C-return creates new heading after content instead of next line.
org-link-file-path-type 'relative
org-use-tag-inheritance nil ;; Don't show un-tagged sub-headings when there is a tag on a high-level.
;; https://writequit.org/denver-emacs/presentations/2017-04-11-time-clocking-with-org.html#estimating-task-time
;; global Effort estimate values
org-global-properties
'(("Effort_ALL" .
"0:15 0:30 1:00 2:00 4:00 8:00 16:00 24:00 36:00 "))
;; 1 2 3 4 5 6 7 8 9
;; These are the hotkeys ^^
)
)- http://orgmode.org/worg/code/elisp/dto-org-gtd.el
- http://www.gnu.org/software/emacs/manual/html_node/org/Remember-templates.html
- Convert markdown links (
[display_message](link)) to org links ([[link][display_message]]):(fset 'convert-markdown-link-to-org-link "\C-[xreplace-regexp\C-m\\[\\(.*\\)\\](\\(.*\\))\C-m[[\\2][\\1]]\C-m")
Suggested Export Options at top of file: #+OPTIONS: \n:nil toc:nil
num:nil. Or: #+OPTIONS: \n:nil toc:nil num:nil html-postamble:nil to remove
the footer as well.
- No line wrapping.
- No TOC.
- Don’t number headings.
Been trying different ways to export org files to then dump into Confluence. Current rating of exporters:
- Export to HTML.
- Highlight region.
M-x org-html-export-as-html, cursor jumps to export buffer.M-x browse-url-of-buffer, to open in your browser.- Select all in Browser tab and paste into Confluence edit mode.
- Export to ASCII.
M-x org-ascii-export-as-ascii.- Requires below config changes.
- Issues around Headings being picked up by Confluence (eg. h3 == h2, no h3+).
- Issues around Formatting being picked up by Confluence (eg. No Bold markup).
- Export to Markdown.
M-x org-md-export-as-markdown.- Great rendering in a
/markdownmacro, but other macros cannot be nested inside or work with the/markdownmacro. eg. No/tocmacro. - Pretty good rendering pasting into Confluence edit area, but no auto wrapping. ie. 80 characters.
- BROKEN:
M-x ox-confluencefromorg-contribthrows errors on emacs29.
Better ASCII export output from org files when the target is an Atlassian
Confluence Wiki. Export via: M-x org-ascii-export-as-ascii (C-cC-etA).
TODO: figure out what Heading underlining style Confluence uses for H3-H5!!
(setq org-ascii-text-width 10000) ;; Large text width to avoid line wrapping.
(setq org-ascii-inner-margin 0) ;; Don't indent lines between headings.
;; Confluence expects H2 to be ~-~.
(setq org-ascii-underline '((ascii 61 45 45)
(latin1 61 126 45)
(utf-8 9552 9472 9548 9476 9480)))
(defun org-custom-link-img-follow (path)
"PATH to find custom linked images."
(org-open-file-with-emacs
(format "~/org/github_blog/images/%s" path)))
(defun org-custom-link-img-export (path desc format)
"Rewrite custom linked images for export.
PATH - path to images.
DESC - Description to add as alt text..
FORMAT - .format to use."
(cond
((eq format 'html)
(format "<img src=\"http://jackson15j.github.io/%s\" alt=\"%s\"/>" path desc))))
(require 'org)
;; FIXME: `org-add-link-type` is deprecated. Replace with:
;; `org-link-set-parameters`.
(org-add-link-type "img" 'org-custom-link-img-follow 'org-custom-link-img-export)(use-package ox-epub
:ensure t)Hit C-c C-e E e to publish the current buffer to an EPUB.
There are some required export options that need to be set. These are
UID: a unique id of the document, otherwise known as uri, may be a urlDATE: the date of the document, for valid values see https://www.w3.org/TR/NOTE-datetimeAUTHOR: the document author or editor, the creator in the EPUB specTITLE: the document title
Furthermore there are some properties which are optional:
Subject: the subject matter of the bookDescription: a description of the bookPublisher: the publisher of the bookLicense: the rights associated with this book, the copyright notice and further rights may be included in this option.EPUBCOVER: the cover image to use for the exportEPUBSTYLE: the CSS file to use for the export, this is set by default but can be set on a per document basis
The only other option that is exported:
LANGUAGE: the language of the book, this is to be interpreted according to RFC3066 or it’s succeeding documents https://www.ietf.org/rfc/rfc3066.txt, no other interpretations are allowed according to the EPUB spec.
(let () (dolist (dot_emacs '("~/org/config.org"
))
"Loading my extra emacs dot files if they exist."
(when (file-exists-p dot_emacs)
(message (concat "Loading external literate config: " dot_emacs))
(org-babel-load-file dot_emacs))))(defvar dig-my-grave/templates-alist/org-mode
'(("Bash" . "#+BEGIN_SRC bash :results scalar replace :exports both :tangle yes\n#+END_SRC")
("C#" . "#+BEGIN_SRC csharp\n#+END_SRC")
("Blockquote" . "#+BEGIN_QUOTE\n#+END_QUOTE")
("Details and Summary" . "#+begin_details\n#+begin_summary\n\n#+end_summary\n#+end_details")
("Emacs Lisp" . "#+BEGIN_SRC emacs-lisp\n#+END_SRC")
("Golang" . "#+BEGIN_SRC golang\n#+END_SRC")
("Javascript" . "#+BEGIN_SRC javascript\n#+END_SRC")
("JSON" . "#+BEGIN_EXAMPLE json\n#+END_EXAMPLE")
("Org Structure" . org-insert-structure-template)
("Plant UML" . "#+BEGIN_SRC plantuml\n@startuml\n!theme amiga\n\n@enduml\n#+END_SRC")
("Mermaid" . "#+BEGIN_SRC mermaid\n#+END_SRC")
("Python" . "#+BEGIN_SRC python\n#+END_SRC")
("Restclient" . "#+BEGIN_SRC restclient :results silent\n#+END_SRC")
("Ruby" . "#+BEGIN_SRC ruby\n#+END_SRC")
("Text" . "#+BEGIN_EXAMPLE text\n#+END_EXAMPLE")
("Shell" . "#+BEGIN_SRC shell :results scalar replace :exports both :tangle yes\n#+END_SRC")
("SQL" . "#+BEGIN_SRC sql\n#+END_SRC")
("Update" . tempel-insert-update_block))
"A list of `cons' cells with `car' as the label and `cdr' as
the value that we'll insert. Used as the collection for the
`dig-my-grave' `completing-read'.")
(defun dig-my-grave ()
"Three consecutive graves (e.g. “`”) at the start of the line prompts for
inserting content. See `dig-my-grave/templates-alist/org-mode'. Stolen
from:
https://takeonrules.com/2023/04/09/dig-my-grave-leveraging-the-triple-back-tick-in-org-mode/"
(interactive)
(if (or (and (> (point) 3)
(string= (buffer-substring-no-properties
(- (point) 3) (point)) "\n``"))
;; Account for starting on the first line
(and (= (point) 3)
(string= (buffer-substring-no-properties
(- (point) 2) (point)) "``")))
;; We have just hit our third back-tick at the beginning of the line.
(progn
(delete-char -2)
;; I use the alist-get pattern a lot...perhaps a function?
(let ((value (alist-get (completing-read "Special Content: "
dig-my-grave/templates-alist/org-mode nil t)
dig-my-grave/templates-alist/org-mode nil nil #'string=)))
(cond
;; Let's assume that we're dealing with registered org blocks.
((stringp value)
(insert value) (forward-line -1) (org-edit-special))
;; Trust the function
((commandp value) (call-interactively value))
((functionp value) (funcall value))
((ad-lambda-p) (funcall value))
;; Time for a pull request
(t (error "Unprocessable value %s for #'dig-my-grave" value)))))
(setq last-command-event ?`)
(call-interactively #'org-self-insert-command)))
(define-key org-mode-map (kbd "`") #'dig-my-grave)Add: :async to an org-babel code block to run async when called with:
C-cC-c.
FIXME: Comment out `ob-async`. It’s throwing errors on post-install restart!
- https://www.orgmode.org/manual/Custom-Agenda-Views.html
- https://redgreenrepeat.com/2021/04/09/org-mode-agenda-getting-started-scheduled-items-and-todos/
- http://www.cachestocaches.com/2016/9/my-workflow-org-agenda/#the-agenda
- https://github.com/gjstein/emacs.d/blob/master/config/gs-org-agenda.el
(defun my-clocktable-write (&rest args)
"Custom clocktable writer.
es the default writer but shifts the first column right."
;; https://emacs.stackexchange.com/questions/42329/how-to-choose-the-order-of-clocktable-columns
;; https://stackoverflow.com/questions/53653616/add-comment-column-to-emacs-org-mode-clock-table/53684091#53684091
;;
;; FIXME: When using =:scope agenda= the file is in column1 and Properties are
;; in column2, so this moves the first, not 2nd (effort) column.
(apply #'org-clocktable-write-default args)
(save-excursion
(forward-char) ;; move into the first table field
(org-table-move-column-right)
(org-table-move-column-right)
))
(use-package org
:config
(setq
org-agenda-custom-commands '(
;; Keep tags but hide `DONE` tasks: https://orgmode.org/manual/Matching-tags-and-properties.html
("r" "Agenda Review"
(
(agenda "")
(tags "ACTION" ((org-agenda-overriding-header "\nItems I need to action!! ~:ACTION:~")))
(tags "CHASE" ((org-agenda-overriding-header "\nChase down these people!! ~:CHASE:~")))
(tags "INVESTIGATE|INVESTIGATION" ((org-agenda-overriding-header "\nInvestigation tasks!! ~:INVESTIGATE:INVESTIGATION:~")))
(tags "REVIEW|WIKI" ((org-agenda-overriding-header "\nDump this into Confluence!! ~:REVIEW:WIKI:~")))
(tags "READ|WATCH" ((org-agenda-overriding-header "Books/Links I need to read/WATCH!! ~:READ:WATCH:~")))
(tags "TRAINING" ((org-agenda-overriding-header "Current/Future training tasks ~:TRAINING:~")))
(tags "ADMIN" ((org-agenda-overriding-header "Admin tasks ~:ADMIN:~")))
(tags-todo "-ACTION-ADMIN-CHASE-READ-REVIEW-TRAINING-WATCH-WIKI" ((org-agenda-overriding-header "\nGeneral TODO's")))
)
nil ;; settings
("/tmp/org_agenda_review.html" "/tmp/org_agenda_review.ics" "/tmp/org_agenda_review.txt") ;; ~org-store-agenda-views~ output file
)
;; Getting Things Done
("g" "GTD - Getting Things Done"
(
(agenda "")
(tags "QUICK" ((org-agenda-overriding-header "\nQuick = 5min tasks!! Fill in the gaps!! ~:QUICK:~")))
(tags "NEXT" ((org-agenda-overriding-header "\nNext = actionable!! Complete these!! ~:NEXT:~")))
(tags "CHASE|DELEGATE" ((org-agenda-overriding-header "\nChase down these people!! ~:CHASE:DELEGATE:~")))
(tags "READ|REVIEW|WATCH" ((org-agenda-overriding-header "\nBooks/Links I need to read/review/watch!! ~:READ:REVIEW:WATCH:~")))
(tags-todo "-CHASE-DELEGATE-NEXT-READ-REVIEW-WATCH" ((org-agenda-overriding-header "\nGeneral TODO's: What is the Next Action? What does Done look like?")))
)
(
(org-agenda-span 8)
(org-agenda-start-day "today")
) ;; settings
("/tmp/org_agenda_gtd.html" "/tmp/org_agenda_gtd.ics" "/tmp/org_agenda_gtd.txt") ;; ~org-store-agenda-views~ output file
)
;; https://fortelabs.com/blog/para/
("p" "PARA Personal (Project Area Resources Archive) Agenda Review"
(
(agenda "" ((org-agenda-files (list "~/org/" "~/org/personal/" "~/org/programming_notes/"))))
(tags "ACTION|CHASE|INVESTIGATE|INVESTIGATION|TRAVEL" ((org-agenda-overriding-header "\nProject: \"a series of tasks linked to a goal, with a deadline.\" ~:ACTION:CHASE:INVESTIGATE:INVESTIGATION:~") (org-agenda-files (list "~/org/" "~/org/personal/" "~/org/programming_notes/"))))
(tags-todo "-ACTION-ADMIN-CHASE-EMACS-PERSONAL-READ-REVIEW-TRAINING-TRAVEL-WATCH-WIKI-WORKFLOW-STYLE=\"habit\"-SCHEDULED>=\"<now>\"-DEADLINE>=\"<now>\"" ((org-agenda-overriding-header "Project: (Tag to remove non-urgent TODO's out of this list!!)") (org-agenda-files (list "~/org/" "~/org/personal/" "~/org/programming_notes/"))))
(tags "ADMIN|REVIEW|WIKI|WORKFLOW-STYLE=\"habit\"" ((org-agenda-overriding-header "\nAreas: \"a sphere of activity with a standard to be maintained over time.\" ~:ADMIN:REVIEW:WIKI:WORKFLOW:~") (org-agenda-files (list "~/org/" "~/org/personal/" "~/org/programming_notes/"))))
(tags "EMACS|PERSONAL-STYLE=\"habit\"|READ|TRAINING-STYLE=\"habit\"|WATCH|UNSORTED" ((org-agenda-overriding-header "\nResource: \"a topic or theme of ongoing interest.\" ~:EMACS:PERSONAL:READ:TRAINING:WATCH:UNSORTED:~") (org-agenda-files (list "~/org/" "~/org/personal/" "~/org/programming_notes/"))))
)
nil ;; settings
;; See: https://orgmode.org/manual/Exporting-Agenda-Views.html
;; ~M-x org-store-agenda-views~ outputs all files for all views.
;; Script export: ~emacs --batch -l ~/.emacs --eval '(org-store-agenda-views)'~
("/tmp/org_agenda_para.html" "/tmp/org_agenda_para.ics" "/tmp/org_agenda_para.txt")
)
("w" "PARA Work (Project Area Resources Archive) Agenda Review"
(
(agenda "" ((org-agenda-files (directory-files-recursively "~/org/work/" org-agenda-file-regexp))))
(tags "ACTION|CHASE|INVESTIGATE|INVESTIGATION|TRAVEL" ((org-agenda-overriding-header "\nProject: \"a series of tasks linked to a goal, with a deadline.\" ~:ACTION:CHASE:INVESTIGATE:INVESTIGATION:~") (org-agenda-files (directory-files-recursively "~/org/work/" org-agenda-file-regexp))))
(tags-todo "-ACTION-ADMIN-CHASE-EMACS-PERSONAL-READ-REVIEW-TRAINING-TRAVEL-WATCH-WIKI-WORKFLOW" ((org-agenda-overriding-header "Project: (Tag to remove non-urgent TODO's out of this list!!)") (org-agenda-files (directory-files-recursively "~/org/work/" org-agenda-file-regexp))))
(tags "ADMIN|REVIEW|WIKI|WORKFLOW" ((org-agenda-overriding-header "\nAreas: \"a sphere of activity with a standard to be maintained over time.\" ~:ADMIN:REVIEW:WIKI:WORKFLOW:~") (org-agenda-files (directory-files-recursively "~/org/work/" org-agenda-file-regexp))))
(tags "READ|TRAINING|WATCH|UNSORTED" ((org-agenda-overriding-header "\nResource: \"a topic or theme of ongoing interest.\" ~:READ:TRAINING:WATCH:UNSORTED:~") (org-agenda-files (directory-files-recursively "~/org/work/" org-agenda-file-regexp))))
)
nil ;; settings
;; See: https://orgmode.org/manual/Exporting-Agenda-Views.html
;; ~M-x org-store-agenda-views~ outputs all files for all views.
;; Script export: ~emacs --batch -l ~/.emacs --eval '(org-store-agenda-views)'~
("/tmp/org_agenda_para.html" "/tmp/org_agenda_para.ics" "/tmp/org_agenda_para.txt")
)
("d" "Agenda for Today (Compact view for Exporting to displays)"
(
(agenda)
(tags "ACTION|CHASE|INVESTIGATE|INVESTIGATION|TRAVEL" ((org-agenda-overriding-header "Project: \"a series of tasks linked to a goal, with a deadline.\" ~:ACTION:CHASE:INVESTIGATE:INVESTIGATION:~")))
)
(
(org-agenda-span 1)
(org-agenda-use-time-grid nil)
)
("/tmp/org_agenda_today.html" "/tmp/org_agenda_today.ics" "/tmp/org_agenda_today.txt")
)
("i" "Personal agenda for last 2 weeks"
(
(agenda "")
)
(
(org-agenda-span 15)
(org-agenda-start-day "-14d")
(org-agenda-skip-function-global nil)
)
)
("y" "Personal agenda for month"
(
(agenda "")
)
(
(org-agenda-span 'month)
(org-agenda-skip-function-global nil)
)
)
("o" "Work agenda for last 2 weeks (1-2-1 Reviews)"
(
(agenda "" ((org-agenda-files (directory-files-recursively "~/org/work/" org-agenda-file-regexp))))
)
(
(org-agenda-span 15)
(org-agenda-start-day "-14d")
(org-agenda-skip-function-global nil)
)
)
("u" "Work Month view"
(
(agenda "" ((org-agenda-files (directory-files-recursively "~/org/work/" org-agenda-file-regexp))))
)
(
(org-agenda-span 'month)
(org-agenda-skip-function-global nil)
)
)
)
org-src-fontify-natively t
;; https://cachestocaches.com/2016/9/my-workflow-org-agenda/
org-columns-default-format "%50ITEM(Task) %5Effort(Est){:} %10CLOCKSUM %16TIMESTAMP_IA"
;; org-columns-default-format "%60ITEM %CATEGORY %TODO %TAGS %CLOCKSUM{:} %5Effort(Est){:} " ;; C-cC-xC-c in an Agenda view.
org-agenda-compact-blocks t ;; Compact agenda. Same as setting: `org-agenda-block-separator nil`.
org-agenda-include-diary t
org-agenda-tags-column 100 ;; Stop tags rendering off the right of the buffer.
org-agenda-skip-function-global '(org-agenda-skip-entry-if 'todo 'done) ;; Hide `DONE` lines from Agenda view.
org-complete-tags-always-offer-all-agenda-tags t
org-clock-persist t ;; Save clock on emacs exit.
org-clock-report-include-clocking-task t ;; Include current open clock task in reports.
)
)Repeated tasks / org#Tracking your habits:
- Enable
org-habitin agenda view: org#Tracking your habits. - Tag repeated tasks with a deadline (
C-cC-d). - Add the repeat [and reminder] value.
- Mark as done with
C-cC-t, which will log thatDOENand update the deadline to the next future point.
Repeat:
- every fortnight: put
+2winto deadline/schedule datetime. - daily, but next iteration is after today, if marking as
"DONE"after missing several days: put.+1dinto deadline/schedule datetime.
See: Sachachua: Org-mode and habits.
(use-package org
:custom
(org-habit-graph-column 60) ;; 40
(org-habit-preceding-days 30) ;; 21
(org-habit-show-all-today t)
:config
(add-to-list 'org-modules 'org-habit)
)Eval Org-modules. See: Sachachua: dotemacs#modules:
(eval-after-load 'org
'(org-load-modules-maybe t))(use-package ob-core
:custom
(
(org-confirm-babel-evaluate . nil)
)
)Initial babel core languages list:
Items like shell language supports multiple shells, but using those
shells does not work since the core is ob-shell not
ob-<sh|bash|dash|fish|zsh>.
;; active Babel languages
(org-babel-do-load-languages
'org-babel-load-languages
'(
(awk . t)
(C . t)
(css . t)
(dot . t)
(emacs-lisp . t)
(gnuplot . t)
(makefile . t)
(plantuml . t)
(python . t)
(shell . t)
(sql . t)
(sqlite . t)
)
)Also see:
See: StackOverflow: Org Bable Redirect stderr (-c option requires an argument).
Either:
- Redirect all output at the file level:
#+PROPERTY: header-args:shell :prologue "exec 2>&1" :epilogue ":" :results drawer - Redirect all output at the Heading level:
:PROPERTIES: :header-args:shell: :prologue "exec 2>&1" :epilogue ":" :results drawer :END:
NOTE: C-cC-c on the Property block to refresh for the file.
;; (make-directory "~/org/jira/" t)
;; (use-package org-jira
;; :ensure t
;; :defer t
;; :config
;; (setq
;; jiralib-url "https://eigentech.atlassian.net/"
;; org-jira-working-dir "~/org/jira/"
;; )
;; )org-mindmap (dead):
Lockywolf is no longer on Github, so just commenting this all out!
Modern Org Presentation solution.
Base config stolen from: Github: jypma/emacsconf2021/blob/master/presentation.org.
(defun my/presentation-setup ()
(shell-command "dunstctl set-paused true")
(turn-off-display-fill-column-indicator-mode)
(flyspell-mode 0)
(setq text-scale-mode-amount 3)
(org-display-inline-images)
(text-scale-mode 1)
(hide-mode-line-mode 1)
(display-line-numbers-mode 0)
;; (visual-fill-column-mode 1) ;; doesn't work in org-tree-slide
(visual-line-mode 1)
(font-lock-flush)
(font-lock-ensure))
(defun my/presentation-end ()
(shell-command "dunstctl set-paused false")
(turn-on-display-fill-column-indicator-mode)
(flyspell-mode 1)
(text-scale-mode 0)
(hide-mode-line-mode 0)
(display-line-numbers-mode 1)
(org-remove-inline-images)
;; (visual-fill-column-mode 0)
(visual-line-mode 0)
(font-lock-flush)
(font-lock-ensure))
(use-package org-tree-slide
:ensure t
;; Load immediately, since it messes with org-mode faces
:demand
:hook
((org-tree-slide-play . my/presentation-setup)
(org-tree-slide-stop . my/presentation-end))
:bind
(:map org-mode-map
("<f6>" . org-tree-slide-mode))
(:map org-tree-slide-mode-map
("p" . 'org-tree-slide-move-previous-tree)
("n" . 'org-tree-slide-move-next-tree)
)
:custom
(org-tree-slide-slide-in-effect nil)
(org-tree-slide-activate-message "Presentation started.")
(org-tree-slide-deactivate-message "Presentation ended.")
(org-tree-slide-header t)
(org-image-actual-width nil)
)Applying styles to TODO keywords in org files + allow multiple sequences.
See:
- org#Faces for TODO keywords.
- org#Multiple sets in one file.
C-S-<left>/<right>to jump sub-sequences (Ctrl-Shift-<left>/<right>).
(setq org-todo-keyword-faces
'(
("TODO" . org-warning)
("FUTURE" . (:foreground "black" :weight bold :background "DarkOrange1"))
("STARTED" . (:foreground "black" :background "gold1"))
("INPROGRESS" . (:foreground "white" :background "green4"))
("BLOCKED" . (:foreground "white" :weight bold :background "red4"))
("CANCELED" . (:foreground "blue" :weight bold :strike-through t))
("PARKED" . (:foreground "DarkGrey"))
)
)
(setq org-todo-keywords
'(
(sequence "TODO" "INPROGRESS" "BLOCKED" "|" "DONE" "CANCELED" "PARKED")
)
)Modes for drawing diagrams like: Ladder/Sequence, MindMaps, Class/Block/Object, UML diagrams.
.mscgen files are used to create diagrams from plaintext. These days I am
using UML/mermaid.
- http://www.mcternan.me.uk/mscgen/
- https://emacs-fu.blogspot.com/2010/04/creating-custom-modes-easy-way-with.html
(define-generic-mode
'mscgen-mode ;; name of the mode to create
'("#") ;; comments start with '#'
'("label" "note" "width"
"textcolour" "linecolour" "textbgcolour") ;; some keywords
'(("=" . 'font-lock-operator) ;; '=' is an operator
("=>" . 'font-lock-operator)
("->" . 'font-lock-operator)
(";" . 'font-lock-builtin) ;; ';' is a a built-in
("[" . 'font-lock-builtin)
("]" . 'font-lock-builtin)
("|" . 'font-lock-builtin)
)
'("\\.msc$") ;; files for which to activate this mode
nil ;; other functions to call
"A mode for mscgen files" ;; doc string for this mode
)
(defun mscgen-compile-buffer-hook()
"Compile command to generate a PNG from the current mscgen buffer.
See: https://stackoverflow.com/questions/6138029/how-to-add-a-hook-to-only-run-in-a-particular-mode
for the use of the hook."
(compile (concat "mscgen -T png " buffer-file-name " && mscgen -T svg " buffer-file-name))
(message (concat "Generated PNG/SVG for: " buffer-file-name))
)
(add-hook 'mscgen-mode-hook 'my-programming-defaults-config)
(add-hook 'mscgen-mode-hook
(lambda ()
(add-hook 'after-save-hook 'mscgen-compile-buffer-hook nil 'make-it-local)))Mermaid is a new plaintext diagram markup that has native rendering support in Github (See: Github Docs: Creating Diagrams). To render locally, you need to install: =mermaid-cli=. Example that should render natively in Github:
sequenceDiagram
A-->B: Works!
- Add to top of file and then
C-cC-cto both store errors in the RESULT block and to also ignore the puppeteer headless deprecation warning. NOTE: Minor spelling mistake in puppeteer for config #21:#+PROPERTY: header-args:mermaid :prologue "exec 2>&1" :epilogue ":" :pupeteer-config-file ~/.puppeteerrc - Add:
{"headless": "new"}to:~/.puppeteerrc.
brew install mermaid-cli` falls over with: ~Error: mermaid-cli has been
disabled because it installs a pre-built copy of Chromium!.
Which is mentioned in the Closed:WontFix issue: update brew formula to work
with 9.0.3 #288. Installing via npm globally instead.
C-cC-bin a mermaid code edit buffer to generate preview.
(use-package mermaid-mode
;; :ensure-system-package (mmdc . "npm install -g @mermaid-js/mermaid-cli")
:ensure t
:config
(setq
;; Use docker instead of the above global node package.
;; https://github.com/abrochard/mermaid-mode#mermaid-cli-in-docker
mermaid-mmdc-location "docker"
mermaid-flags "run --rm -v /tmp:/tmp ghcr.io/mermaid-js/mermaid-cli/mermaid-cli -w 1920"
)
)(use-package ob-mermaid
:ensure-system-package (mmdc . "npm install -g @mermaid-js/mermaid-cli")
:ensure t
:after (mermaid-mode)
:config
(setq ob-mermaid-cli-path "mmdc")
;; TODO: figure out how to pass tempfile into docker!
;; See: https://github.com/arnm/ob-mermaid/issues/24
;; (setq ob-mermaid-cli-path "docker run --rm -v /tmp:/tmp ghcr.io/mermaid-js/mermaid-cli/mermaid-cli")
(add-to-list 'org-babel-load-languages '(mermaid . t))
(org-babel-do-load-languages 'org-babel-load-languages org-babel-load-languages)
)Create architecture/design images with UML.
Here are some good org-babel plantuml examples: Github: dfeich/org-babel-examples/blob/master/plantuml/plantuml-babel.org.
NOTE: On Mac’s brew does not symlink OpenJDK by default, to not break
system packages. Run:
sudo ln -sfn /usr/local/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdkdocker run -d --name plantuml-server -p 8099:8080 plantuml/plantuml-server:jetty(defun plantuml-compile-buffer-hook()
"Compile command to generate a PNG from the current plantuml buffer."
(compile (concat "java -jar ~/org/plantuml.jar " buffer-file-name ";\njava -jar ~/org/plantuml.jar -tsvg " buffer-file-name))
(message (concat "Generated PNG for: " buffer-file-name))
)
(use-package plantuml-mode
;; https://plantuml.com/emacs
:ensure-system-package ((dot . graphviz) (java))
:ensure t
:after (org org-src)
;; FIXME: since my tree-sit change in python to use `python-mode`
;; everywhere, it seems to have broken the `.plantuml` look-up in
;; `auto-mode-alist`. ie. plantuml files open up with `python-mode` ??
:mode "\\.plantuml\\'"
:hook
(
(plantuml-mode . my-programming-defaults-config)
(plantuml-mode . (lambda () (add-hook 'after-save-hook 'plantuml-compile-buffer-hook nil 'make-it-local)))
)
:init
;; Enable plantuml-mode for PlantUML org code block
(add-to-list 'org-src-lang-modes '("plantuml" . plantuml))
:config
(setq
;; Use plantuml server, once: ~(setq plantuml-default-exec-mode 'server)~.
;; https://hub.docker.com/r/plantuml/plantuml-server
;; docker run -d --name plantuml-server -p 8099:8080 plantuml/plantuml-server:jetty
plantuml-default-exec-mode 'server
plantuml-server-url "http://localhost:8099"
;; ;; See: following issue for inability to use PlantUML server in org-babel:
;; ;; https://github.com/skuro/plantuml-mode/issues/165
;; org-plantuml-jar-path "~/org/plantuml.jar"
;; plantuml-jar-path "~/org/plantuml.jar"
;; plantuml-default-exec-mode 'jar
)
)(use-package docker
:ensure t
:defer t
:bind ("C-c d" . docker)
:custom
(
;; https://github.com/Silex/docker.el/issues/188
;; Don't use vterm everywhere.
(docker-run-async-with-buffer-function 'docker-run-async-with-buffer-shell)
(docker-container-columns '(
(:name "Names" :width 40 :template "{{ json .Names }}" :sort nil :format nil)
(:name "Status" :width 30 :template "{{ json .Status }}" :sort nil :format nil)
(:name "Image" :width 40 :template "{{ json .Image }}" :sort nil :format nil)
(:name "Id" :width 12 :template "{{ json .ID }}" :sort nil :format nil)
(:name "Ports" :width 20 :template "{{ json .Ports }}" :sort nil :format nil)
(:name "Command" :width 23 :template "{{ json .Command }}" :sort nil :format nil)
(:name "Created" :width 23 :template "{{ json .CreatedAt }}" :sort nil :format (lambda (x) (format-time-string "%F %T" (date-to-time x))))
)
)
)
)eglot uses: https://github.com/rcjsuen/dockerfile-language-server-nodejs.
(use-package dockerfile-mode
:ensure-system-package (docker-langserver . "npm install -g dockerfile-language-server-nodejs")
:ensure t
;; TODO: Raise bug about how this `:after` call breaks `eglot` automatically
;; running.
;; :after (eglot)
:hook
(
((dockerfile-mode dockerfile-ts-mode) . eglot-ensure)
((dockerfile-mode dockerfile-ts-mode) . (lambda () (set (make-local-variable 'compile-command) "docker build .")))
)
);; ( use-package kubernetes
;; ;; https://kubernetes-el.github.io/kubernetes-el/
;; :ensure t
;; :defer t
;; :commands (kubernetes-overview)
;; :init
;; ;; https://github.com/kubernetes-el/kubernetes-el/issues/265
;; ;; Work around: cyclic dependency.
;; ;; `Debugger entered--Lisp error: (invalid-function kubernetes-utils--save-window-state)`
;; (defmacro kubernetes-utils--save-window-state (&rest body)
;; `(let ((pos (point)) (col (current-column)) (window-start-line (window-start)) (inhibit-redisplay t))
;; (save-excursion ,@body)
;; (goto-char pos)
;; (move-to-column col)
;; (set-window-start (selected-window) window-start-line)))
;; )kele:
;; (use-package kele
;; :ensure t
;; :config
;; (kele-mode 1))Tramp into a docker container with: C-x C-f /docker:[user@]container:/path/to/file
Originally used: docker-tramp, but updated to latest Emacs29 (on 2022-10-25)
and now have this warning: ~ ■ Warning (emacs): Package ‘docker-tramp’ has been
obsoleted, please use integrated package ‘tramp-container’ [2 times]~, so
removing for: tramp-container.
NOTE: TRAMP natively supports Docker, Podman and Kubernetes. Need to look into how this will work in latest Emacs29 branch builds!!
(use-package ansible
; https://github.com/k1LoW/emacs-ansible
:ensure t
:defer t
:config
(progn
(add-hook 'yaml-mode-hook '(lambda () (ansible 1)))
)
(use-package ansible-doc
; https://github.com/lunaryorn/ansible-doc.el
:ensure t
:defer t
:hook (yaml-mode . ansible-doc-mode)
)
(use-package company-ansible
; https://github.com/krzysztof-magosa/company-ansible
:ensure t
:defer t
:after (company)
:config
(add-to-list 'company-backends 'company-ansible)
)
)Code completions. This can be done with the built-in completion-at-point
(C-M-i), but using company-mode for a drop down at point.
(use-package company
:ensure t
:defer t
:bind (:map company-active-map
("C-n" . company-select-next)
([(tab)] . company-complete)
)
:hook ((prog-mode . global-company-mode))
:config
(setq
company-tooltip-limit 20 ; bigger popup window.
company-idle-delay .3 ; decrease delay before autocompletion popup shows.
;; (setq company-backends (delete 'company-semantic company-backends))
)
)
Rate completions by use.
(use-package company-statistics
:ensure t
:after (company-mode)
:hook ((after-init . company-statistics-mode))
)++ C/CPP:
- https://emacs-lsp.github.io/lsp-mode/page/lsp-cmake/
pipenv install --dev cmake-language-server.- Bit weird, but need to activate pipenv on a python file in the repo, then reload the CMakeList.txt`.
(use-package cmake-mode
:ensure-system-package (cmake)
:ensure t
:hook ((cmake-mode . eglot-ensure))
)TODO:
- Move to
eglot.- Treesit mode is being picked up now but eglot is not enabled in the mode.
- Build
compile_commands.json.
See: Clangd Docs: Editor Plugins.
(use-package cc-mode
;; https://emacs-lsp.github.io/lsp-mode/page/lsp-clangd/
:ensure-system-package (clangd)
:ensure t
:after (eglot)
:hook (((c++-mode c++-ts-mode c-mode c-ts-mode) . eglot-ensure))
:config
(add-to-list 'major-mode-remap-alist '(c-mode . c-ts-mode))
(add-to-list 'major-mode-remap-alist '(c++-mode . c++-ts-mode))
(add-to-list 'major-mode-remap-alist '(c-or-c++-mode . c-or-c++-ts-mode))
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs '((c++-mode c++-ts-mode c-mode c-ts-mode) "clangd"))
)
)My very very old setup, long before LSP was a thing. Haven’t used it in about a decade.
;; (use-package cc-mode
;; ;; gdb on mac:
;; ;; brew tap homebrew/dupes && brew install gdb
;; ;; Note: gdb keybinding is: C-x C-a C-l, which I did have my rename term windows as.
;; :ensure t
;; :defer t
;; :bind (
;; ;; ("<f9>" . compile)
;; ([remap comment-region] . 'recompile) ; "C-c C-c"
;; ("M-." . 'xref-find-definitions) ; https://www.emacswiki.org/emacs/EmacsTags
;; )
;; :config
;; (progn
;; (use-package smart-compile
;; :ensure t
;; :defer t)
;; (use-package xcscope
;; ;; Use cscope files within emacs, to jump around C/C++ code.
;; ;; https://github.com/dkogan/xcscope.el
;; :ensure t
;; :defer t
;; :config
;; (progn
;; ;; Setup auto-magically hooks into c/c++ modes.
;; (cscope-setup)
;; )
;; (define-key c++-mode-map [remap c-set-style] 'cscope-find-this-symbol) ;; C-c .
;; ;; Note etags search defaults to: M-.
;; )
;; (use-package company-c-headers
;; ;; Complete c-headers
;; :ensure t
;; :defer t
;; :config
;; (push 'company-c-headers company-backends)
;; )
;; ;; cc-mode general settings.
;; ;; g++-4.9 -g3 -Wall -std=c++11 -stdlib=libc++ -lc++ *.cpp
;; ;; clang++ -g3 -Wall -std=c++11 -stdlib=libc++ -lc++ *.cpp
;; (add-to-list 'smart-compile-alist '("\\.[Cc]+[Pp]*\\'" . "clang++ -g3 -Wall -std=c++11 -stdlib=libc++ -lc++ -o %n.out *.cpp"))
;; (add-hook 'c-mode-common-hook 'my-programming-defaults-config)
;; (setq c-basic-offset 4) ;; http://emacswiki.org/emacs/IndentingC
;; (setq c-default-style "linux") ;; http://cc-mode.sourceforge.net/html-manual/Built_002din-Styles.html#Built_002din-Styles
;; ;; FIXME: Either bound this to `*compilation*` window only, so it stops
;; ;; jumping when I grep, or find the old stop-on-first-error behaviour I
;; ;; used to use.
;; (setq compilation-auto-jump-to-first-error nil)
;; )
;; (define-key c++-mode-map [remap comment-region] 'compile) ;; C-c C-c
;; )(use-package clang-format
;; Applies clang-format to C++ files based on a .clang-format file in the
;; project.
;; requires `clang-format` to be installed from system package manger.
:ensure-system-package (clang)
:ensure t
:after (cc-mode)
:config
(progn
(define-key c++-mode-map (kbd "C-c #") 'clang-format-region)
)
)Used to use this a decade ago. Not sure if it’s worth keeping now that LSP is the common way to offload completions and look-ups.
(defun create-tags (dir-name)
"Create tags file in directory: DIR-NAME."
(interactive "Directory: ")
(eshell-command
; (format "find %s -type f -name \"*.[ch]\" | etags -" dir-name))) ;; `.c`/`.h` in a non-git repo.
(format "cd $(git rev-parse --show-toplevel) && git ls-files | etags -" dir-name))) ;; tag all files.;; (use-package csharp-mode
;; :ensure t
;; ; :defer t
;; :config
;; (with-eval-after-load 'tramp
;; (add-to-list 'tramp-remote-path "~/.nix-profile/bin")
;; (add-to-list 'tramp-remote-path 'tramp-own-remote-path))
;; ;; (with-eval-after-load 'eglot
;; ;; ;; (add-to-list 'eglot-server-programs
;; ;; ;; '(csharp-mode . ,(eglot-alternatives
;; ;; ;; '(("~/Downloads/omnisharp-osx-arm64-net6.0/OmniSharp" "-lsp"))
;; ;; ;; )))
;; ;; (add-to-list 'eglot-server-programs
;; ;; '(csharp-ts-mode , ,(eglot-alternatives
;; ;; '(("csharp-ls"))
;; ;; )))
;; ;; )
;; ;; "/home/vscode/.cursor-server/extensions/nromanov.dotrush-25.5.135-linux-arm64/extension/bin/LanguageServer/DotRush"
;; ;; :hook
;; ;; (
;; ;; ((csharp-mode csharp-ts-mode) . (eglot-ensure))
;; ;; )
;; )FIXME: keep getting: `Unable to activate package ‘csharp-mode’.` messages, so disabling until I have time to re-implement with `lsp-mode`.
(defun my-csharp-mode-syntax ()
"Hook for my tweaks to 'csharp-mode'."
(interactive)
;; https://www.gnu.org/software/emacs/manual/html_node/efaq/Indenting-switch-statements.html
;; https://stackoverflow.com/questions/3954607/c-sharp-emacs-mode-questions-indentation-and-build#3956173
;; http://kirste.userpage.fu-berlin.de/chemnet/use/info/cc-mode/cc-mode_6.html
;; `C-cC-s` to see indent at point.
(c-set-offset `inline-open 0) ; Stop brackets being indented further on a method.
)
(use-package csharp-mode
;; https://jamiecollinson.com/blog/my-emacs-config/#c-1
:ensure t
:defer t
:init
(add-hook 'csharp-mode-hook 'my-programming-defaults-config)
(add-hook 'csharp-mode-hook 'my-csharp-mode-syntax)
;; https://stackoverflow.com/questions/4608679/can-i-change-emacs-default-compile-command
(add-hook 'csharp-mode-hook (lambda () (set (make-local-variable 'compile-command) "cd $(git rev-parse --show-toplevel) && dotnet run")))
(use-package omnisharp
;; https://github.com/OmniSharp/omnisharp-emacs
;; https://jamiecollinson.com/blog/my-emacs-config/#c-1
;; https://www.tuicool.com/articles/22a2Ejb
;; NOTE: Needs a project with a `.csproj` file to do completions. Done with:
;; `dotnet new <project_type>`
;; FIXME: Deferring since I don't have omnisharp installed. Currently not
;; doing csharp. Should do a check of packages installed.
:defer t
:after (company)
:bind (:map omnisharp-command-map
;; FIXME: Make these not global to C++ !!
("C-c f" . 'omnisharp-run-code-action-refactoring) ; Refactor/missing_imports/etc...
("M-." . 'omnisharp-go-to-definition)
)
:config
(add-hook 'csharp-mode-hook 'omnisharp-mode)
(add-to-list 'company-backends 'company-omnisharp))
(use-package coverlay
;; https://github.com/twada/coverlay.el
;; Coverage from an LCOV file.
;; Watch a file via: `M-x coverlay-watch-file /path/to/lcov-file`. or:
;; `C-c C-l w`.
:ensure t
:defer t
:init
(setq coverlay:mark-tested-lines nil)
)
)
;; (lsp-register-client
;; (make-lsp-client :new-connection (lsp-tramp-connection "/home/vscode/.dotnet/tools/csharp-ls")
;; :activation-fn (lsp-activate-on "cs")
;; :major-modes '(csharp-mode csharp-ts-mode)
;; :remote? t
;; :server-id 'csharp-ls-remote))
(setq lsp-csharp-server-path "/home/vscode/.dotnet/tools/csharp-ls")TODO: switch over to eglot!
(use-package css-mode
; https://emacs-lsp.github.io/lsp-mode/page/lsp-css/
:ensure t
:ensure-system-package (vscode-langservers-extracted)
:defer t
:hook ((css-mode css-ts-mode) . eglot-ensure)
)(use-package csv-mode
:ensure t
:defer t)(use-package dap-mode
:if (not (eq system-type 'windows-nt)) ;; FIXME: (void-function dap-ui-mode)
:ensure t
:defer t
:after (lsp hydra)
:bind (
([f6] . dap-hydra)
([f7] . 'dap-ui-repl)
)
:commands
(
dap-mode
dap-ui-mode
dap-tooltip-mode
dap-ui-controls-mode
)
:config
(setq
;; NOTE: For Python. install: `debugpy` python package in the project!
dap-python-debugger 'debugpy ;; The default: `ptvsd` is deprecated!
dap-ui-variable-length 1000 ;; https://github.com/emacs-lsp/dap-mode/issues/416 - don't truncate `locals` variables.
dap-internal-terminal 'dap-internal-terminal-shell ;; Forgotten how to scroll `vterm` so using shell.
)
;; https://www.reddit.com/r/emacs/comments/tckmb2/dapmode_breakpoints_not_showing_when_in_terminal/
(add-hook 'dap-stopped-hook
(lambda (arg) (call-interactively #'dap-hydra)))
)
;; (use-package dap-LANGUAGE) to load the dap adapter for your language
(with-eval-after-load 'dap-faces
(unless (display-graphic-p)
(set-face-background 'dap-ui-marker-face "color-166") ; An orange background for the line to execute
(set-face-attribute 'dap-ui-marker-face nil :inherit nil) ; Do not inherit other styles
(set-face-background 'dap-ui-pending-breakpoint-face "blue") ; Blue background for breakpoints line
(set-face-attribute 'dap-ui-verified-breakpoint-face nil :inherit 'dap-ui-pending-breakpoint-face)
)
)Dape (Debug Adapter Protocol) for Emacs:
Alternative to dap-mode that uses all built-ins to interact with
per-language debuggers installed on the Host.
;; Changing Modeline colours when debugging. Based off:
;; https://amitp.blogspot.com/2025/04/emacs-per-project-colors.html.
;; TODO: Set for the =project-current=, so it's maintained when
;; jumping to other files during debugging.
(defun my-debug-modeline ()
"Set mode line color based on current buffer's project"
(interactive)
(face-remap-add-relative 'tab-line-tab-current :background "red" :foreground "white")
(face-remap-add-relative 'mode-line-active :background "red" :foreground "white")
(face-remap-add-relative 'line-number-current-line :background "red" :foreground "white")
)
(defun my-normal-modeline ()
"Set mode line color based on current buffer's project"
(interactive)
(face-remap-add-relative 'tab-line-tab-current :background "goldenrod" :foreground "black")
(face-remap-add-relative 'mode-line-active :foreground "black" :background "goldenrod")
(face-remap-add-relative 'line-number-current-line :background "goldenrod" :foreground "black")
)
(use-package dape
:ensure t
:preface
;; By default dape shares the same keybinding prefix as `gud'
;; If you do not want to use any prefix, set it to nil.
;; (setq dape-key-prefix "\C-x\C-a")
:hook
;; Save breakpoints on quit
(kill-emacs . dape-breakpoint-save)
;; Load breakpoints on startup
(after-init . dape-breakpoint-load)
:config
;; Turn on global bindings for setting breakpoints with mouse
(dape-breakpoint-global-mode)
;; Info buffers to the right
;; (setq dape-buffer-window-arrangement 'right)
;; Info buffers like gud (gdb-mi)
;; (setq dape-buffer-window-arrangement 'gud)
;; (setq dape-info-hide-mode-line nil)
;; Pulse source line (performance hit)
(add-hook 'dape-display-source-hook 'pulse-momentary-highlight-one-line)
;; Showing inlay hints
(setq dape-inlay-hints t)
;; Save buffers on startup, useful for interpreted languages
;; (add-hook 'dape-start-hook (lambda () (save-some-buffers t t)))
(add-hook 'dape-start-hook #'my-debug-modeline)
;; FIXME: This hook isn't called on: `dape-quit` so adding an
;; advice.
;; (add-hook 'dape-stopped-hook #'my-normal-modeline)
(defadvice dape-quit (after after-dape-quit)
(my-normal-modeline))
(ad-activate 'dape-quit)
;; Kill compile buffer on build success
;; (add-hook 'dape-compile-hook 'kill-buffer)
;; Projectile users
;; (setq dape-cwd-function 'projectile-project-root)
)
;; Enable repeat mode for more ergonomic `dape' use
(use-package repeat
:ensure t
:config
(repeat-mode))See:
- https://dev.to/dorneanu/mastering-golang-debugging-in-emacs-34p7.
- Github: svaante/dape - Debug go program via tramp #109 via ssh configured host + ssh tunnel to route to delve on remote system.
- https://github.com/go-delve/delve
- https://github.com/svaante/dape?tab=readme-ov-file#go—dlv
- https://github.com/svaante/dape/wiki#go—dlv
(use-package dape
:config
(add-to-list 'dape-configs
;; https://dev.to/dorneanu/mastering-golang-debugging-in-emacs-34p7
;; Profile 1: Launch application and start DAP server
`(go-debug-locally
modes (go-mode go-ts-mode)
command "dlv"
;; Debug port != Application port.
command-args ("dap" "--listen" "127.0.0.1::autoport")
command-cwd default-directory
;; TODO: Do I want to run compiler before debugging?
;; Also, the hook that kills the compilation buffer,
;; still leaves the buffers split.
;;compile "go build"
host "127.0.0.1"
port :autoport
:request "launch"
:mode "debug"
:type "go"
:showLog "true"
:program default-directory
))
(add-to-list 'dape-configs
;; Profile 2: Attach to external debugger eg. `make debug`
`(go-debug-remote
modes (go-mode go-ts-mode)
command "dlv"
port 50000
:request "attach" ;; this will run "dlv attach ..."
:mode "remote" ;; connect to a running debugger session
:type "go"
))
(add-to-list 'dape-configs
;; Profile 3: Attach to debugger in docker container eg. `make debug`
`(go-debug-docker
modes (go-mode go-ts-mode)
command "dlv"
port 50000
:request "attach" ;; this will run "dlv attach ..."
:mode "remote" ;; connect to a running debugger session
:type "go"
;; https://github.com/emacs-lsp/dap-mode/blob/b97756665709bea37b9ffe262c5fa9196f1b4577/docs/page/configuration.md?plain=1#L622
;; Set `from` as absolute path to repo root and map to code root in container.
:substitutePath (vector (ht ("from" (funcall dape-cwd-fn)) ("to" "/app")))
))
(add-to-list 'dape-configs
`(go-debug-testcase-locally
modes (go-mode go-ts-mode)
ensure dape-ensure-command
fn (dape-config-autoport dape-config-tramp)
command "dlv"
command-insert-stderr t
command-args ("dap" "--listen" "127.0.0.1::autoport")
command-cwd (lambda()(if (string-suffix-p "_test.go" (buffer-name))
default-directory (dape-cwd)))
port :autoport
:type "debug"
:request "launch"
:mode (lambda() (if (string-suffix-p "_test.go" (buffer-name)) "test" "debug"))
:program "."
:cwd "."
:args (lambda()
(require 'which-func)
(if (string-suffix-p "_test.go" (buffer-name))
(if-let* ((test-name (which-function))
(test-regexp (concat "^" test-name "$")))
; Debug testcase
`["-test.run" ,test-regexp]
; Debug all tests
`["-test.v"])))
))
)See:
- https://github.com/svaante/dape?tab=readme-ov-file#javascript—vscode-js-
- Assumption: unpack
https://github.com/microsoft/vscode-js-debug/releases/ to
~/Downloads/.
- Assumption: unpack
https://github.com/microsoft/vscode-js-debug/releases/ to
- https://github.com/svaante/dape/wiki#nodejs-vscode-js-debug
- https://www.snamellit.com/blog/dape/
(use-package dape
:config
(add-to-list 'dape-configs
`(js-ts-debug-locally
modes (js-mode js-ts-mode typescript-mode typescript-ts-mode)
host "localhost"
port :autoport
command "node"
command-cwd ,(file-name-concat gnus-home-directory "Downloads/js-debug/")
command-args ("src/dapDebugServer.js" :autoport)
:type "pwa-node"
:request "launch"
:cwd dape-cwd-fn
:outputCapture "console"
:program dape-buffer-default
:sourceMapRenames t
:pauseForSourceMap nil
:enableContentValidation t
:autoAttachChildProcesses t
:console "internalConsole"
:killBehavior "forceful"))
)(use-package realgud
:ensure t
:defer t)Major mode for .env files.
(use-package dotenv-mode
:ensure t)(add-hook 'emacs-lisp-mode-hook 'my-programming-defaults-config)
;; code from: http://www.emacswiki.org/emacs/EmacsLispMode
(add-hook 'emacs-lisp-mode-hook
(lambda ()
;; Pretty-print eval'd expressions.
(define-key emacs-lisp-mode-map
"\C-x\C-e" 'pp-eval-last-sexp)
;; ;; Recompile if .elc exists. ;; recompiles everything on every save -cas
;; (add-hook (make-local-variable 'after-save-hook)
;; (lambda ()
;; (byte-force-recompile default-directory)))
(define-key emacs-lisp-mode-map
"\r" 'reindent-then-newline-and-indent)))
(add-hook 'emacs-lisp-mode-hook 'eldoc-mode)FIXME: erlang mode is throwing errors on start in latest emacs28!!
;; (use-package erlang
;; ;; (require 'erlang-start)
;; :ensure t
;; :defer t
;; )(use-package feature-mode
:ensure t
:defer t
:mode "\\.spec\\'"
)Required by M-x org-plot/gnuplot.
(use-package gnuplot
:ensure-system-package (gnuplot)
:ensure t
:defer t
)Mode for editing gnuplot files.
(use-package gnuplot-mode
:ensure t
:defer t
)Go config links:
- https://andrewjamesjohnson.com/configuring-emacs-for-go-development/.
- https://legends2k.github.io/note/go_setup/.
- Github Gist: GnaneshKunai/go-ts-fmt.el.
- https://arenzana.org/2019/01/emacs-go-mode/.
- https://honnef.co/articles/writing-go-in-emacs/ & https://honnef.co/articles/writing-go-in-emacs-cont./.
- https://github.com/golang/go/wiki/IDEsAndTextEditorPlugins.
- https://dev.to/dorneanu/mastering-golang-debugging-in-emacs-34p7.
Requires go, gopls & delve to be installed. See:
- https://github.com/golang/tools/tree/master/gopls
- https://emacs-lsp.github.io/lsp-mode/page/lsp-gopls/
- https://github.com/go-delve/delve/tree/master/Documentation/installation
# On macOS make sure you also install the command line developer tools: xcode-select --install # If you didn't enable Developer Mode using Xcode you will be asked to # authorize the debugger every time you use it. To enable Developer Mode # and only have to authorize once per session use: sudo /usr/sbin/DevToolsSecurity -enable # You might also need to add your user to the developer group: sudo dscl . append /Groups/_developer GroupMembership $(whoami)
Also see: Add optional support for tree-sitter #396, which is tracking issues
with supporting the new go-ts-mode.
(use-package go-mode
:ensure-system-package ((go) (gopls) (dlv . delve))
:ensure t
:after eglot
:functions flycheck-mode
:preface
(defun cas/go-config ()
"Tame tab indenting for go mode."
(setq tab-width 4)
(setq go-ts-mode-indent-offset 4)
(setq indent-tabs-mode t)
(add-hook 'before-save-hook #'eglot-format-buffer -10 t)
(add-hook 'before-save-hook #'gofmt-before-save)
;; Need the above line to load the: ~gofmt~ package in emacs. Why!?
;; (add-hook 'before-save-hook 'gofmt nil t)
(if (not (string-match "go" compile-command))
(set (make-local-variable 'compile-command)
"cd $(git rev-parse --show-toplevel)/ && go mod tidy && go generate ./... && go build -v && go test -v && go vet && go run ."))
)
:hook (
((go-mode go-ts-mode) . cas/go-config)
((go-mode go-ts-mode) . eglot-ensure)
)
)Debug Go programs with: Delve, via: go-dlv on top of realgud.
For help either look at: Github:
go-delve/delve/blob/master/Documentation/cli/README.md, or: help in a
running delve process.
Typical workflow might be:
- Debug Tests:
M-x dlv <return> dlv test <return>, Debug App:dlv debug. - Set Breakpoint:
b <file>:<line>, List:bp, toggle:toggle <int> - Start/Continue:
c. - Step:
s, Step Over:n, Step Out:n. - Print variable:
p <variable>. - Call function:
call <func>. - Restart:
r. **NOTE:** need to restart debug session to pick up file changes!! - Exit:
exit
(use-package go-dlv
:ensure-system-package (delve)
:ensure t
:after (realgud)
)Go support in org-code blocks.
(use-package ob-go
:ensure t
:config
(add-to-list 'org-babel-load-languages '(go . t))
(org-babel-do-load-languages 'org-babel-load-languages org-babel-load-languages)
)This will allow the following code block to run:
fmt.Println("Current Time:", time.Now())(use-package graphql-mode
:ensure t
:defer t
)Dependency on GraphQL-mode to do requests.
(use-package request
:ensure t
:defer t
)(use-package groovy-mode
; https://github.com/Groovy-Emacs-Modes/groovy-emacs-modes
:ensure t
:defer t
:mode (
("\\.groovy\\'" . groovy-mode)
("\\Jenkinsfile*\\'" . groovy-mode)
)
:config
(progn
(add-hook 'groovy-mode-hook 'my-programming-defaults-config)
)
); https://emacs-lsp.github.io/lsp-mode/page/lsp-html/
;; (add-hook 'html-mode-hook 'lsp)(use-package i3wm-config-mode
:ensure t
:defer t)See: InnoSetup mode: https://jrsoftware.org/isinfo.php
(use-package iss-mode
:mode "\\.iss\\'"
:ensure t
:defer t
:init
(setq iss-compiler-path "C:/Program Files (x86)/Inno Setup 6")
)(defun my-java-mode-syntax ()
"Hook for my tweaks to `java-mode`."
(interactive)
;; https://www.gnu.org/software/emacs/manual/html_node/efaq/Indenting-switch-statements.html
(c-set-offset 'case-label '+) ; A "case" or "default" label.
(c-set-offset 'brace-list-entry '++) ; Subsequent lines in an enum or static array list.
(c-set-offset `arglist-intro `+) ; function fields on a new line.
)
;; https://writequit.org/eos/eos-java.html
;; https://github.com/dakrone/emacs-java-imports
;; https://github.com/mopemope/meghanada-emacs
(use-package meghanada
:ensure t
:defer t
:init
(add-hook 'java-mode-hook #'meghanada-mode)
(add-hook 'java-mode-hook 'flycheck-mode)
(add-hook 'java-mode-hook 'my-programming-defaults-config)
;; Java warnings stop compilation scrolling, so let's always scroll.
(add-hook 'java-mode-hook (lambda() compilation-scroll-output t))
(add-hook 'java-mode-hook (lambda () compile-command "cd $(git rev-parse --show-toplevel) && mvn clean verify"))
(add-hook 'java-mode-hook 'my-java-mode-syntax)
)
(use-package mvn
:ensure t
:defer t
:init
;; Correctly colourise the compilation buffer for maven calls.
;; https://github.com/apg/mvn-el
(ignore-errors
(require 'ansi-color)
(defun colorize-compilation-buffer ()
(when (eq major-mode 'compilation-mode)
(let ((inhibit-read-only t))
(if (boundp 'compilation-filter-start)
(ansi-color-apply-on-region compilation-filter-start (point))))))
(add-hook 'compilation-filter-hook 'colorize-compilation-buffer))
);; https://github.com/codesuki/add-node-modules-path
;; (use-package add-node-modules-path
;; :ensure t
;; :defer t
;; )
;; https://github.com/jscheid/prettier.el
;; (use-package prettier
;; :ensure t
;; :defer t
;; )
; https://github.com/prettier/prettier-emacs
; Requires global prettier install: `npm install -g prettier`.
;; (use-package prettier-js
;; :ensure t
;; :defer t
;; )
; https://emacs.cafe/emacs/javascript/setup/2017/05/09/emacs-setup-javascript-2.html
; https://emacs-lsp.github.io/lsp-mode/tutorials/reactjs-tutorial/ = ts-ls.
; https://emacs-lsp.github.io/lsp-mode/page/lsp-eslint/
; https://classic.yarnpkg.com/en/docs/cli/global
; - move yarn global install path to home dir and then install eslint globally.
; `yarn config set prefix ~/.yarn`
; `npx -p node@14 yarn global add eslint`
; `M-x lsp-install-server <ret> eslint <ret>`
(use-package js2-mode
:ensure t
:defer t
:mode ("\\.js\\'" "\\.jsx\\'" "\\.mjs\\'")
:hook (
;; (js2-mode . add-node-modules-path)
;; (js2-mode . prettier-js-mode) ; runs prettier on save.
;; (js2-mode . prettier-mode) ; runs prettier on save.
(js2-mode . eglot-ensure)
)
;; :config
)
;; FIXME: need to update the path to my local node-modules for my project that
;; is in a sub-directory of the repo.
;; (use-package eslint-fix
;; ; https://github.com/codesuki/eslint-fix
;; :ensure t
;; :defer t
;; :hook (
;; (js-mode . selint-fix)
;; (js2-mode . selint-fix)
;; )
;; :init
;; (setq eslint-fix-executable "npx eslint")
;; )
(use-package json-mode
:ensure t
:defer t
:mode ("\\.json\\'" . json-mode)
:hook (
(json-mode . my-programming-defaults-config)
(json-mode . (lambda () (auto-fill-mode -1))) ;; disables auto fill at column.
(json-mode . (lambda () (setq js-indent-level 2)))
)
);; *****************************************************
;; *****************************************************
;; Json programming
;; *****************************************************
;; *****************************************************
; TODO: Figure out which package is requiring `json-reformat` ??
;; Debugger entered--Lisp error: (file-missing "Cannot open load file" "No such file or directory" "json-reformat")
;; require(json-reformat)
;; byte-code("\300\301!\210\300\302!\210\300\303!\210\300\304!\210\305\306\307\310\311\301%\207" [require js rx json-snatcher json-reformat custom-declare-group json-mode nil "Major mode for editing JSON files." :group] 6)
;; json-mode()
;; set-auto-mode-0(json-mode nil)
;; set-auto-mode--apply-alist((("\\.iss\\'" . iss-mode) ("\\.msc$" . mscgen-mode) ("\\.rcp\\'" . emacs-lisp-mode) (".*mutt.*" . mail-mode) ("\\.plantuml\\'" . plantuml-mode) ("\\.odc\\'" . archive-mode) ("\\.odf\\'" . archive-mode) ("\\.odi\\'" . archive-mode) ("\\.otp\\'" . archive-mode) ("\\.odp\\'" . archive-mode) ("\\.otg\\'" . archive-mode) ("\\.odg\\'" . archive-mode) ("\\.ots\\'" . archive-mode) ("\\.ods\\'" . archive-mode) ("\\.odm\\'" . archive-mode) ("\\.ott\\'" . archive-mode) ("\\.odt\\'" . archive-mode) ("\\.mjs\\'" . js2-mode) ("\\.jsx\\'" . js2-mode) ("\\.js\\'" . js2-mode) ("\\.py\\'" . python-mode) ("\\.restclient\\'" . restclient-mode) ("\\.json\\'" . json-mode) ("\\.yaml\\'" . yaml-mode) ("\\.yml\\'" . yaml-mode) ("\\.\\(e?ya?\\|ra\\)ml\\'" . yaml-mode) ("\\.md\\'" . markdown-mode) ("\\Jenkinsfile*\\'" . groovy-mode) ("\\.groovy\\'" . groovy-mode) ("\\.php\\'" . php-mode) ("\\.\\(?:php[s345]?\\|phtml\\)\\'" . php-mode-maybe) ("\\.\\(?:php\\.inc\\|stub\\)\\'" . php-mode) ("/\\.php_cs\\(?:\\.dist\\)?\\'" . php-mode) ("web.config$" . xml-mode) ("\\.cmake\\'" . cmake-mode) ("CMakeLists\\.txt\\'" . cmake-mode) ("\\.tsv\\'" . tsv-mode) ("\\.[Cc][Ss][Vv]\\'" . csv-mode) ("\\.dockerfile\\'" . dockerfile-mode) ("/Dockerfile\\(?:\\.[^/\\]*\\)?\\'" . dockerfile-mode) ("\\.hrl\\'" . erlang-mode) ("\\.erl\\'" . erlang-mode) ("/ebin/.+\\.app" . erlang-mode) ("\\.yrl" . erlang-mode) ("\\.xrl$" . erlang-mode) ("\\.hrl$" . erlang-mode) ("\\.escript" . erlang-mode) ("\\.app\\.src$" . erlang-mode) ("\\.erl$" . erlang-mode) ("go\\.mod\\'" . go-dot-mod-mode) ...) nil nil)
;; set-auto-mode()
;; normal-mode(t)
;; after-find-file(nil nil)
;; find-file-noselect-1(#<buffer package.json> "~/work/Apollo/Unlock/unlock_webui/package.json" :nowarn nil "~/work/Apollo/Unlock/unlock_webui/package.json" (27399170 66307))
;; find-file-noselect("/home/craig/work/Apollo/Unlock/unlock_webui/packag..." :nowarn)
;; desktop-restore-file-buffer("/home/craig/work/Apollo/Unlock/unlock_webui/packag..." "package.json" nil)
;; desktop-create-buffer(208 "/home/craig/work/Apollo/Unlock/unlock_webui/packag..." "package.json" fundamental-mode (override-global-mode global-whitespace-mode company-mode projectile-mode which-key-mode dap-mode global-auto-revert-mode) 2720 (nil nil) nil nil ((buffer-display-time 24951 42966 348475 416000) (buffer-file-coding-system . utf-8-unix)) ((mark-ring nil)))
;; eval-buffer(#<buffer *load*> nil "/home/craig/.emacs.desktop" nil t) ; Reading at buffer position 15343
;; load-with-code-conversion("/home/craig/.emacs.desktop" "/home/craig/.emacs.desktop" t t)
;; load("/home/craig/.emacs.desktop" t t t)
;; desktop-read()
;; #f(compiled-function () #<bytecode -0x19a5bc467a428ba3>)()
;; run-hooks(after-init-hook delayed-warnings-hook)
;; command-line()
;; normal-top-level()
(use-package json-reformat
:ensure t
:defer t)Setup Flycheck (Code checking on the fly (replaces flymake)). Used to run this for years, but moving back to using emacs built-ins.
(use-package flycheck ; On-the-fly syntax checking
:ensure t
:defer t
:bind (:map flycheck-mode-map
("C-c e" . list-flycheck-errors)
("C-c T f" . flycheck-mode)
("C-c j" . flycheck-next-error)
)
;; :init (global-flycheck-mode)
:config
(progn
(setq
flycheck-completion-system 'ido
flycheck-highlighting-mode 'lines
flycheck-display-errors-delay 0.0
flycheck-flake8-maximum-complexity 10
flycheck-flake8rc "setup.cfg"
flycheck-highlighting-mode (quote lines)
;; Set the standard library to libc++ so that C++11 headers will work
flycheck-clang-standard-library "libc++"
)
(set-face-attribute 'flycheck-error nil :background "DarkRed") ; dark red
(set-face-attribute 'flycheck-warning nil :background "DarkBlue") ; dark blue
(set-face-attribute 'flycheck-info nil :background "DarkGreen") ; dark green
;; Use italic face for checker name
(set-face-attribute 'flycheck-error-list-checker-name nil :inherit 'italic)
)
:diminish flycheck-mode)
(flycheck-mode flycheck-mode-line) ; Flycheck status
'(flycheck-error-list-column-number ((t (:inherit font-lock-constant-face :background "blue"))))
'(flycheck-warning ((t (:background "DarkBlue" :underline (:color "DarkOrange" :style wave)))))
;; ;; Chain modes after `lsp`.
;; ;; https://rat.dev/flycheck/flycheck/issues/1762
;; (defvar-local my/flycheck-local-cache nil)
;; (defun my/flycheck-checker-get (fn checker property)
;; (or (alist-get property (alist-get checker my/flycheck-local-cache))
;; (funcall fn checker property)))
;; (advice-add 'flycheck-checker-get :around 'my/flycheck-checker-get)
;; (add-hook 'lsp-managed-mode-hook
;; (lambda ()
;; (when (derived-mode-p 'python-mode)
;; (setq my/flycheck-local-cache '((lsp . ((next-checkers . (python-pylint)))))))))Log file highlighting
(use-package log4j-mode
:ensure t
:defer t
:mode "\\.log\\'"
)
'(log4j-font-lock-fatal-face ((t (:foreground "darkred" :weight bold))))
'(log4j-font-lock-info-face ((t (:foreground "ForestGreen"))))
'(log4j-font-lock-warn-face ((t (:foreground "orange"))))lsp-mode is the external, feature-rich version of: [[*\[\[https://joaotavora.github.io/eglot/\]\[eglot\]\]:][eglot]] (built-in), for
interacting with LSP Servers in emacs.
Seeing LSP and other packages blowing up on this missing requirement.
(use-package posframe
:ensure t
:defer t
);; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l")
(setq lsp-keymap-prefix "s-l")
(use-package lsp-mode
:ensure t
:defer t
:hook (;; replace XXX-mode with concrete major-mode(e. g. python-mode)
;; Python workflow:
;; * `pipenv install --dev python-language-server[all]`.
;; * Start pipenv: `C-cC-pa`.
;; * Start lsp: `M-x lsp`.
(rust-mode . lsp)
;; if you want which-key integration
(lsp-mode . lsp-enable-which-key-integration)
(lsp-mode . my-programming-defaults-config)
)
:commands lsp
:config
(setq
lsp-file-watch-threshold 20000
gc-cons-threshold 100000000
read-process-output-max (* 1024 1024 4) ;; 4MB
)
)(use-package lsp-ui
;; https://github.com/emacs-lsp/lsp-ui
:ensure t
:defer t
:after (lsp)
:commands (
lsp-ui-mode
lsp-ui-peek-mode
lsp-ui-sideline-mode
)
:bind (:map lsp-command-map
([remap xref-find-definitions] . #'lsp-ui-peek-find-definitions) ;; M-.
([remap xref-find-references] . #'lsp-ui-peek-find-references) ;; M-?
)
:config
(setq
lsp-ui-doc-show-with-cursor t
)
)(use-package lsp-treemacs
:after (lsp))I preferred jedi over rope for ease of setup and usage, but have moved away from Jedi for pyright ([[*\[\[https://emacs-lsp.github.io/lsp-pyright/\]\[lsp-pyright\]\]:][lsp-pyright]]) since it is installed outside of dependencies (so more consistent usage with emacs across repos + no longer have to fight to install dev dependencies for local editor completions). See: https://github.com/pappasam/jedi-language-server.
;; (use-package lsp-jedi
;; :ensure t
;; :defer t
;; :after (python-mode lsp)
;; )My Current choice of sourcing completions for python: Github: emacs-lsp/lsp-pyright.
(use-package lsp-pyright
:disabled
;; :ensure t
:defer t
:after (python-mode lsp)
:hook (python-mode . (lambda ()
(require 'lsp-pyright)
(lsp)))) ; or lsp-deferredNOTE: Working on some code that prevents me installing Jedi due to dependency conflicts. Trying out MS Python, but eventually moved over to: [[*\[\[https://emacs-lsp.github.io/lsp-pyright/\]\[lsp-pyright\]\]:][lsp-pyright]]. Error:
(ignore-error module-not-gpl-compatible ;; Added ingore-error due to noise from tree-sitter-langs `python.dylib`. ;; See: https://github.com/emacs-tree-sitter/elisp-tree-sitter/issues/100 for a similar problem on NixOS. )
(use-package lsp-python-ms
:disabled
;; :ensure t
:defer t
:after (python-mode lsp)
:init (setq lsp-python-ms-auto-install-server t)
:hook (python-mode . (lambda ()
(require 'lsp-python-ms)
;; Using `lsp-deferred` since it handles showing
;; errors in the buffer after the MS LSP agent has
;; finished analysis (instead of `lsp`).
(lsp-deferred))))LSP Bridge (SSH/DevContainers):
Used to connect to LSP Servers in remote systems for lsp-mode.
BROKEN: Requires:
- Python packages.
- No byte compiling.
- Expects
straightto install, since it’s not in melpa.
;; (use-package lsp-bridge
;; :vc (:url "https://github.com/manateelazycat/lsp-bridge.git"
;; :rev :newest)
;; :ensure t
;; :config
;; (global-lsp-bridge-mode)
;; )(use-package lua-mode
:ensure t
:defer t
:hook (lua-mode . eglot-ensure)
)make-mode (built-in):
FIXME: remove the eglot-ensure hook on prog-mode, since there is no
lsp-server for Makefile’s.
(use-package make-mode
:ensure t
:preface
(defun cas/make-mode-config ()
"Set config just for Makefile buffers."
(setq indent-tabs-mode t)
;; (remove-hook 'prog-mode-hook 'eglot-ensure)
)
:hook ((makefile-mode . cas/make-mode-config))
)NOTE:
flymdlooks to be broken and unmaintained. Useimpatient-modefor live previews.M-x markdown-preview, requires:markdown, to be installed with system package manager.
Look at:
;; https://www.emacswiki.org/emacs/KeyboardMacros
;; https://www.emacswiki.org/emacs/KeyboardMacrosTricks
(fset 'convert-markdown-ref-to-list
"\C-[xreplace-regexp\C-m\\[\\(.*\\)\\].*\C-m* [\\1].\C-m")
(fset 'convert-markdown-github-url-to-ref
"\C-[xreplace-regexp\C-m.*github.com/\\(.*\\)/\\(.*\\)\C-m[Github: \\1/\\2]: https://github.com/\\1/\\2\C-m")
;; FIXME: figure out how to feed the `LFD` or `C-qC-j` without it
;; counting as a real `RET` and breaking the `replace-regexp` with:
;; `\\(` !!
(defalias 'strip-a-ids-from-org-markdown-export
(kmacro "M-< M-x r e p l a c e - r e g e x p RET \\ ( < a SPC i d = .* > < / a > \\ ) RET RET"))
(use-package markdown-mode
;; ~markdown~ in arch package manager.
;; :ensure-system-package (markdown) ;; Required by ~M-x markdown-preview~.
:ensure t
:ensure-system-package (marksman)
:mode ("README\\.md\\'" . gfm-mode)
;; multimarkdown is in brew/yay, but not pulling down on arch??
;; :init (setq markdown-command "multimarkdown")
:bind (
("C-c C-a b" . convert-markdown-ref-to-list)
("C-c C-a g" . convert-markdown-github-url-to-ref)
("C-c C-a s" . strip-a-ids-from-org-markdown-export)
)
:hook (
(markdown-mode . my-text-mode-config)
(markdown-mode . eglot-ensure)
)
)impatient-mode is a way of doing live previews of the current buffer in a web
browser.
(use-package impatient-mode
; start webserver with: `M-x httpd-start`.
; Then set the mode on the buffer: `M-x impatient-mode`.
:ensure t
:defer t
)http-start doesn’t blow up when port is in use, so this ends up
sending the impatient-mode generated URL to whatever service is already
running on the default port of 8080.
See: https://blog.bitsandbobs.net/blog/emacs-markdown-live-preview/
(defun my-markdown-filter (buffer)
"Function to allow `impatient-mode` to preview markdown. Usage:
* `M-x httpd-start`
* Go to required BUFFER.
* `M-x impatient-mode`
* `M-x imp-set-user-filter RET markdown-html RET`"
(princ
(with-temp-buffer
(let ((tmp (buffer-name)))
(set-buffer buffer)
(set-buffer (markdown tmp))
(format "<!DOCTYPE html><html><title>Markdown preview</title><link rel=\"stylesheet\" href = \"https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.min.css\"/>
<body><article class=\"markdown-body\" style=\"box-sizing: border-box;min-width: 200px;max-width: 980px;margin: 0 auto;padding: 45px;\">%s</article></body></html>" (buffer-string))))
(current-buffer)))
(defun my-markdown-preview ()
"Preview markdown."
(interactive)
(unless (process-status "httpd")
(setq httpd-port 8088)
(httpd-start))
(impatient-mode)
(imp-set-user-filter 'my-markdown-filter)
(imp-visit-buffer))(use-package html-to-markdown
;; Convert html code to markdown.
:ensure t
:defer t)(use-package markdown-toc
;; https://github.com/ardumont/markdown-toc
;; Used to generate a table of contents in a markdown file.
:ensure t
:defer t)ox-gfm (export):
I’m not a fan of: M-x org-md-export-as-markdown, since it adds a
load of space around sections and bullet points.
(use-package ox-gfm
:ensure t);; CLI tools installed by Mise
;; See: https://www.emacswiki.org/emacs/ExecPath
(setenv "PATH" (concat (getenv "PATH") ":" (expand-file-name gnus-home-directory) ".local/share/mise/shims"))
(setq exec-path (append exec-path '(concat (expand-file-name gnus-home-directory) ".local/share/mise/shims")))mise project awareness:
(use-package mise
:ensure t
:hook (
(after-init . global-mise-mode)
)
)pcap:
pcap (wireshark) file support.
(use-package pcap-mode
:ensure t
:defer t)Need to run the php-language-server for eglot to connect to:
docker kill php-language-server
docker rm php-language-server
docker pull felixfbecker/php-language-server
docker run --detach -p2088:2088 --restart=always --name php-language-server felixfbecker/php-language-serverWhat’s Next?
- Sign in to your Docker account → docker login
- View a summary of image vulnerabilities and recommendations → docker scout quickview felixfbecker/php-language-server
WARNING: The requested image’s platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested b9a761ffbf9a77c0fa4fbdbc390e7f43977f75338963d7285232766297d903c2
NOTE: On Mac’s; eglot will not connect if it is set to localhost!
(use-package php-mode
:ensure t
:defer t
:mode ("\\.php\\'" . php-mode)
:hook (
(php-mode-hook . my-programming-defaults-config)
(php-mode . eglot-ensure)
)
;; :custom
;; ;; See: https://2metz.fr/blog/configuring-emacs-eglot-lsp-with-docker-containers/
;; ;; for an example of eglot starting docker containers.
;; (eglot-withhold-process-id "1")
:config
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'(php-mode . ("127.0.0.1" 2088))))
)
;; '(php-mode . ("docker" "run" "--rm" "--detach" "--name=php-language-server" "felixfbecker/php-language-server"))))(use-package powershell
:ensure t
:defer t
:hook (
(powershell-mode . my-programming-defaults-config)
; (powershell-mode . lsp) ;; No `Expand-Archive` on Arch pwsh, so cannot install `pwsh-ls` automatically.
)
)Historical Links:
- http://www.emacswiki.org/emacs/ProgrammingWithPythonDotEl.
- https://github.com/fgallina/python.el.
- http://www.saltycrane.com/blog/2010/05/my-emacs-python-environment/.
NOTE: This still requires running: M-x eglot and then picking the python LSP
server (suggest: pyright-langserver).
(use-package python
:ensure-system-package ((python3 . python) (pyright))
:after eglot
:ensure t
:functions flycheck-mode
:preface
(defun cas/python-config ()
"Python additional config."
(if (not (string-match "python" compile-command))
(set (make-local-variable 'compile-command)
"pytest"))
)
:hook (
(python-ts-mode . cas/python-config)
((python-mode python-ts-mode) . eglot-ensure)
)
:config
(setq
;; See: https://github.com/renzmann/treesit-auto#keep-track-of-your-hooks
python-ts-mode-hook python-mode-hook
)
)Uses Github: psf/black to reformat python buffer on save.
(use-package blacken
:ensure t
:hook (python-mode . blacken-mode)
;; :init
;; NOTE: Commented out below line due to currently working on projects that
;; require `black` but have no: `[tool.black]` in the `pyproject.toml` file.
;; (setq blacken-only-if-project-is-blackened t)
)Calls isort to sort imports.
TODO: figure out why this is cause code to be eaten from the top of the file on save.
;; (use-package isortify
;; :ensure t
;; :defer t
;; :after (python-mode)
;; :hook (python-mode . isortify-mode)
;; )Mentioned as the Emacs Ruff integration.
FIXME: bound to only python buffers (with ruff installed??).
(use-package flymake-ruff
:ensure-system-package ((ruff))
:ensure t
:hook (eglot-managed-mode . flymake-ruff-load)
:custom
;; https://github.com/renzmann/.emacs.d/blob/emacs-29/README.org#python
(python-check-command "ruff")
)(with-eval-after-load 'compile
(add-to-list 'compilation-error-regexp-alist-alist
'(pyright "^[[:blank:]]+\\(.+\\):\\([0-9]+\\):\\([0-9]+\\).*$" 1 2 3))
(add-to-list 'compilation-error-regexp-alist 'pyright));; FIXME: auto activation blows up when a file has no conda env associated to it.
;;
(when (eq system-type 'darwin)
;; FIXME: Bound this to my Work laptop only and not break my personal linux
;; laptop when I don't touch conda.
(use-package conda
:after (python-mode)
:ensure t
:defer t
:config
;; https://github.com/necaris/conda.el/issues/107 - stopped working with
;;conda 4.13.0
;;
;; Brew location for `miniforge`.
;; TODO: bound to `darwin`.
;; TODO: check all available paths to see which exists or look into ENV variables ??
(setq conda-anaconda-home (expand-file-name "/opt/homebrew/Caskroom/miniforge/base/"))
(setq conda-env-home-directory (expand-file-name "/opt/homebrew/Caskroom/miniforge/base/"))
;; ;; Web install location for `miniconda`.
;; (setq conda-anaconda-home (expand-file-name "~/opt/miniconda3/"))
;; (setq conda-env-home-directory (expand-file-name "~/opt/miniconda3/"))
;; if you want interactive shell support, include:
(conda-env-initialize-interactive-shells)
;; if you want eshell support, include:
;; (conda-env-initialize-eshell)
;; (defun conda-autoload ()
;; (interactive)
;; "auto activate conda if environment.yml exists."
;; (f-traverse-upwards (lambda (path)
;; (let ((venv-path (f-expand "environment.yml" path)))
;; (when (f-exists? venv-path)
;; (conda-env-activate-for-buffer)
;; )))))
;; NOTE: Using above function to load env for each buffer, instead of the
;; global mode, since the global setting below doesn't gracefully handle
;; buffers that don't have a conda env.
;;
;; ;; if you want auto-activation (see below for details), include:
;; (conda-env-autoactivate-mode t)
;; ;; if you want to automatically activate a conda environment on the opening of a file:
;; (add-to-hook 'find-file-hook (lambda () (when (bound-and-true-p conda-project-env-path)
;; (conda-env-activate-for-buffer))))
;; modeline
;; (setq-default mode-line-format (cons '(:exec conda-env-current-name) mode-line-format))
;; :hook (
;; (python-mode . conda-autoload)
;; )
)
)
FIXME: removing since current work is poetry in a conda env. Advice is to just use conda to manage the venv loading, since poetry is looking in the wrong location.
(use-package poetry
:ensure t
:defer t
:after (python-mode)
;; :config
;; (poetry-tracking-mode) ;; activate poetry virtualenv's on buffer change.
)Configure global pyright to pick up project local venv. Starting
eglot, will then call the correctly configured pyright (Still need to
pyvenv-activate then restart eglot, for the rest of emacs to be
happy).
- See:
M-x pyrightconfig-write </path/to/venv/>.M-x eglot.
(defun pyrightconfig-write (virtualenv)
"Write a `pyrightconfig.json' file at the Git root of a project
with `venvPath' and `venv' set to the absolute path of
`virtualenv'. When run interactively, prompts for a directory to
select."
(interactive "DEnv: ")
;; Naming convention for venvPath matches the field for pyrightconfig.json
(let* ((venv-dir (tramp-file-local-name (file-truename virtualenv)))
(venv-file-name (directory-file-name venv-dir))
(venvPath (file-name-directory venv-file-name))
(venv (file-name-base venv-file-name))
(base-dir (vc-git-root default-directory))
(out-file (expand-file-name "pyrightconfig.json" base-dir))
(out-contents (json-encode (list :venvPath venvPath :venv venv))))
(with-temp-file out-file (insert out-contents))
(message (concat "Configured `" out-file "` to use environment `" venv-dir))))The replacement to virtualenv. Do C-cC-pa or M-x pipenv-activate to start
a projects pipenv.
;; (use-package pipenv
;; :ensure t
;; :defer t
;; :after (python-mode)
;; :hook (python-mode . pipenv-mode)
;; :init
;; (setq
;; pipenv-projectile-after-switch-function
;; #'pipenv-projectile-after-switch-default))(use-package pyvenv
:ensure t
:defer t
:after (python-mode)
:functions pyvenv-autoload
:config
(defun pyvenv-autoload ()
"auto activate venv directory if exists. See: https://github.com/jorgenschaefer/pyvenv/issues/51"
(interactive)
(f-traverse-upwards (lambda (path)
(let ((venv-path (f-expand ".venv" path)))
(when (f-exists? venv-path)
(pyvenv-activate venv-path)
)))))
:hook (
(python-mode . pyvenv-autoload)
;; Modified from: https://github.com/jorgenschaefer/pyvenv/issues/95
;; FIXME: correct this so it runs LSP after above call, so I don't
;; need to do: C-xC-v.
;; (pyvenv-post-activate-hooks . lsp)
)
)rust:
(use-package rust-mode
:ensure t
:defer t
:hook (rust-mode . eglot-ensure)
)(use-package sh-script
:ensure-system-package ((shellcheck) (bash-language-server))
:ensure t
:defer t
:hook (((shell-script-mode sh-mode bash-ts-mode) . eglot-ensure))
)- Linter: Github: sqlfluff/sqlfluff
(use-package sql
:ensure-system-package (sqlfluff)
:ensure t
:config
(setq
sql-dialect 'postgres
sql-linter-program 'sqlfluff
indent-tabs-mode nil ;; spaces instead of tabs
)
)Testing out SQLFluff for linting.
(use-package flymake-sqlfluff
:ensure-system-package (sqlfluff)
:ensure t)(use-package sql-indent
:ensure t)Terraform is infrastructure as code to abstract across the big Cloud providers.
(use-package terraform-mode
:ensure-system-package
(
(terraform)
(terraform-ls)
)
:ensure t
:hook (((terraform-mode terraform-ts-mode) . eglot-ensure))
:config (setq terraform-format-on-save t)
;; https://github.com/hashicorp/terraform-ls/blob/main/docs/USAGE.md
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
`(terraform-mode . ,(eglot-alternatives
'(("terraform-ls" "serve")
("terraform-lsp" "serve"))))))
)(use-package typescript-mode
:ensure t
:ensure-system-package (typescript-language-server)
)(use-package nxml-mode
:mode (
("web.config$" . xml-mode)
("\\.nfo\\'" . nxml-mode)
)
:init
(progn
(add-hook 'nxml-mode-hook 'my-programming-defaults-config)
(add-hook 'nxml-mode-hook (lambda () (auto-fill-mode -1))) ;; disables auto fill at column.
;; http://www.nuxeo.com/blog/nxml-mode-tabs/
(add-hook 'nxml-mode-hook (lambda () (setq indent-tabs-mode nil)))
(setq
nxml-child-indent 2
)
)
)- SO: Pretty Printing XML files on Emacs. Picked the solution below so that I did not have to pull in an OS package.
(defun bf-pretty-print-xml-region (begin end)
"Pretty format XML markup in region. You need to have nxml-mode
http://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do
this. The function inserts linebreaks to separate tags that have
nothing but whitespace between them. It then indents the markup
by using nxml's indentation rules."
(interactive "r")
(save-excursion
(nxml-mode)
(goto-char begin)
(while (search-forward-regexp "\>[ \\t]*\<" nil t)
(backward-char) (insert "\n") (setq end (1+ end)))
(indent-region begin end))
(message "Ah, much better!"))Usage:
- Past XML into an
nxml-modebuffer. - To expand single-line XML: Select region or jump to start and call:
bf-pretty-print-xml-region. - To indent multi-line XML: Select region and call:
indent-region.
Use :ensure-system-package to install the: Github:
redhat-developer/yaml-language-server for eglot to use. NOTE: Look at the
github page to configure schemas for the YAML file (eg. Kubernetes schema) to
do completions!
(use-package yaml-mode
:ensure-system-package (yaml-language-server)
:ensure t
:hook (((yaml-mode yaml-ts-mode) . eglot-ensure))
)RedHat maintains a whole library of JSON schemas for it’s Github: redhat-developer/yaml-language-server to use. These need to be pulled in dynamically, so that emacs can appropriately warn/highlight/complete/document the YAML in the current buffer.
Links:
- https://developers.redhat.com/blog/2020/11/25/how-to-configure-yaml-schema-to-make-editing-files-easier#yaml_schema.
- https://emacs-lsp.github.io/lsp-mode/page/lsp-yaml/.
- https://www.schemastore.org/json/.
- https://github.com/SchemaStore/schemastore/commit/12841f7f81401f2c48c3c1c647c9e0739a34a89b for DBT project files.
- Github: joaotavora/eglot/discussions/918 - Eglot + yaml-language-server #918.
Hopefully, Github: yveszoundi/eglot-yaml solves this problem for eglot.
M-x eglot-yaml-schema-for-buffer to select a JSON schema for the current YAML
buffer.
NOTE: Not in emacs package managers! Commented out for now.
;; (use-package eglot-yaml
;; :ensure t
;; :after (eglot)
;; :hook ((yaml-ts-mode . eglot-yaml-init))
;; )RSS feeds in emacs.
An Emacs web feeds client.
(use-package elfeed
:ensure t
:defer t
:bind
(:map elfeed-search-mode-map
("l" . elfeed-search-tag--star))
(:map elfeed-show-mode-map
("l" . elfeed-show-tag--star))
:hook (
(elfeed-show-mode . (lambda () (setq-local shr-width 80)))
)
:custom
(elfeed-use-curl t)
(elfeed-log-level 'debug)
:config (setq-default word-wrap t)
;; (setq elfeed-log-level 'debug)
(defun elfeed-show-tag--star ()
(interactive)
(elfeed-show-tag 'star))
(defun elfeed-search-tag--star ()
(interactive)
(elfeed-search-toggle-all 'star))
)Configure the Elfeed RSS reader with an Orgmode file.
(use-package elfeed-org
:ensure t
:defer t
:config
(setq
rmh-elfeed-org-files (list "~/org/personal/elfeed.org")
)
:init (elfeed-org)
)(use-package elfeed-protocol
:after (elfeed elfeed-org)
:init
(setq
;; curl recommend
elfeed-use-curl t
elfeed-set-timeout 36000
elfeed-curl-extra-arguments '("--insecure") ;necessary for https without a trust certificate
;; Setup Fever
elfeed-protocol-update-unread-only t
elfeed-protocol-fever-fetch-category-as-tag t
;; ~.authinfo.gpg~ contents: ~machine <ip/hostname> port <port> login <user> password <password>~.
elfeed-protocol-feeds '(("fever+http://craig@192.168.0.98:8095"
:api-url "http://craig@192.168.0.98:8095/api/fever.php"
:use-authinfo t))
)
;; enable elfeed-protocol
(elfeed-protocol-enable)
:ensure t
:defer t
:custom
(
(elfeed-protocol-log-trace t)
(elfeed-protocol-fever-maxsize 10)
)
) (setq my-elfeed-update-timer
(run-at-time 15 15
(lambda () (when (= elfeed-curl-queue-active 0)
(elfeed-protocol-fever-update-older "fever+http://craig@192.168.0.98:8095")))))
(cancel-timer my-elfeed-update-timer)(defun elfeed-nuclear-update ()
(interactive)
(cl-loop for entry in (elfeed-search-selected)
do (elfeed-untag-1 entry 'unread))
(elfeed-protocol-fever-reinit "http://craig@192.168.0.98:8095")
)(defun elfeed-protocol-advice-rmh-elfeed-org-export-feed (headline)
"Advice for `rmh-elfeed-org-export-feed', add elfeed-protocol ID as suffix for each feed."
(let* ((url (car headline))
(proto-id (car (elfeed-protocol-feed-list))))
(when proto-id
(setcar headline (elfeed-protocol-format-subfeed-id proto-id url)))))
(advice-add 'rmh-elfeed-org-export-feed :before #'elfeed-protocol-advice-rmh-elfeed-org-export-feed)Update old tags on config change with: M-x elfeed-apply-hooks-now.
(use-package elfeed-autotag
:after (elfeed elfeed-org elfeed-protocol)
:init
(setq elfeed-autotag-files '("~/org/personal/elfeed.org"))
(elfeed-autotag)
:ensure t
:defer t
)Youtube integration for Elfeed, the feed reader for Emacs.
(use-package elfeed-tube
:ensure-system-package ((mpv) (yt-dlp))
:ensure t
:defer t
:after (elfeed)
:demand t
:config
;; (setq elfeed-tube-auto-save-p nil) ; default value
;; (setq elfeed-tube-auto-fetch-p t) ; default value
(elfeed-tube-setup)
:bind (:map elfeed-show-mode-map
("F" . elfeed-tube-fetch)
([remap save-buffer] . elfeed-tube-save)))If you want “live” captions and better MPV support:
(use-package elfeed-tube-mpv
:ensure-system-package (mpv)
:ensure t
:bind (
(:map elfeed-show-mode-map
("C-c C-f" . elfeed-tube-mpv-follow-mode)
("C-c C-w" . elfeed-tube-mpv-where)
("v" . elfeed-tube-mpv)
)
(:map elfeed-search-mode-map
("v" . elfeed-tube-mpv)
)
)
)A frontend for elfeed (like Mu4e Dashboard).
(use-package elfeed-dashboard
:ensure t
:defer t
:config
(setq elfeed-dashboard-file "~/org/personal/elfeed-dashboard.org")
;; update feed counts on elfeed-quit
(advice-add 'elfeed-search-quit-window :after #'elfeed-dashboard-update-links))Alternative to [[*\[\[https://github.com/manojm321/elfeed-dashboard\]\[elfeed-dashboard\]\]:][elfeed-dashboard]].
(use-package elfeed-summary
:ensure t
:defer t
:custom
(
(elfeed-summary-default-filter "")
(elfeed-summary-settings
'(
;; (group (:title . "All feeds") (:elements (query . :all)))
(group (:title . "Searches")
(:elements
(search (:filter . "+in-progress")
(:title . "InProgress videos"))
(search (:filter . "+star")
(:title . "Starred"))
(search (:filter . "+favourite")
(:title . "Favourites"))
(search (:filter . "@1-days-ago +unread")
(:title . "Unread today"))
(search (:filter . "@7-days-ago +unread")
(:title . "Unread entries this week"))
(search (:filter . "@6-months-ago emacs")
(:title . "Something about Emacs"))))
(group (:title . "Videos")
(:elements
(group
(:title . "RPGs")
(:elements
(query . (and youtube solorpg))))
(group
(:title . "Coffee")
(:elements
(query . (and youtube coffee))))
(group
(:title . "Documentaries")
(:elements
(query . (and youtube documentary))))
(group
(:title . "Development")
(:elements
(query . (and youtube (design dev programming work)))))
))
(group (:title . "Blogs")
(:elements
(group
(:title . "RPGs")
(:elements
(query . (and solorpg (not youtube)))))
(group
(:title . "Documentaries")
(:elements
(query . (and documentary (not youtube)))))
(group
(:title . "Development")
(:elements
(query . (and (design dev programming work ci tech security) (not youtube)))))
))
(group (:title . "All other feeds") (:elements :misc))
;; (group (:title . "Tags Tree")
;; (:elements
;; (auto-tags (:source . (query . :all)))))
)
)
)
)FIXME: Raise bug around missing Powerline version in melpa.
- https://sr.ht/~johnhamelink/elfeed-paywall/, https://www.reddit.com/r/emacs/comments/6r07ea/is_elfeed_able_to_extract_full_text_from_articles/ - Avoid paywalls and retrieve content from a feed entry’s link.
- https://github.com/zabe40/elfeed-time - elfeed-time displays the approximate time it will take to read, watch, or listen to an elfeed entry. It can display this information in both elfeed-search-mode, and elfeed-show-mode.
- https://github.com/yt-dlp/yt-dlp,
cvzi/mpv-youtube-upnext#8 - log into YouTube via
either:
.netrc, or:--cookiespulled from the browser and stored in a file set in theyt-dlpconfig file. - https://cundy.me/post/elfeed/ - Customized
elfeed-search-print-entry-functionto put more useful information on theelfeed-searchbuffer. eg. likeelfeed-time(youtube duration, date). - Fix
elfeed-orgtags on FreshRSS sourced feeds. - https://gist.github.com/alphapapa/80d2dba33fafcb50f558464a3a73af9a - anything worth stealing from Alphapapa’s config?
- https://noonker.github.io/posts/2020-04-22-elfeed/ - any inspiration?
- https://punchagan.muse-amuse.in/blog/elfeed-hook-to-fetch-full-content/ - Fetch full content of a page.
- https://bitbucket.org/shackra/4hoa/src/master/ - A Go application that will burn your feeds and retrieve articles of the Internet for you to read in eww (or any other non-graphical web browser).
Mingus (MPD client)
MPD references:
- https://github.com/dakrone/eos/blob/master/eos-music.org
- https://wiki.archlinux.org/index.php/Music_Player_Daemon
- https://wiki.archlinux.org/index.php/Ncmpcpp
(use-package mingus
:ensure t
:defer t
:bind
(
("C-c m" . mingus)
("<f9>" . mingus-toggle)
("C-<f12>" . mingus-prev)
("<f12>" . mingus-next)
)
:custom
(
(mingus-mpd-host "raudio-office.local")
)
)Looking to see if there are any good alternative MPD clients to mingus for controlling my remote MPD servers.
C-x ZPrefixlPlaylist.NArtists.:Browser.CConnect to Profile. Profiles defined via: libmpdel.SPCPlay/Pause toggle.
(use-package libmpdel
:ensure t
)
(use-package mpdel
:ensure t
:after (libmpdel)
:custom
(
(libmpdel-hostname "raudio-office.local")
)
:config
(setq libmpdel-profiles
'(
("Local server" "localhost" 6600 ipv4)
("RAudio-Office server" "raudio-office.local" 6600 ipv4)
("RAudio-Office2 server" "raudio-office2.local" 6600 ipv4)
("Volumio-Office server" "volumio-office.local" 6600 ipv4)
("Volumio-Kitchen server" "volumio-kitchen.local" 6600 ipv4)
)
)
(mpdel-mode)
)Packages around reading (eg. novels/epubs, Speed Reading, etc).
Speed reading by line or word.
(use-package amread-mode
:ensure t
:commands (amread-mode)
:custom
(
(amread-scroll-style 'word)
(amread-voice-reader-language 'english)
(amread-word-speed 10.0) ;; WPS eg. 300WPM = 5WPS.
)
:custom-face
(amread-highlight-face ((t (:background "red4" :foreground "white"))))
)(use-package devdocs
:ensure t
:defer t
:hook (
(c-mode . (lambda () (setq-local devdocs-current-docs '("c"))))
(c++-mode . (lambda () (setq-local devdocs-current-docs '("cpp" "cmake~3.20"))))
(python-mode . (lambda () (setq-local devdocs-current-docs '("python~3.9" "django~3.2" "django_rest_framework"))))
)
)Emacs-based screen reader to read words when passing over them, or the whole
buffer with M-< (beginning-of-buffer). Toggle with: M-x eloud-mode.
NOTE:
- This slows down buffer movement greatly.
- Throws traceback when trying to close with a FIDO fuzzy completion. Have to
type out:
eloud-mode<return>, in:M-x, to disable. - Espeak Docs: Commnands.
(use-package eloud
:ensure t
:ensure-system-package (espeak)
:config
(if (eq system-type 'darwin)
(setq eloud-espeak-path "/usr/local/bin/espeak"))
(setq eloud-speech-rate 350)
)iRFC (Download & View RFC’s). FIXME: appears to not exist anymore.
;; (use-package irfc
;; :ensure t
;; :defer t
;; :config
;; (progn
;; (setq
;; irfc-directory "~/Downloads/rfcs/"
;; irfc-assoc-mode t)
;; )
;; )Reddit client. Guessing this is dead after the public API shutdown, but here is
my original note: FIXME: uncomment once Debugger entered--Lisp error:
(void-variable hierarchy--make) is fixed.
;; (use-package md4rd
;; :ensure t
;; :defer t
;; )nov (ereader mode - epub):
Open .epub archive and then M-x nov-mode.
(use-package nov
:ensure t
:mode ("\\.epub\\'" . nov-mode)
:custom
(nov-save-place-file "~/org/personal/nov_history")
)Replacement for built-in doc-view + ghostscript dependency to view
PDF’s. Renders in memory, instead of storing images in an on-disk
cache.
(use-package pdf-tools
:ensure t
:config
(pdf-tools-install)
)Speed reading in a buffer by flashing each word in turn. Spritz clone for speed reading.
(use-package spray
:ensure t
:defer t)In spray-mode buffers, following commands are available:
spray-start/stop(SPC) pause or resume spraying.spray-backward-word(h, <left>) pause and back to the last word.spray-forward-word(l, <right>) inverse of spray-backward-word.spray-faster(f) increases speed.spray-slower(s) decreases speed.spray-quit(q, <return>) quitspray-mode.
Stackoverflow search. FIXME: package doesn’t exist any more?
;; (use-package sos
;; :ensure t
;; :defer t
;; :bind (("<f5>" . sos))
;; )Highlight word stems in text buffers, thereby providing artificial fixation points to improve speed reading.
(use-package stem-reading-mode
:ensure t
:defer t)See: Howard Abrams: RPG DM config.
This project supplies a collection of functions in Emacs Lisp to allow developers to craft RPG-inspired programs, with a focus on Solo RPGs played in Org-formatted files.
(use-package rpgtk
:vc (:url "https://codeberg.org/howardabrams/emacs-rpgtk"
:rev :newest)
:ensure t
)Dungeon Master Support in Emacs
TODO: Set tables location!!
(use-package rpgdm
:vc (:url "https://gitlab.com/howardabrams/emacs-rpgdm"
:rev :newest)
:ensure t
)FIXME: Actually load when I have tables for it to pull in.
;; (use-package rpgdm-ironsworn
;; :vc (:url "https://gitlab.com/howardabrams/emacs-ironsworn"
;; :rev :newest)
;; ;:ensure t
;; )ansi-term is terminal emulator. I originally preferred it to
multi-term/eshell/shell, but find shell works better with paths and running
of applications (eg. `aws` CLI client correctly logging in).
Code from: https://github.com/jwalgran/dotfiles/blob/master/.emacs.d/config.el
(use-package term
:demand t
:bind (("<f2>" . visit-ansi-term)
;; Note: gdb keybinding is: C-x C-a C-l, which I did have my rename term windows as.
;; ("C-x C-a" . open-term)
)
:init
(progn
;; https://github.com/ahinz/emacs-config/blob/7e025076097f045aea2a0aedd0523ee996753346/.emacs.d/ah-modes.el#L268
(defun open-named-term (new-buffer-name cmd &rest switches)
(setq term-ansi-buffer-name (generate-new-buffer-name new-buffer-name))
(setq term-ansi-buffer-name (apply 'make-term term-ansi-buffer-name cmd nil switches))
(set-buffer term-ansi-buffer-name)
(term-mode)
(term-char-mode)
(term-set-escape-char ?\C-x)
(switch-to-buffer term-ansi-buffer-name))
;; https://github.com/ahinz/emacs-config/blob/7e025076097f045aea2a0aedd0523ee996753346/.emacs.d/ah-modes.el#L268
(defun open-term (name)
(interactive "sName: ")
(open-named-term name "/bin/bash"))
(defun visit-ansi-term ()
"If the current buffer is:
1) a running ansi-term named *ansi-term*, rename it.
2) a stopped ansi-term, kill it and create a new one.
3) a non ansi-term, go to an already running ansi-term
or start a new one while killing a defunt one"
(interactive)
(let ((is-term (string= "term-mode" major-mode))
(is-running (term-check-proc (buffer-name)))
(term-cmd "/bin/bash")
(anon-term (get-buffer "*ansi-term*")))
(if is-term
(if is-running
(if (string= "*ansi-term*" (buffer-name))
(call-interactively 'rename-buffer)
(if anon-term
(switch-to-buffer "*ansi-term*")
(ansi-term term-cmd)))
(kill-buffer (buffer-name))
(ansi-term term-cmd))
(if anon-term
(if (term-check-proc "*ansi-term*")
(switch-to-buffer "*ansi-term*")
(kill-buffer "*ansi-term*")
(ansi-term term-cmd))
(ansi-term term-cmd)))))
;; Make ansi-term buffers close when you kill the shell process
(defun term-sentinel--my-advice-term-sentinel (proc msg)
(if (memq (process-status proc) '(signal exit))
(let ((buffer (process-buffer proc)))
ad-do-it
(kill-buffer buffer))
ad-do-it))
(advice-add 'term-sentinel :around #'my-advice-term-sentinel)
)
(add-hook 'ansi-term-hook (lambda () (global-hl-line-mode 0))) ; http://stackoverflow.com/questions/9990370/how-to-disable-hl-line-feature-in-specified-mode
)eat:
To setup shell integration for GNU Bash, put the following at the end of your `.bashrc’:
For Zsh, put the following in your `.zshrc’:
(use-package eat
:ensure t
:hook
(
;; Run eat in eshell
(eat-eshell-mode . eshell-load-hook)
(eat-eshell-visual-command-mode . eshell-load-hook)
)
)Add the following programs to the list of programs that eshell won’t complain
about not being a proper terminal. This will move out of line-mode and into
paging mode (eg. like scrolling through a man page on a real terminal). See:
- Emacs StackExchange: fix or workaround: “Terminal is not fully functional”.
- Emacs Wiki: Eshell Visual Commands.
NOTE: This will use ansi-term for those command calls, so can use:
C-xC-j, and: C-cC-k, to jump in and out of editing mode.
Bindings:
C-p/C-nto move up/down by line.C-cC-p/C-cC-nto move up/down to each input/prompt.
(use-package eshell
:ensure t
:config
(setq eshell-history-size 1000000)
(with-eval-after-load 'em-term
(add-to-list 'eshell-visual-commands "aws"))
)Vterm is a terminal with pretty good ncurses support and compliance.
NOTES: Requires cmake installed on the system to compile!!
C-cC-tto enter/exit copy-mode.
(use-package vterm
:if (not (eq system-type 'windows-nt)) ;; FIXME: compiling on Windows.
:ensure-system-package (cmake)
:ensure t
:after (cmake-mode)
:init (setq vterm-always-compile-module t)
:custom
(vterm-max-scrollback 100000)
:hook (vterm-mode . compilation-shell-minor-mode)
)Touch typing practice. Call: M-x speed-type-text.
(use-package speed-type
:ensure t
:defer t)Emacs Monkeytype is a typing game/tutor inspired by monkeytype.com but for Emacs.
M-x monkeytype-<buffer|region>.M-x monkeytype-stoporC-cC-cs.
(use-package monkeytype
:ensure t
:defer t
:config
(setq
;; How often to update mode-line
monkeytype-mode-line-interval-update 10
;; Use space instead or newline
monkeytype-treat-newline-as-space t
;; Minimum amount of transitions for test
;; If not enough repeat them
monkeytype-minimum-transitions 50
;; Inserts debugging log, this can take a while
;; if typing text is too long.
monkeytype-insert-log nil
;; Default directory for saving Monkeytype data
monkeytype-directory "~/.monkeytype"
;; Format for time-stamped files for saving.
monkeytype-file-name "%a-%d-%b-%Y-%H-%M-%S"
;; Toggle randomise text
monkeytype-randomize t
;; Toggle downcase text
monkeytype-dowcase t
;; Amount of words for most mistyped words test
monkeytype-most-mistyped-amount 100
;; Toggle auto-fill on typing text
monkeytype-auto-fill nil
;; Toggle auto-fill on words related typing text
monkeytype-words-auto-fill t
;; Toggle auto deletion of trailing white space
monkeytype-delete-trailing-whitespace t
;; Regexp used to divide and extracts words
monkeytype-excluded-chars-regexp "[^[:alnum:]']"
;; Toggle converting downloaded text to ASCII
monkeytype-asciify t
)
)Create visual menu’s like what `magit` provides, but easily customised.
(use-package hydra :ensure t)Search YouTube from emacs, play via mpv, download via yt-dlp.
(use-package yeetube
:ensure
:ensure-system-package ((wget))
:custom
(yeetube-display-thumbnails nil)
(yeetube-results-limit 50)
)Switched over to: Github: emacsorphanage/restclient, since: Github: pashky/restclient has been abandoned but not handed over. See: Github: emacsorphanage/restclient issue #1.
Run up a rest client in emacs to quickly test APIs. See:
- http://emacsrocks.com/e15.html
- EmacsConf 2021: Creating technical API documentation and presentations using org-babel, restclient, and org-treeslide.
- Github: jypma/emacsconf2021/blob/master/presentation.org.
Eg. Run (C-cC-c) the following in an empty buffer with restclient-mode on:
GET https://api.github.com User-Agent: Emacs Restclient
(use-package restclient
:ensure t
:vc (:url "https://github.com/emacsorphanage/restclient" :rev :newest)
:defer t
:mode ("\\.restclient\\'" . restclient-mode)
:config
(setq restclient-enable-eval t)
)Add restclient support to org-babel code blocks.
Eg. Run (C-cC-c) the following code block.
GET https://api.github.com
User-Agent: Emacs Restclient
(use-package ob-restclient
:ensure t
:after (restclient)
:config
(add-to-list 'org-babel-load-languages '(restclient . t))
(org-babel-do-load-languages 'org-babel-load-languages org-babel-load-languages)
)elpher (Gopher client):
(use-package elpher
:ensure t
)Configs that look good enough to go back and maybe learn/steal from: