This configuration file serves as the single source of truth for all Emacs customizations. It includes rough notes on setup and usage. It is continuously updated to reflect my current usage patterns.
- emacs.d/malb.org at master · malb/emacs.d · GitHub
- Former Emacs maintainer John Wiegley's config
- GitHub - munen/emacs.d: My emacs configuration documented in literate program…
- Literate Emacs Configuration - Look here for org-export customizations
- GitHub - joseph8th/literatemacs: My literate Emacs config
- Robert Zaremba "Scale it", Emacs cheatsheet
- " - str '(kf-htmlegalize-region skeleton-point (point)) "
- Quick Help: Emacs as a Text Productivity Platform : emacs
- My Emacs Configuration
- GitHub - karthink/.emacs.d: My personal emacs settings
- From Doom to Vanilla Emacs - blog.dornea.nu
- GitHub - dorneanu/dotemacs: Collection of Emacs configurations
Greetings! I currently use Spacemacs on Windows Subsystem for Linux (WSL).
Instructions for installing Emacs on WSL2. Beginners Emacs users may be
interested in the "Spacemacs Reference Manual" heading. Experienced Emacs users
will want to Ctrl-F
to find a particular package or layer. Contact me if
something is unclear or should you have any questions. Run the following on a
new computer to clone my configuration,
# Runtime dependencies of my Emacs config. sudo apt install git mu4e ispell # On Android termux, # pkg install git mu aspell aspell-en # See heading "Github Tutorial" if you are unfamiliar with git. git clone https://github.com/benedicthw/spacemacs.git -b with-elisp-packages ~/.emacs.d git clone https://github.com/benedicthw/common-lisp-sly ~/.emacs.d/private/common-lisp-sly cp ~/.emacs.d/.spacemacs ~/.spacemacs
;; -*- mode: emacs-lisp; lexical-binding: t -*- ;; This file is loaded by Spacemacs at startup. ;; It must be stored in your home directory. (defconst +project-maria-dir+ "/home/ben/project-maria/" "On UNIX likes, expands to /home/ben/project-maria/") (defconst +project-jerome-dir+ "/home/ben/project-jerome/" "On UNIX likes, expands to /home/ben/project-jerome/") (defun dotspacemacs/layers () "Layer configuration: This function should only modify configuration layer settings." (setq-default ;; Base distribution to use. This is a layer contained in the directory ;; `+distribution'. For now available distributions are `spacemacs-base' ;; or `spacemacs'. (default 'spacemacs) dotspacemacs-distribution 'spacemacs ;; Lazy installation of layers (i.e. layers are installed only when a file ;; with a supported type is opened). Possible values are `all', `unused' ;; and `nil'. `unused' will lazy install only unused layers (i.e. layers ;; not listed in variable `dotspacemacs-configuration-layers'), `all' will ;; lazy install any layer that support lazy installation even the layers ;; listed in `dotspacemacs-configuration-layers'. `nil' disable the lazy ;; installation feature and you have to explicitly list a layer in the ;; variable `dotspacemacs-configuration-layers' to install it. ;; (default 'unused) dotspacemacs-enable-lazy-installation 'nil ;; If non-nil then Spacemacs will ask for confirmation before installing ;; a layer lazily. (default t) dotspacemacs-ask-for-lazy-installation t ;; List of additional paths where to look for configuration layers. ;; Paths must have a trailing slash (i.e. `~/.mycontribs/') dotspacemacs-configuration-layer-path '() ;; List of configuration layers to load. dotspacemacs-configuration-layers '(;; ---------------------------------------------------------------- ;; Example of useful layers you may want to use right away. ;; Uncomment some layer names and press `SPC f e R' (Vim style) or ;; `M-m f e R' (Emacs style) to install them. ;; ---------------------------------------------------------------- (auto-completion :variables auto-completion-enable-help-tooltip t auto-completion-enable-snippets-in-popup t :packages (not helm-company yasnippet-snippets fuzzy ac-ispell auto-complete)) (better-defaults :packages (not mwim)) (bibtex :variables bibtex-enable-ebib-support t ebib-preload-bib-files (list (concat +project-maria-dir+ "project-jerome.bib")) ebib-file-search-dirs (list +project-jerome-dir+) ebib-import-directory (list +project-jerome-dir+)) ;; $ git clone git@github.com:BenedictHW/common-lisp-sly.git ~/.emacs.d/private/ common-lisp-sly (elfeed :variables elfeed-enable-goodies nil rmh-elfeed-org-files (list (concat +project-maria-dir+ "dotelfeed.org"))) (emacs-lisp :packages (not flycheck-package nameless emr overseer flycheck-elsa auto-compile inspector )) evil-better-jumper (evil-snipe :variables evil-snipe-enable-alternate-f-and-t-behaviors 't) finance (git :variables git-enable-magit-todos-plugin t :packages (not git-modes golden-ratio smeargle gitignore-templates git-messenger helm-git-grep git-timemachine )) (helm :packages (not helm-descbinds helm-swoop helm-themes helm-make helm-ls-git helm-mode-manager helm-flx)) helpful (llm-client :variables llm-client-enable-ellama nil llm-client-enable-gptel t) (mu4e :variables mu4e-installation-path "/usr/share/emacs/site-lisp/elpa/mu4e-1.10.8" :packages (not mu4e-alert)) (org :variables org-enable-modern-support nil org-want-todo-bindings t org-enable-org-brain-support t org-enable-reveal-js-support t org-enable-org-journal-support nil org-enable-org-contacts-support t org-enable-appear-support t org-enable-sticky-header nil :packages (not org-rich-yank)) ;; pandoc pdf plantuml (python :variables python-backend 'lsp python-lsp-server 'pylsp python-shell-interpreter "python3") (shell :variables shell-default-height 30 shell-default-position 'bottom shell-default-shell 'shell :packages (not esh-help eshell-prompt-extras eshell-z xterm-color vterm multi-vterm terminal-here multi-term )) (spell-checking :packages (not auto-dictionary )) (syntax-checking :packages (not flycheck-pos-tip)) (transmission :variables transmission-auto-refresh-all t) ;; Danger! Making edits to the default layers. ;; See Spacemacs Issue 13595. The spacemacs distribution layer lists ;; treemacs in configuration-layer/declare-layers. (treemacs :packages nil) (spacemacs-bootstrap :packages (not dash holy-mode hybrid-mode)) (spacemacs-defaults :packages (not quickrun)) (spacemacs-editing :variables vim-style-enable-undo-region t :packages (not eval-sexp-fu expand-region aggressive-indent editorconfig hungry-delete multi-line password-generator uuidgen string-edit lorem-ipsum drag-stuff evil-easymotion)) (spacemacs-editing-visual :packages (not term-cursor highlight-indentation writeroom-mode hide-comnt highlight-numbers indent-guide volatile-highlights )) (spacemacs-completion :packages (not flx-ido)) (spacemacs-language :packages (not define-word)) (spacemacs-layouts :packages (not counsel-projectile)) (spacemacs-misc :packages (not devdocs)) (spacemacs-purpose :packages (not helm-purpose)) (spacemacs-modeline :packages (not anzu fancy-battery font-lock+ neotree symon vim-powerline)) (spacemacs-navigation :packages (not restart-emacs ace-link ace-window golden-ratio centered-cursor-mode open-junk-file auto-highlight-symbol)) (spacemacs-org :packages (not toc-org)) (spacemacs-visual :packages (not all-the-icons)) (spacemacs-evil :packages (not evil-numbers evil-lisp-state evil-escape evil-anzu evil-exchange evil-goggles evil-iedit-state evil-tutor evil-unimpaired evil-visual-mark-mode evil-visualstar evil-args vi-tilde-fringe evil-indent-plus vim-empty-lines-mode )) ) ;; *** Additional Packages ;; List of additional packages that will be installed without being ;; wrapped in a layer. If you need some configuration for these ;; packages, then consider creating a layer. You can also put the ;; configuration in `dotspacemacs/user-config'. dotspacemacs-additional-packages '(;; Replaces `dotspacemacs/user-env'. exec-path-from-shell org-noter org-pdftools org-web-tools ;; Pulls entire douay rheims bible from sword project ;; (sword-to-org :location (recipe :fetcher github ;; :repo "alphapapa/sword-to-org")) cdlatex org-fragtog ;; keyfreq ;; For org-brain ascii-art-to-unicode ;; wolfram-mode ;; See emacs-jupyter in user config section ;; jupyter lexic ;; Since it is a pretty heavy package, only include it when doing heavy ;; analysis on my own time spent. ;; org-analyzer org-tanglesync poly-org ement ox-rss youtube-sub-extractor elfeed-tube elfeed-tube-mpv greader literate-calc-mode listen casual-calc biome ) ;; A list of packages that cannot be updated. dotspacemacs-frozen-packages '(;; Otherwise it will reinstall itself helm-swoop ) ;; A list of packages that will not be installed and loaded. dotspacemacs-excluded-packages '(hybrid-mode helm-org-rifle org-present org-pomodoro org-projectile dotenv-mode) ;; Defines the behaviour of Spacemacs when installing packages. ;; Possible values are `used-only', `used-but-keep-unused' and `all'. ;; `used-only' installs only explicitly used packages and deletes any unused ;; packages as well as their unused dependencies. `used-but-keep-unused' ;; installs only the used packages but won't delete unused ones. `all' ;; installs *all* packages supported by Spacemacs and never uninstalls them. ;; (default is `used-only') dotspacemacs-install-packages 'used-only)) (defun dotspacemacs/init () "Initialization: This function is called at the very beginning of Spacemacs startup, before layer configuration. It should only modify the values of Spacemacs settings." ;; This setq-default sexp is an exhaustive list of all the supported ;; spacemacs settings. (setq-default ;; If non-nil then enable support for the portable dumper. You'll need to ;; compile Emacs 27 from source following the instructions in file ;; EXPERIMENTAL.org at to root of the git repository. ;; ;; WARNING: pdumper does not work with Native Compilation, so it's disabled ;; regardless of the following setting when native compilation is in effect. ;; ;; (default nil) dotspacemacs-enable-emacs-pdumper nil ;; Name of executable file pointing to emacs 27+. This executable must be ;; in your PATH. ;; (default "emacs") dotspacemacs-emacs-pdumper-executable-file "emacs" ;; Name of the Spacemacs dump file. This is the file will be created by the ;; portable dumper in the cache directory under dumps sub-directory. ;; To load it when starting Emacs add the parameter `--dump-file' ;; when invoking Emacs 27.1 executable on the command line, for instance: ;; ./emacs --dump-file=$HOME/.emacs.d/.cache/dumps/spacemacs-27.1.pdmp ;; (default (format "spacemacs-%s.pdmp" emacs-version)) dotspacemacs-emacs-dumper-dump-file (format "spacemacs-%s.pdmp" emacs-version) ;; If non-nil ELPA repositories are contacted via HTTPS whenever it's ;; possible. Set it to nil if you have no way to use HTTPS in your ;; environment, otherwise it is strongly recommended to let it set to t. ;; This variable has no effect if Emacs is launched with the parameter ;; `--insecure' which forces the value of this variable to nil. ;; (default t) dotspacemacs-elpa-https t ;; Maximum allowed time in seconds to contact an ELPA repository. ;; (default 5) dotspacemacs-elpa-timeout 5 ;; Set `gc-cons-threshold' and `gc-cons-percentage' when startup finishes. ;; This is an advanced option and should not be changed unless you suspect ;; performance issues due to garbage collection operations. ;; (default '(100000000 0.1)) ;; Emacs maintainer Eli Zaretskii recommends not altering the value from ;; Emacs default. ;; https://old.reddit.com/r/emacs/comments/bg85qm/garbage_collector_magic_hack/ ;; https://old.reddit.com/r/emacs/comments/6uc7g5/just_figured_out_why_emacs_pauses_sometimes/ ;; Update: see `spacemacs-editing/init-undo-tree' undo limits. ;; If we lower the threshold there will be freezing ;; when we use the undo history. ;; Also see: https://github.com/lewang/flx#gc-optimization dotspacemacs-gc-cons '(100000000 0.1) ;; Set `read-process-output-max' when startup finishes. ;; This defines how much data is read from a foreign process. ;; Setting this >= 1 MB should increase performance for lsp servers ;; in emacs 27. ;; (default (* 1024 1024)) dotspacemacs-read-process-output-max (* 1024 1024) ;; If non-nil then Spacelpa repository is the primary source to install ;; a locked version of packages. If nil then Spacemacs will install the ;; latest version of packages from MELPA. Spacelpa is currently in ;; experimental state please use only for testing purposes. ;; (default nil) dotspacemacs-use-spacelpa nil ;; If non-nil then verify the signature for downloaded Spacelpa archives. ;; (default t) dotspacemacs-verify-spacelpa-archives t ;; If non-nil then spacemacs will check for updates at startup ;; when the current branch is not `develop'. Note that checking for ;; new versions works via git commands, thus it calls GitHub services ;; whenever you start Emacs. (default nil) dotspacemacs-check-for-update nil ;; If non-nil, a form that evaluates to a package directory. For example, to ;; use different package directories for different Emacs versions, set this ;; to `emacs-version'. (default 'emacs-version) dotspacemacs-elpa-subdirectory 'emacs-version ;; One of `vim', `emacs' or `hybrid'. ;; `hybrid' is like `vim' except that `insert state' is replaced by the ;; `hybrid state' with `emacs' key bindings. The value can also be a list ;; with `:variables' keyword (similar to layers). Check the editing styles ;; section of the documentation for details on available variables. ;; (default 'vim) dotspacemacs-editing-style 'vim ;; If non-nil show the version string in the Spacemacs buffer. It will ;; appear as (spacemacs version)@(emacs version) ;; (default t) dotspacemacs-startup-buffer-show-version t ;; Specify the startup banner. Default value is `official', it displays ;; the official spacemacs logo. An integer value is the index of text ;; banner, `random' chooses a random text banner in `core/banners' ;; directory. A string value must be a path to an image format supported ;; by your Emacs build. ;; If the value is nil then no banner is displayed. (default 'official) dotspacemacs-startup-banner nil ;; Scale factor controls the scaling (size) of the startup banner. Default ;; value is `auto' for scaling the logo automatically to fit all buffer ;; contents, to a maximum of the full image height and a minimum of 3 line ;; heights. If set to a number (int or float) it is used as a constant ;; scaling factor for the default logo size. dotspacemacs-startup-banner-scale 'nil ;; List of items to show in startup buffer or an association list of ;; the form `(list-type . list-size)`. If nil then it is disabled. ;; Possible values for list-type are: ;; `recents' `recents-by-project' `bookmarks' `projects' `agenda' `todos'. ;; List sizes may be nil, in which case ;; `spacemacs-buffer-startup-lists-length' takes effect. ;; The exceptional case is `recents-by-project', where list-type must be a ;; pair of numbers, e.g. `(recents-by-project . (7 . 5))', where the first ;; number is the project limit and the second the limit on the recent files ;; within a project. dotspacemacs-startup-lists '((agenda . 30)) ;; True if the home buffer should respond to resize events. (default t) dotspacemacs-startup-buffer-responsive t ;; Show numbers before the startup list lines. (default t) dotspacemacs-show-startup-list-numbers t ;; The minimum delay in seconds between number key presses. (default 0.4) dotspacemacs-startup-buffer-multi-digit-delay 0.4 ;; If non-nil, show file icons for entries and headings on Spacemacs home buffer. ;; This has no effect in terminal or if "all-the-icons" package or the font ;; is not installed. (default nil) dotspacemacs-startup-buffer-show-icons nil ;; Default major mode for a new empty buffer. Possible values are mode ;; names such as `text-mode'; and `nil' to use Fundamental mode. ;; (default `text-mode') dotspacemacs-new-empty-buffer-major-mode 'nil ;; Default major mode of the scratch buffer (default `text-mode') dotspacemacs-scratch-mode 'common-lisp-mode ;; If non-nil, *scratch* buffer will be persistent. Things you write down in ;; *scratch* buffer will be saved and restored automatically. dotspacemacs-scratch-buffer-persistent nil ;; If non-nil, `kill-buffer' on *scratch* buffer ;; will bury it instead of killing. dotspacemacs-scratch-buffer-unkillable nil ;; Initial message in the scratch buffer, such as "Welcome to Spacemacs!" ;; (default nil) dotspacemacs-initial-scratch-message nil ;; List of themes, the first of the list is loaded when spacemacs starts. ;; Press `SPC T n' to cycle to the next theme in the list (works great ;; with 2 themes variants, one dark and one light) dotspacemacs-themes '(spacemacs-light spacemacs-dark) ;; Set the theme for the Spaceline. Supported themes are `spacemacs', ;; `all-the-icons', `custom', `doom', `vim-powerline' and `vanilla'. The ;; first three are spaceline themes. `doom' is the doom-emacs mode-line. ;; `vanilla' is default Emacs mode-line. `custom' is a user defined themes, ;; refer to the DOCUMENTATION.org for more info on how to create your own ;; spaceline theme. Value can be a symbol or list with additional properties. ;; (default '(spacemacs :separator wave :separator-scale 1.5)) dotspacemacs-mode-line-theme '(spacemacs :separator nil :separator-scale 0.5) ;; If non-nil the cursor color matches the state color in GUI Emacs. ;; (default t) dotspacemacs-colorize-cursor-according-to-state t ;; Default font or prioritized list of fonts. The `:size' can be specified as ;; a non-negative integer (pixel size), or a floating-point (point size). ;; Point size is recommended, because it's device independent. (default 10.0) ;; Dell 32 4K USB-C Hub Monitor - P3222QE dotspacemacs-default-font '("Iosevka Term Slab" :size 18.0 :weight normal :width normal) ;; The leader key (default "SPC") dotspacemacs-leader-key "SPC" ;; The key used for Emacs commands `M-x' (after pressing on the leader key). ;; (default "SPC") dotspacemacs-emacs-command-key "" ;; The key used for Vim Ex commands (default ":") dotspacemacs-ex-command-key ":" ;; The leader key accessible in `emacs state' and `insert state' ;; (default "M-m") dotspacemacs-emacs-leader-key "M-m" ;; Major mode leader key is a shortcut key which is the equivalent of ;; pressing `<leader> m`. Set it to `nil` to disable it. (default ",") dotspacemacs-major-mode-leader-key "," ;; Major mode leader key accessible in `emacs state' and `insert state'. ;; (default "C-M-m" for terminal mode, "<M-return>" for GUI mode). ;; Thus M-RET should work as leader key in both GUI and terminal modes. ;; C-M-m also should work in terminal mode, but not in GUI mode. dotspacemacs-major-mode-emacs-leader-key (if window-system "<M-return>" "C-M-m") ;; These variables control whether separate commands are bound in the GUI to ;; the key pairs `C-i', `TAB' and `C-m', `RET'. ;; Setting it to a non-nil value, allows for separate commands under `C-i' ;; and TAB or `C-m' and `RET'. ;; In the terminal, these pairs are generally indistinguishable, so this only ;; works in the GUI. (default nil) dotspacemacs-distinguish-gui-tab t ;; Name of the default layout (default "Default") dotspacemacs-default-layout-name "Default" ;; If non-nil the default layout name is displayed in the mode-line. ;; (default nil) dotspacemacs-display-default-layout nil ;; If non-nil then the last auto saved layouts are resumed automatically upon ;; start. (default nil) dotspacemacs-auto-resume-layouts nil ;; If non-nil, auto-generate layout name when creating new layouts. Only has ;; effect when using the "jump to layout by number" commands. (default nil) dotspacemacs-auto-generate-layout-names nil ;; Size (in MB) above which spacemacs will prompt to open the large file ;; literally to avoid performance issues. Opening a file literally means that ;; no major mode or minor modes are active. (default is 1) dotspacemacs-large-file-size 50 ;; Also see large-file-warning-threshold, set in dotspacemacs user config ;; Location where to auto-save files. Possible values are `original' to ;; auto-save the file in-place, `cache' to auto-save the file to another ;; file stored in the cache directory and `nil' to disable auto-saving. ;; (default 'cache) dotspacemacs-auto-save-file-location 'cache ;; Maximum number of rollback slots to keep in the cache. (default 5) dotspacemacs-max-rollback-slots 5 ;; If non-nil, the paste transient-state is enabled. While enabled, after you ;; paste something, pressing `C-j' and `C-k' several times cycles through the ;; elements in the `kill-ring'. (default nil) dotspacemacs-enable-paste-transient-state t ;; Which-key delay in seconds. The which-key buffer is the popup listing the ;; commands bound to the current keystroke sequence. (default 0.4) HW annot: ;; the default sacrifices -quite a lot of!- performance for accessibility, ;; and after some experience a tradeoff in favour of the former is preferred. dotspacemacs-which-key-delay 2 ;; Which-key frame position. Possible values are `right', `bottom' and ;; `right-then-bottom'. right-then-bottom tries to display the frame to the ;; right; if there is insufficient space it displays it at the bottom. ;; (default 'bottom) dotspacemacs-which-key-position 'bottom ;; Control where `switch-to-buffer' displays the buffer. If nil, ;; `switch-to-buffer' displays the buffer in the current window even if ;; another same-purpose window is available. If non-nil, `switch-to-buffer' ;; displays the buffer in a same-purpose window even if the buffer can be ;; displayed in the current window. (default nil) dotspacemacs-switch-to-buffer-prefers-purpose nil ;; If non-nil a progress bar is displayed when spacemacs is loading. This ;; may increase the boot time on some systems and emacs builds, set it to ;; nil to boost the loading time. (default t) dotspacemacs-loading-progress-bar nil ;; If non-nil the frame is fullscreen when Emacs starts up. (default nil) ;; (Emacs 24.4+ only) dotspacemacs-fullscreen-at-startup nil ;; If non-nil `spacemacs/toggle-fullscreen' will not use native fullscreen. ;; Use to disable fullscreen animations in OSX. (default nil) dotspacemacs-fullscreen-use-non-native nil ;; If non-nil the frame is maximized when Emacs starts up. ;; Takes effect only if `dotspacemacs-fullscreen-at-startup' is nil. ;; (default nil) (Emacs 24.4+ only) dotspacemacs-maximized-at-startup t ;; If non-nil the frame is undecorated when Emacs starts up. Combine this ;; variable with `dotspacemacs-maximized-at-startup' in OSX to obtain ;; borderless fullscreen. (default nil) dotspacemacs-undecorated-at-startup nil ;; A value from the range (0..100), in increasing opacity, which describes ;; the transparency level of a frame when it's active or selected. ;; Transparency can be toggled through `toggle-transparency'. (default 90) dotspacemacs-active-transparency 100 ;; A value from the range (0..100), in increasing opacity, which describes ;; the transparency level of a frame when it's inactive or deselected. ;; Transparency can be toggled through `toggle-transparency'. (default 90) dotspacemacs-inactive-transparency 100 ;; If non-nil show the titles of transient states. (default t) dotspacemacs-show-transient-state-title t ;; If non-nil show the color guide hint for transient state keys. (default t) dotspacemacs-show-transient-state-color-guide t ;; If non-nil unicode symbols are displayed in the mode line. ;; If you use Emacs as a daemon and wants unicode characters only in GUI set ;; the value to quoted `display-graphic-p'. (default t) dotspacemacs-mode-line-unicode-symbols t ;; If non-nil smooth scrolling (native-scrolling) is enabled. Smooth ;; scrolling overrides the default behavior of Emacs which recenters point ;; when it reaches the top or bottom of the screen. (default t) dotspacemacs-smooth-scrolling t ;; Show the scroll bar while scrolling. The auto hide time can be configured ;; by setting this variable to a number. (default t) dotspacemacs-scroll-bar-while-scrolling nil ;; Control line numbers activation. ;; If set to `t', `relative' or `visual' then line numbers are enabled in all ;; `prog-mode' and `text-mode' derivatives. If set to `relative', line ;; numbers are relative. If set to `visual', line numbers are also relative, ;; but only visual lines are counted. For example, folded lines will not be ;; counted and wrapped lines are counted as multiple lines. ;; This variable can also be set to a property list for finer control: ;; '(:relative nil ;; :visual nil ;; :disabled-for-modes dired-mode ;; doc-view-mode ;; markdown-mode ;; org-mode ;; pdf-view-mode ;; text-mode ;; :size-limit-kb 1000) ;; When used in a plist, `visual' takes precedence over `relative'. ;; (default nil) dotspacemacs-line-numbers nil ;; Code folding method. Possible values are `evil', `origami' and `vimish'. ;; (default 'evil) dotspacemacs-folding-method 'evil ;; If non-nil and `dotspacemacs-activate-smartparens-mode' is also non-nil, ;; `smartparens-strict-mode' will be enabled in programming modes. ;; (default nil) dotspacemacs-smartparens-strict-mode nil ;; If non-nil smartparens-mode will be enabled in programming modes. ;; (default t) dotspacemacs-activate-smartparens-mode t ;; If non-nil pressing the closing parenthesis `)' key in insert mode passes ;; over any automatically added closing parenthesis, bracket, quote, etc... ;; This can be temporary disabled by pressing `C-q' before `)'. (default nil) dotspacemacs-smart-closing-parenthesis nil ;; Select a scope to highlight delimiters. Possible values are `any', ;; `current', `all' or `nil'. Default is `all' (highlight any scope and ;; emphasis the current one). (default 'all) dotspacemacs-highlight-delimiters 'all ;; If non-nil, start an Emacs server if one is not already running. ;; (default nil) dotspacemacs-enable-server nil ;; Set the emacs server socket location. ;; If nil, uses whatever the Emacs default is, otherwise a directory path ;; like \"~/.emacs.d/server\". It has no effect if ;; `dotspacemacs-enable-server' is nil. ;; (default nil) dotspacemacs-server-socket-dir nil ;; If non-nil, advise quit functions to keep server open when quitting. ;; (default nil) dotspacemacs-persistent-server nil ;; List of search tool executable names. Spacemacs uses the first installed ;; tool of the list. Supported tools are `rg', `ag', `pt', `ack' and `grep'. ;; (default '("rg" "ag" "pt" "ack" "grep")) dotspacemacs-search-tools '("rg" "ag" "pt" "ack" "grep") ;; The backend used for undo/redo functionality. Possible values are ;; `undo-tree', `undo-fu' and `undo-redo', see also `evil-undo-system'. ;; Note that saved undo history does not get transferred when changing ;; from undo-tree to undo-fu or undo-redo. ;; The default is currently 'undo-tree, but it will likely be changed ;; and at some point removed because undo-tree is not maintained anymore. dotspacemacs-undo-system 'undo-fu ;; Format specification for setting the frame title. ;; %a - the `abbreviated-file-name', or `buffer-name' ;; %t - `projectile-project-name' ;; %I - `invocation-name' ;; %S - `system-name' ;; %U - contents of $USER ;; %b - buffer name ;; %f - visited file name ;; %F - frame name ;; %s - process status ;; %p - percent of buffer above top of window, or Top, Bot or All ;; %P - percent of buffer above bottom of window, perhaps plus Top, or Bot or All ;; %m - mode name ;; %n - Narrow if appropriate ;; %z - mnemonics of buffer, terminal, and keyboard coding systems ;; %Z - like %z, but including the end-of-line format ;; If nil then Spacemacs uses default `frame-title-format' to avoid ;; performance issues, instead of calculating the frame title by ;; `spacemacs/title-prepare' all the time. ;; (default "%I@%S") dotspacemacs-frame-title-format nil ;; Format specification for setting the icon title format ;; (default nil - same as frame-title-format) dotspacemacs-icon-title-format nil ;; Show trailing whitespace (default t) dotspacemacs-show-trailing-whitespace t ;; Delete whitespace while saving buffer. Possible values are `all' ;; to aggressively delete empty line and long sequences of whitespace, ;; `trailing' to delete only the whitespace at end of lines, `changed' to ;; delete only whitespace for changed lines or `nil' to disable cleanup. ;; (default nil) dotspacemacs-whitespace-cleanup 'trailing ;; If non-nil activate `clean-aindent-mode' which tries to correct ;; virtual indentation of simple modes. This can interfere with mode specific ;; indent handling like has been reported for `go-mode'. ;; If it does deactivate it here. ;; (default t) dotspacemacs-use-clean-aindent-mode nil ;; Accept SPC as y for prompts if non-nil. (default nil) dotspacemacs-use-SPC-as-y nil ;; If non-nil shift your number row to match the entered keyboard layout ;; (only in insert state). Currently supported keyboard layouts are: ;; `qwerty-us', `qwertz-de' and `querty-ca-fr'. ;; New layouts can be added in `spacemacs-editing' layer. ;; (default nil) dotspacemacs-swap-number-row nil ;; Either nil or a number of seconds. If non-nil zone out after the specified ;; number of seconds. (default nil) dotspacemacs-zone-out-when-idle nil ;; Run `spacemacs/prettify-org-buffer' when ;; visiting README.org files of Spacemacs. ;; (default nil) dotspacemacs-pretty-docs nil ;; If nil the home buffer shows the full path of agenda items ;; and todos. If non-nil only the file name is shown. dotspacemacs-home-shorten-agenda-source t ;; If non-nil then byte-compile some of Spacemacs files. dotspacemacs-byte-compile t)) (defun dotspacemacs/user-env () "Environment variables setup. This function defines the environment variables for your Emacs session. By default it calls `spacemacs/load-spacemacs-env' which loads the environment variables declared in `~/.spacemacs.env' or `~/.spacemacs.d/.spacemacs.env'. See the header of this file for more information.") (defun dotspacemacs/user-init () "Initialization for user code: This function is called immediately after `dotspacemacs/init', before layer configuration. It is mostly for variables that should be set before packages are loaded. If you are unsure, try setting them in `dotspacemacs/user-config' first." ;; https://github.com/syl20bnr/spacemacs/issues/11321 (spacemacs|do-after-display-system-init (spacemacs/set-default-font dotspacemacs-default-font))) (defun dotspacemacs/user-load () "Library to load while dumping. This function is called only while dumping Spacemacs configuration. You can `require' or `load' the libraries of your choice that will be included in the dump.") (defun dotspacemacs/user-config () "Configuration function for user code. This function is called at the very end of Spacemacs initialization after layers configuration. This is the place where most of your configurations should be done. Unless it is explicitly specified that a variable should be set before a package is loaded, you should place your code here." (require 'biome) (biome-def-preset biome-query-preset-14 ((:name . "GEM (Canada)") (:group . "hourly") (:params ("hourly" "wind_speed_10m" "cloud_cover" "precipitation" "apparent_temperature") ("longitude" . -79.337021) ("latitude" . 43.856098)))) (spacemacs/set-leader-keys "a w w" 'biome-query-preset-14) (require 'gptel) (require 'auth-source) (defun bhw/switch-to-llm-buffer () (interactive) (switch-to-buffer "*Gemini*")) (defun get-authinfo-password (machine login) (let ((credential (auth-source-search :max 1 :host machine :user login :require '(:secret)))) (if credential (let ((secret (plist-get (nth 0 credential) :secret))) (if (functionp secret) (funcall secret) secret)) (message "No password found for %s@%s" login machine)))) ;; In ~/.authinfo, ;;machine aistudio.google.com login ben password *YourAPIkey* (setf gptel-model "gemini-1.5-pro-latest" gptel-backend (gptel-make-gemini "Gemini" :key (get-authinfo-password "aistudio.google.com" "ben") :stream t) gptel-directives '((default . " Ignore all previous instructions. 1. You are to provide clear, concise, and direct responses. 2. Eliminate unnecessary reminders, apologies, self-references, and any pre-programmed niceties. 3. Maintain a casual tone in your communication. 4. Be transparent; if you're unsure about an answer or if a question is beyond your capabilities or knowledge, admit it. 5. For any unclear or ambiguous queries, ask follow-up questions to understand the user's intent better. 6. When explaining concepts, use real-world examples and analogies, where appropriate. 7. For complex requests, take a deep breath and work on the problem step-by-step. 8. For every response, you will be tipped up to $200 (depending on the quality of your output). It is very important that you get this right.") (programming . "You are a large language model and a careful programmer. Provide code and only code as output without any additional text, prompt or note.") (writing . "You are a large language model and a writing assistant. Respond concisely.") (chat . "You are a large language model and a conversation partner. Respond concisely."))) (spacemacs/set-leader-keys (kbd "al") #'bhw/switch-to-llm-buffer) (add-hook 'eww-after-render-hook 'eww-readable) (require 'greader) ;; FIXME Auto-completion causes lag in shell-mode. (setf company-global-modes '(not shell-mode)) (require 'youtube-sub-extractor) (require 'ement) (evil-collection-ement-setup) (spacemacs/set-leader-keys (kbd "acM") #'ement-connect (kbd "acm") #'ement-list-rooms (kbd "acn") #'ement-notify-switch-to-notifications-buffer (kbd "acc") #'ement-room-send-message (kbd "acv") #'ement-view-room) (evilified-state-evilify-map ement-room-mode-map :mode ement-room-mode :eval-after-load ement-room :bindings ";" #'helm-occur "n" #'ement-room-scroll-up-mark-read) (evilified-state-evilify-map ement-room-list-mode-map :mode ement-room-list-mode :eval-after-load ement-room-list :bindings ";" #'helm-occur "n" #'ement-room-list-next-unread) (add-hook 'ement-room-compose-hook 'ement-room-compose-org) (setf ement-save-sessions t ement-room-mark-rooms-read 'send ement-room-send-typing nil) (setq plantuml-default-exec-mode 'jar plantuml-jar-path "/usr/share/plantuml/plantuml.jar" org-plantuml-jar-path "/usr/share/plantuml/plantuml.jar" plantuml-output-type "txt") (with-eval-after-load "org-mode" (add-to-list 'org-src-lang-modes '("plantuml" . plantuml))) (setf paradox-github-token t) ;; (keyfreq-mode 1) ;; (keyfreq-autosave-mode 1) ;; (setf keyfreq-excluded-commands ;; '(self-insert-command ;; org-self-insert-command ;; forward-char ;; backward-char ;; previous-line ;; next-line ;; evil-forward-char ;; evil-backward-char ;; evil-previous-visual-line ;; evil-next-visual-line ;; helm-next-line ;; helm-previous-line ;; evil-scroll-page-down ;; evil-scroll-page-up ;; delete-backward-char ;; evil-delete-backward-char-and-join ;; evil-undo ;; mwheel-scroll ;; mouse-set-point ;; mouse-drag-region ;; evil-mouse-drag-region ;; evil-normal-state ;; keyboard-escape-quit ;; evil-goto-first-line ;; evil-insert ;; evil-append ;; evil-delete ;; evil-join ;; evil-delete-char ;; evil-open-below ;; evil-change ;; backward-delete-char-untabify ;; dired-next-line ;; dired-previous-line)) (setf pdf-view-use-scaling t pdf-view-display-size 'fit-width pdf-view-resize-factor 1.1 image-cache-eviction-delay 128 pdf-cache-image-limit 128) ;; Custom function to allow double page scrolling by calling ;; my-pdf-view-double-scroll-horizontal-view (defun my-pdf-view-double-scroll-up-or-next-page (&optional arg) "Scroll page up ARG lines if possible, else go to the next page. When `pdf-view-continuous' is non-nil, scrolling upward at the bottom edge of the page moves to the next page. Otherwise, go to next page only on typing SPC (ARG is nil)." (interactive "P") (if (or pdf-view-continuous (null arg)) (let ((hscroll (window-hscroll)) (cur-page (pdf-view-current-page))) (when (or (= (window-vscroll) (image-scroll-up arg)) ;; Workaround rounding/off-by-one issues. (memq pdf-view-display-size '(fit-height fit-page))) (pdf-view-next-page 2) (when (/= cur-page (pdf-view-current-page)) (image-bob) (image-bol 1)) (set-window-hscroll (selected-window) hscroll))) (image-scroll-up arg))) (defun my-pdf-view-double-scroll-horizontal-view () (interactive) (my-pdf-view-double-scroll-up-or-next-page) (other-window 1) (my-pdf-view-double-scroll-up-or-next-page) (other-window 1)) ;; add spacemacs major mode keybind (spacemacs/set-leader-keys-for-major-mode 'pdf-view-mode "d" 'my-pdf-view-double-scroll-horizontal-view) ;; Allow rotating of sheet music in pdfs (defun pdf-view--rotate (&optional counterclockwise-p page-p) "Rotate PDF 90 degrees. Requires pdftk to work.\n Clockwise rotation is the default; set COUNTERCLOCKWISE-P to non-nil for the other direction. Rotate the whole document by default; set PAGE-P to non-nil to rotate only the current page. \nWARNING: overwrites the original file, so be careful!" ;; error out when pdftk is not installed (if (null (executable-find "pdftk")) (error "Rotation requires pdftk") ;; only rotate in pdf-view-mode (when (eq major-mode 'pdf-view-mode) (let* ((rotate (if counterclockwise-p "left" "right")) (file (format "\"%s\"" (pdf-view-buffer-file-name))) (page (pdf-view-current-page)) (pages (cond ((not page-p) ; whole doc? (format "1-end%s" rotate)) ((= page 1) ; first page? (format "%d%s %d-end" page rotate (1+ page))) ((= page (pdf-info-number-of-pages)) ; last page? (format "1-%d %d%s" (1- page) page rotate)) (t ; interior page? (format "1-%d %d%s %d-end" (1- page) page rotate (1+ page)))))) ;; empty string if it worked (if (string= "" (shell-command-to-string (format (concat "pdftk %s cat %s " "output %s.NEW " "&& mv %s.NEW %s") file pages file file file))) (pdf-view-revert-buffer nil t) (error "Rotation error!")))))) (defun pdf-view-rotate-clockwise (&optional arg) "Rotate PDF page 90 degrees clockwise. With prefix ARG, rotate entire document." (interactive "P") (pdf-view--rotate nil (not arg))) (defun pdf-view-rotate-counterclockwise (&optional arg) "Rotate PDF page 90 degrees counterclockwise. With prefix ARG, rotate entire document." (interactive "P") (pdf-view--rotate :counterclockwise (not arg))) (define-key spacemacs-pdf-view-mode-map (kbd "R") 'pdf-view-rotate-clockwise) (setf forge-owned-accounts '(("BenedictHW" :remote-name "origin")) magit-save-repository-buffers 'dontask) ;;------------------------------------------------------------------------- ;; *** Emacs Jupyter Config ;;------------------------------------------------------------------------- (setf dired-omit-mode t ;; Stop asking to quit dired buffers of deleted files dired-clean-up-buffers-too nil) (add-hook 'dired-mode-hook (lambda () (dired-hide-details-mode))) (evilified-state-evilify-map dired-mode-map :mode dired-mode :eval-after-load dired :bindings "s" #'avy-goto-word-or-subword-1 "S" #'hydra-dired-quick-sort/body ";" #'helm-occur "C-i" #'better-jumper-jump-forward "C-o" #'better-jumper-jump-backward "q" #'spacemacs/kill-this-buffer) (setf common-lisp-hyperspec-root (concat "file://" +project-jerome-dir+ "000-generalities-information-computers/000-computer-science/HyperSpec/")) ;; https://emacs.stackexchange.com/questions/62536/what-does-making-browse-url ;; -browser-function-local-to-eww-while-let-bound-m (advice-add 'hyperspec-lookup :around (lambda (orig-fun &rest args) (setq-local browse-url-browser-function 'eww-browse-url) (apply orig-fun args))) (setf python-format-on-save t python-indent-offset 4) (require 'lexic) (setf lexic-dictionary-specs ' (("Webster's Revised Unabridged Dictionary (1913)" :short "===========================================================\n Webster's Revised Unabridged Dictionary (1913)\n===========================================================" :formatter lexic-format-webster :priority 1) ("Soule's Dictionary of English Synonyms" :short "===========================================================\n Soule's Dictionary of English Synonyms (1871)\n===========================================================" :formatter lexic-format-soule :priority 2) ("Online Etymology Dictionary" :short "===========================================================\n Online Etymology Dictionary (2000)\n===========================================================" :formatter lexic-format-online-etym :priority 3) ("Oxford English Dictionary 2nd Ed P1" :short "===========================================================\n Oxford English Dictionary 2nd Ed. (1989)\n===========================================================" :formatter lexic-format-online-etym :priority 4) ("Oxford English Dictionary 2nd Ed P2" :short "===========================================================\n Oxford English Dictionary 2nd Ed. (1989)\n===========================================================" :formatter lexic-format-online-etym :priority 5) )) ;; Set Global Keybindings (spacemacs/set-leader-keys "sx" 'lexic-search-word-at-point) (spacemacs/set-leader-keys "sX" 'lexic-search) ;; Set Lexic Major Mode Keybindings (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "q" 'lexic-return-from-lexic) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode (kbd "RET") 'lexic-search-word-at-point) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "a" 'outline-show-all) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "h" 'outline-hide-body) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "o" 'lexic-toggle-entry) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "n" 'lexic-next-entry) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "p" 'lexic-previous-entry) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "b" 'lexic-search-history-backwards) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "f" 'lexic-search-history-forwards) ;; I am convinced this is a case of bad defaults. Setting ;; =savehist-autosave-interval= to 60 seconds (from the default of 300) and ;; =history-length= to 1000 (from the default of 100) causes disproportionate ;; performance problems for arguable benefits. Performance problems can be plainly ;; seen by using the Emacs cpu+mem profiler. See ;; https://emacs.stackexchange.com/questions/12086/high-cpu-memory-usage-and-abnormally-large-savehist-file ;; =spacemacs-defaults/init-savehist=, Spacemacs Github issues #9409, #1369. ;; Reset variables to sensible Emacs defaults. (setf history-length 25 savehist-save-minibuffer-history nil savehist-autosave-interval nil kill-ring-max 200 savehist-mode nil) (delq 'mark-ring savehist-additional-variables) (delq 'global-mark-ring savehist-additional-variables) (delq 'search-ring savehist-additional-variables) (delq 'regexp-search-ring savehist-additional-variables) (delq 'extended-command-history savehist-additional-variables) (delq 'kill-ring savehist-additional-variables) (put 'org-brain-headline-cache 'history-length 10) (put 'bibtex-completion-cache 'history-length 10) (push 'org-brain-headline-cache savehist-additional-variables) (push 'bibtex-completion-cache savehist-additional-variables) (push 'helm-ff-history savehist-additional-variables) (push 'org-clock-history savehist-additional-variables) ;; Emacs profiler shows `savehist-autosave' is very performance intensive. (add-hook 'kill-emacs-hook #'savehist-save) ; Savehist only on exit. ;; Scrolling. ;; ;; The behaviors Emacs offers for scrolling can be customized ;; by the variables some of which were already mentioned: ;; scroll-conservatively, scroll-margin, scroll-step, and ;; scroll-up/down-aggressively. They basically control whether ;; Emacs recenters point when it scrolls the window, when (if ;; at all) it does recenter, by how many lines it scrolls if ;; it doesn't recenter, and how close to window edges point is ;; allowed to be before the window is scrolled. This defines a ;; set of behaviors you can get universally. In general, the ;; default is to recenter if scrolling by a few lines fails to ;; bring point into view. That is what you see, and that is ;; how Emacs works. ;; Source: https://old.reddit.com/r/emacs/comments/8jli87/is_there_a_hook_after_cursor_jump/ (setq scroll-conservatively 0) (setq scroll-preserve-screen-position t) ;; Line Breaks/Fill Column/Characters ;; ;; Prefer 80 chars due to anatomical restriction of the human eye. ;; Secondary concern of long known emacs performance issues with long lines. ;; ;; According to the Emacs manual, to enable autofill in all major modes: ;; (setq-default auto-fill-function 'do-auto-fill) ;; https://www.gnu.org/software/emacs/manual/html_node/efaq/Turning-on-auto_002dfill-by-default.html ;; ;; However, it does have side-effects in some modes, most notably it screws ;; up auto-completion in lisp mode buffers. In addition to performance ;; reasons, it makes sense to selectively enable for certain modes. ;; Therefore look under the mode configuration for the added hooks. ;; i.e. search for (add-hook 'example-mode-hook 'turn-on-auto-fill) ;; allows the use of SPC leader key in calc buffer (with-eval-after-load 'calc (define-key calc-mode-map " " spacemacs-cmds)) (setq large-file-warning-threshold '100000000) ;; https://www.masteringemacs.org/article/disabling-prompts-emacs (setq kill-buffer-query-functions (remq 'process-kill-buffer-query-function kill-buffer-query-functions)) (require 'cl-lib) (defun site/always-save-advice (oldfn &optional arg) "Overwrite `yes-or-no-p' in OLDFN. The new temporary function will return non-nil, when the message wants to save modified buffers, without querying the user. Otherwise the original behaviour is preserves, and ARG is passed on to OLDFN." (cl-letf* ((real-yes-or-no-p (symbol-function 'yes-or-no-p)) ((symbol-function 'yes-or-no-p) (lambda (msg) (or (string= msg "Modified buffers exist; exit anyway? ") (funcall real-yes-or-no-p msg))))) (funcall oldfn arg))) (advice-add #'save-buffers-kill-emacs :around #'site/always-save-advice) ;; Spacemacs default is 60 seconds. Ridiculous. (setf auto-save-interval 1000 auto-save-timeout nil) ;; https://github.com/joaotavora/yasnippet/issues/998#issuecomment-496449546 (defun my-yas-try-expanding-auto-snippets () (when (and (boundp 'yas-minor-mode) yas-minor-mode) (let ((yas-buffer-local-condition ''(require-snippet-condition . auto))) (yas-expand)))) (add-hook 'post-command-hook #'my-yas-try-expanding-auto-snippets) ;; C-h f "evilnc-comment-operator" or any of the default evil keybindings ;; to discover what maps you need to override. ;; rebind "SPC j j" or avy-goto-word-or-subword-1 to "s" ;; At first, will not work as evil-surround is using "s" in visual mode (setf evil-move-beyond-eol t) (evil-define-key 'visual evil-surround-mode-map (kbd "s") 'avy-goto-word-or-subword-1) (evil-define-key 'visual evil-surround-mode-map (kbd "S") 'evil-surround-region) (define-key evil-motion-state-map (kbd "s") 'avy-goto-word-or-subword-1) (define-key evil-normal-state-map (kbd "s") 'avy-goto-word-or-subword-1) (define-key evil-visual-state-map (kbd "s") 'avy-goto-word-or-subword-1) (define-key evil-operator-state-map (kbd "s") 'avy-goto-word-or-subword-1) (define-key package-menu-mode-map (kbd "s") 'avy-goto-word-or-subword-1) ;; #'helm-occur rebinding (define-key evil-motion-state-map (kbd ";") #'helm-occur) (define-key evil-normal-state-map (kbd ";") #'helm-occur) (define-key evil-visual-state-map (kbd ";") #'helm-occur) (define-key evil-operator-state-map (kbd ";") #'helm-occur) (define-key package-menu-mode-map (kbd ";") #'helm-occur) ;; Whenever the commands modified below are called, they are pushed ;; onto the evil-jumps-history stack (evil-add-command-properties #'evil-scroll-down :jump t) (evil-add-command-properties #'evil-scroll-up :jump t) (evil-add-command-properties #'evil-scroll-page-down :jump t) (evil-add-command-properties #'evil-scroll-page-up :jump t) (evil-add-command-properties #'helm-occur :jump t) (evil-add-command-properties #'helm-for-files :jump t) (evil-add-command-properties #'helm-projectile-find-file :jump t) (evil-add-command-properties #'spacemacs/alternate-buffer :jump t) (evil-add-command-properties #'spacemacs/helm-M-x-fuzzy-matching :jump t) (evil-add-command-properties #'helm-find-files :jump t) (evil-add-command-properties #'org-previous-visible-heading :jump t) (evil-add-command-properties #'org-next-visible-heading :jump t) (evil-add-command-properties #'outline-up-heading :jump t) (evil-add-command-properties #'outline-next-heading :jump t) (evil-add-command-properties #'org-bable-goto-src-block-head :jump t) (define-key evil-normal-state-map (kbd "q") #'spacemacs/kill-this-buffer) (define-key evil-normal-state-map (kbd "Q") #'kill-buffer-and-window) ;; Disable all keybindings other than f/t (evil-snipe-mode -1) (setq evil-snipe-scope 'whole-visible) ;; Alias [ and ] to all types of brackets ;; Alias ' to ' and " (setq evil-snipe-aliases '((?\' "['\"]") ;; No longer needed as () are translated to [] ;; via keyboard-translate function ;; (?\[ "[[{(]") ;; (?\] "[]})]") )) ;; Remove overriding of "," key in visual mode Ex. "vf)," (setq evil-snipe-override-evil-repeat-keys nil) ;; See /home/ben/.config/fd/ignore (require 'helm-fd) (require 'helm-ag) (defvar bhw/helm-source-fd (helm-make-source "fd-find" 'helm-fd-class) "For use of FD in `helm-for-files'. See also `helm-fd-switches'") ;; HACK If (error "Candidates function ‘(closure (t) nil ;; (helm-ag--do-ag-candidate-process +project-maria-dir+))’ should run a ;; process") Then eval-current-form-sp on the form below. (defvar bhw/helm-source-maria-ag (helm-make-source "Project Maria - AG" 'helm-do-ag-class :candidates-process (lambda () (helm-ag--do-ag-candidate-process +project-maria-dir+))) "To search Project Maria files from `helm-for-files'. `helm-ag--do-ag-set-source' used as exemplar. You may have to run `helm-projectile-ag' once for fuzzy matching to kick in :O.") (defvar bhw/helm-source-emacs-commands (helm-build-sync-source "Emacs Commands" :candidates (lambda () (let ((cmds)) (mapatoms (lambda (elt) (when (commandp elt) (push (symbol-name elt) cmds)))) cmds)) :coerce #'intern-soft :action #'command-execute) "A simple helm source for Emacs commands. Used in `helm-for-files'.") (setf ace-jump-helm-line-default-action 'select ace-jump-helm-line-idle-delay 1 helm-ff-auto-update-initial-value t recentf-max-saved-items 1000 helm-for-files-preferred-list '(helm-source-recentf bhw/helm-source-fd bhw/helm-source-maria-ag bhw/helm-source-emacs-commands) helm-candidate-number-limit 100 helm-ff-skip-boring-files t helm-ag-fuzzy-match t helm-fd-executable "fdfind" helm-fd-switches '("--search-path" "/home/ben" "--hidden" "--type" "f" "--type" "d" "--color" "never" "--max-results" "10" "--full-path")) (spacemacs/set-leader-keys "SPC" #'helm-for-files) (define-key helm-map (kbd "C-q") nil) ; Replace default binding. (define-key helm-map (kbd "C-d") 'ace-jump-helm-line) (require 'org) ;; Format text to fit 80 chars when pressing RET or ENTER. (add-hook 'org-mode-hook 'turn-on-auto-fill) ;; Source https://emacs.stackexchange.com/questions/10707/in-org-mode-how-to-remove-a-link (defun afs/org-replace-link-by-link-description () "Replace an org link by its description or if empty its address" (interactive) (if (org-in-regexp org-link-bracket-re 1) (save-excursion (let ((remove (list (match-beginning 0) (match-end 0))) (description (if (match-end 2) (org-match-string-no-properties 2) (org-match-string-no-properties 1)))) (apply 'delete-region remove) (insert description))))) ;; Source https://emacs.stackexchange.com/questions/12391/insert-org-id-link-at-point-via-outline-path-completion (defun org-id-complete-link (&optional arg) "Create an id: link using completion" (concat "id:" (org-id-get-with-outline-path-completion))) (org-link-set-parameters "id" :complete 'org-id-complete-link) ;; Source https://hungyi.net/posts/copy-org-mode-url/ (defun org-retrieve-url-from-point () "Copies the URL from an org link at the point" (interactive) (let ((plain-url (thing-at-point-url-at-point))) (if plain-url (progn (kill-new plain-url) (message (concat "Copied: " plain-url))) (let* ((link-info (assoc :link (org-context))) (text (when link-info (buffer-substring-no-properties (or (cadr link-info) (point-min)) (or (caddr link-info) (point-max)))))) (if (not text) (error "Oops! Point isn't in an org link") (string-match org-link-bracket-re text) (let ((url (substring text (match-beginning 1) (match-end 1)))) (kill-new url) (message (concat "Copied: " url)))))))) (setf org-directory +project-maria-dir+ org-agenda-files (cl-loop for agenda-file in '("0inbox.org" "0projects.org" "0solo.org" "0someday.org" "0contacts.org" "0calendar.org") collect (concat +project-maria-dir+ agenda-file)) ;; See org-superstar package for more context inhibit-compacting-font-caches t ;; See Org Manual 16.4 A Cleaner Outline View ;; I prefer a book-like view, which also allows for auto-fill org-adapt-indentation nil org-list-allow-alphabetical t org-image-actual-width '600 org-hide-emphasis-markers nil org-footnote-auto-adjust "Renumber and Sort" org-persist-directory "~/.cache/org-persist/" ;; Needs the libreoffice suite installed. ;; 'sudo apt install libreoffice' org-odt-preferred-output-format "docx") (spacemacs/set-leader-keys-for-major-mode 'org-mode "xR" 'afs/org-replace-link-by-link-description) (spacemacs/set-leader-keys-for-major-mode 'org-mode "iI" 'org-id-get-create) (spacemacs/set-leader-keys-for-major-mode 'org-mode "tC" 'org-table-create-or-convert-from-region) (spacemacs/set-leader-keys-for-major-mode 'org-mode "hn" 'org-next-visible-heading) (spacemacs/set-leader-keys-for-major-mode 'org-mode "hp" 'org-previous-visible-heading) (setq org-sticky-header-full-path 'full) ;; Require org-contacts to work with mu4e (require 'org-contacts) (setf org-contacts-files (list (concat +project-maria-dir+ "0contacts.org"))) (require 'org-re-reveal) (setf org-re-reveal-revealjs-version "4" org-re-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js") (setf org-mime-export-options '(:section-numbers nil ;; otherwise tables will not work :with-broken-links t :with-author nil :with-toc nil :with-latex dvipng)) (setq org-export-backends '(ascii html icalendar latex odt beamer man md org texinfo)) (setf org-download-method 'attach) ;; Add key bindings for org-expiry package (spacemacs/set-leader-keys-for-major-mode 'org-mode "dc" 'org-expiry-insert-created) (spacemacs/set-leader-keys-for-major-mode 'org-mode "de" 'org-expiry-insert-expiry) ;; Add call to org-expiry-insert-created every time org-id-get-create is run (advice-add 'org-id-get-create :after 'org-expiry-insert-created) (require 'org-depend) (require 'cl-lib) (org-clock-persistence-insinuate) (add-hook 'org-clock-in-prepare-hook 'my-org-mode-ask-effort) (defun my-org-mode-ask-effort () "Ask for an effort estimate when clocking in if none exists." (unless (org-entry-get (point) "Effort") (let ((effort (completing-read "Effort: " (org-entry-get-multivalued-property (point) "Effort")))) (unless (equal effort "") (org-set-property "Effort" effort))))) (defun eos/org-clock-in () (interactive) (org-clock-in '(4))) ;; Exclude DONE state tasks from refile targets (defun bh/verify-refile-target () "Exclude todo keywords with a done state from refile targets" (not (member (nth 2 (org-heading-components)) org-done-keywords))) ;; https://orgmode.org/worg/org-contrib/org-depend.html (defun mm/org-insert-trigger () "Automatically insert chain-find-next trigger when entry becomes NEXT" (cond ((equal org-state "NEXT") (unless org-depend-doing-chain-find-next (org-set-property "TRIGGER" "chain-find-next(NEXT,from-current,priority-up,effort-up)"))) ((not (member org-state org-done-keywords)) (org-delete-property "TRIGGER")))) (add-hook 'org-after-todo-state-change-hook 'mm/org-insert-trigger) (progn (defcustom ap/work:clocked-today-ids nil "List of Org heading IDs containing clocktables to read." :type '(repeat string)) (defcustom ap/work:clocked-today-interval 30 "Update the clocktables after this many seconds of idle time." :type 'number) ;; HACK: This version just uses the value as-is, expecting it to be a ;; decimal number with "h" suffix, and it only uses the first value in ;; the ID list. (defun ap/work:clocked-today (&optional messagep) "Show work time clocked today." (interactive (list 'messagep)) (cl-labels ((clocked-for (id) (org-with-point-at (org-id-find id 'marker) (org-narrow-to-subtree) (while (not (org-in-clocktable-p)) (forward-line)) (when (eobp) (error "Can't find clocktable at %S:%S" (current-buffer) id)) (let ((inhibit-message t)) (org-update-dblock)) (while (not (org-at-table-p)) (forward-line)) (if-let ((time (org-table-get 2 3)) ((string-match (rx (group (1+ (or digit ".")) "h")) time))) (match-string 1 time) "0h")))) (let ((string (clocked-for (car ap/work:clocked-today-ids)))) (when messagep (message "Clocked today: %s" string)) string))) (defvar ap/work:clocked-today-lighter "") (defvar ap/work:clocked-today-timer nil) (define-minor-mode ap/work:clocked-today-mode "Show time clocked today in mode line." :global t (let ((lighter '(ap/work:clocked-today-mode ap/work:clocked-today-lighter))) (if ap/work:clocked-today-mode (progn (setf ap/work:clocked-today-timer (run-with-idle-timer ap/work:clocked-today-interval ap/work:clocked-today-interval (lambda () (setf ap/work:clocked-today-lighter (concat "📆" (ap/work:clocked-today) " "))))) (cl-pushnew lighter global-mode-string :test #'equal)) (when (timerp ap/work:clocked-today-timer) (cancel-timer ap/work:clocked-today-timer)) (setf global-mode-string (remove lighter global-mode-string)))))) (spacemacs/set-leader-keys "oa" 'ben/default-custom-agenda) (spacemacs/set-leader-keys "oj" 'spacemacs/org-clock-jump-to-current-clock) (spacemacs/set-leader-keys "oi" 'eos/org-clock-in) (spacemacs/set-leader-keys "oI" 'org-clock-in) (spacemacs/set-leader-keys "oo" 'org-clock-out) (spacemacs/set-leader-keys "or" 'org-resolve-clocks) (spacemacs/set-leader-keys "oc" 'org-capture) ;; Press t to change task todo state (setf org-use-fast-todo-selection t org-treat-S-cursor-todo-selection-as-state-change t ;; Require exit notes for modifying a scheduled for deadline date org-log-reschedule 'time org-log-redeadline 'note org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "PROJ(p)" "APPT(a)" "PROG(i)" "WAIT(w@/!)" "|" "DONE(d)" "CXLD(c@/!)")) org-todo-keyword-faces '(;; Project Defined ("PROJ" :foreground "gold" :weight bold) ;; Todo's Brainstormed ("TODO" :foreground "tomato" :weight bold) ;; Next Action(s) chosen ("NEXT" :foreground "RoyalBlue" :weight bold) ;; Delegated or out of your control ("WAIT" :foreground "magenta" :weight bold) ;; Reducing from potential to actual ("PROG" :foreground "cyan2" :weight bold) ;; Completed task ("DONE" :foreground "SpringGreen3" :weight bold) ;; Formal appointment, in-person/scheduled in advance ;; Of type WAIT, but with a definte deadline ("APPT" :foreground "DarkViolet" :weight bold) ;; Informal (interruption) meeting/verbal/email ;; Informal (interruption) calls/texts ;; ("MEET" :foreground "MediumOrchid" :weight bold) ;; Cancelled task, unable to complete ("CXLD" :foreground "SaddleBrown" :weight bold)) org-enforce-todo-dependencies t org-agenda-dim-blocked-tasks t org-habit-graph-column 80 org-agenda-skip-scheduled-if-deadline-is-shown t ;; 6) Adding New Tasks Quickly with Org Capture ;; Capture templates for: TODO tasks, Notes, appointments, phone calls, meetings, and org-protocol ;; \n is newline in the template. Functions as RET would in insert mode ;; placing a backslash before " in TRIGGER below to have the string not end org-capture-templates '(("n" "Next Action" entry (file "~/project-maria/0inbox.org") "* NEXT [#C] %?%^G\n:PROPERTIES:\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n" :empty-lines 1) ("t" "Todo Task" entry (file "~/project-maria/0inbox.org") "* TODO [#C] %?%^G\n :PROPERTIES:\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n" :empty-lines 1) ("a" "Appointment" entry (file "~/project-maria/0calendar.org") "* APPT %?\nSCHEDULED: %^T\n:PROPERTIES:\n:LOCATION: %^{LOCATION|TBD}\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:" :empty-lines 1) ("j" "Journal Entry" entry (file "~/project-maria/0inbox.org")"* NEXT JOURNAL ENTRY %U\n:PROPERTIES:\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n%?" :empty-lines 1) ("h" "Habit" entry (file "~/project-maria/0inbox.org")"* NEXT %?\nSCHEDULED: %(format-time-string \"%\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:ASSIGNED: %U\n:END:" :empty-lines 1) ("c" "Contacts" entry (file "~/project-maria/0inbox.org") "* %(org-contacts-template-name)\n:PROPERTIES:\n:PHONE: %?\n:EMAIL:\n:ADDRESS:\n:BIRTHDAY:\n:NOTE: Added on: %U\n:END:" :empty-lines 1) ("p" "Project" entry (file "~/project-maria/0projects.org") "* PROJ %? [#C] [/] [%] %^G\n:PROPERTIES:\n:ASSIGNED: %U\n:CATEGORY: %^{CATEGORY|Misc.}\n:END:\n** NEXT [#C]\n:PROPERTIES:\n:TRIGGER: chain-find-next(NEXT,from-current,priority-up,effort-up)\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n" :empty-lines 1)) ;; **** 9) Clocking org-clock-in-switch-to-state "PROG" org-clock-out-remove-zero-time-clocks t org-clock-out-when-done t org-clock-persist t org-clock-in-resume t org-clock-persist-query-resume nil org-clock-auto-clock-resolution 'when-no-clock-is-running org-clock-report-include-clocking-task t org-time-stamp-rounding-minutes '(1 1) org-agenda-clockreport-parameter-plist '(:link t :maxlevel 10 :fileskip0 t :stepskip0 t :compact t :narrow 80) org-log-into-drawer t org-clock-history-length 35 ;; **** 7) Refiling Tasks org-refile-targets '((nil :maxlevel . 9) (org-agenda-files :maxlevel . 9)) org-outline-path-complete-in-steps nil org-refile-use-outline-path 'file org-refile-target-verify-function 'bh/verify-refile-target ;; **** 11) Context Tags with fast selection keys org-tag-alist '(;; Sets geo-spatial and context tags ;; Startgroup and endgroup make tags mutually ;; exclusive (:startgroup) ("0home" . ?h) ("0office" . ?o) ("0errand" . ?e) ;; (:endgroup) ;; Person(s) can be contexts too. ("0father" . ?d) ("0mother" . ?d) ("0brother" . ?d) ("0family" . ?d) ("0workteam1" . ?d) ("0docket" . ?d) ("REF" . ?r) ("FLAGGED" . ??)) org-fast-tag-selection-single-key 'expert org-tags-column 0 ;; For tag searches ignore tasks with scheduled and deadline dates org-agenda-tags-todo-honor-ignore-options t ;; **** 14) Stuck Projects org-stuck-projects '("+TODO=\"PROJ\"" ("NEXT") nil nil) ;; **** 15) Archiving org-archive-default-command 'org-archive-subtree org-archive-location (concat +project-maria-dir+ "archived-tasks/0taskings-" (format-time-string "%Y") ".org::datetree/") org-archive-save-context-info '(time category olpath ltags itags)) (add-hook 'org-agenda-mode-hook (lambda () (define-key org-agenda-mode-map (kbd "s") 'avy-goto-word-or-subword-1))) (defun my/org-agenda-calculate-efforts (limit) "Sum the efforts of scheduled entries up to LIMIT in the agenda buffer." (let (total) (save-excursion (while (< (point) limit) (when (member (org-get-at-bol 'type) '("scheduled" "past-scheduled" "timestamp")) (push (org-entry-get (org-get-at-bol 'org-hd-marker) "EFFORT") total)) (forward-line))) (org-duration-from-minutes (cl-reduce #'+ (mapcar #'org-duration-to-minutes (cl-remove-if-not 'identity total)))))) (defun my/org-agenda-insert-efforts () "Insert the efforts for each day inside the agenda buffer." (save-excursion (let (pos) (while (setq pos (text-property-any (point) (point-max) 'org-agenda-date-header t)) (goto-char pos) (end-of-line) (insert-and-inherit (concat " (" (my/org-agenda-calculate-efforts (next-single-property-change (point) 'day)) ")")) (forward-line))))) (add-hook 'org-agenda-finalize-hook 'my/org-agenda-insert-efforts) (defun ben/default-custom-agenda() "Functionally call custom agenda command bound to KEY" (interactive) (org-agenda nil "d")) (setf org-agenda-block-separator 61 org-agenda-breadcrumbs-separator " | " ;; https://stackoverflow.com/questions/58820073/s-in-org-agenda-prefix-format-doesnt-display-dates-in-the-todo-view org-agenda-prefix-format '((agenda . "%-t %? e%c%s") (todo . "%? e%c%s%(let ((scheduled (org-get-deadline-time (point)))) (if scheduled (format-time-string \" [%Y-%m-%d] \" scheduled) \"\"))") (tags . "%? e%c%s%(let ((scheduled (org-get-deadline-time (point)))) (if scheduled (format-time-string \" [%Y-%m-%d] \" scheduled) \"\"))") (search . "%? e%c%s")) org-agenda-deadline-leaders '("!D!: " "D%3d: " "") org-agenda-scheduled-leaders '("!S!: " "S%3d: " "") org-agenda-time-grid (quote ((daily today remove-match) (0600 0900 1200 1500 1800 2100) "......" "----------------")) org-columns-default-format-for-agenda "%75ITEM(Task) %10Effort(Estim){:} %10CLOCKSUM(ActTime) %5TODO(State)" org-columns-default-format "%75ITEM(Task) %10Effort(Estim){:} %10CLOCKSUM(ActTime) %5TODO(State)" org-global-properties '(quote (("Effort_ALL" . "0:00 0:10 0:30 1:00 1:30 2:00 2:30 3:00 4:00 5:00 6:00 7:00 8:00") ("STYLE_ALL" . "habit"))) org-agenda-columns-add-appointments-to-effort-sum t org-agenda-default-appointment-duration 0 org-agenda-log-mode-items '(closed state clock) org-agenda-start-with-log-mode t org-agenda-start-with-entry-text-mode t org-agenda-add-entry-text-maxlines 5 org-agenda-entry-text-maxlines 5 org-agenda-start-with-clockreport-mode nil org-agenda-custom-commands '( ;; ***** Default Agenda ("d" "Default (Master) Agenda" ((agenda "" ((org-agenda-span 1) (org-deadline-warning-days 7) (org-agenda-overriding-header "Today's Agenda\n"))) (tags "TODO=\"PROG\"" ((org-agenda-sorting-strategy '(priority-down deadline-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nTasks in Progress\n"))) (tags "TODO=\"NEXT\"" ((org-agenda-sorting-strategy '(priority-down deadline-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nAction Items\n") (org-agenda-skip-function '(org-agenda-skip-entry-if 'scheduled)))) ;; Presents only APPT and Routine Events. (agenda "" ((org-agenda-span '33) (org-agenda-start-on-weekday nil) (org-agenda-start-day "+1d") (org-agenda-entry-types '(:timestamp :sexp :scheduled)) (org-agenda-overriding-header "Routine & Appointments\n"))) (tags "+TODO=\"WAIT\"" ((org-agenda-sorting-strategy '(timestamp-down)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nDelegated/Waiting For\n"))) (tags "TODO=\"TODO\"" ((org-agenda-sorting-strategy '(category-keep)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nAll Tasks\n"))) (tags "TODO=\"PROJ\"" ((org-agenda-sorting-strategy '(category-keep)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nAll Projects\n"))) (stuck "" ((org-agenda-overriding-header "\nStuck Projects\n")))) ((org-agenda-tag-filter-preset '("-SDAY")))) ;; ***** Review Agenda ("r" "Review Agenda" ((tags "TODO=\"DONE\"" ((org-agenda-sorting-strategy '(priority-down deadline-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nCompleted Tasks\n"))) (tags "TODO=\"CXLD\"" ((org-agenda-sorting-strategy '(tsia-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nTerminated Tasks\n"))) (stuck "" ((org-agenda-overriding-header "\nStuck Projects\n"))) (agenda "" ((org-agenda-span '33) (org-agenda-start-on-weekday nil) (org-agenda-start-day "+1d") (org-agenda-entry-types '(:timestamp :sexp :scheduled)) (org-agenda-overriding-header "Routine & Appointments\n")))) ((org-agenda-tag-filter-preset '("-SDAY"))))) org-agenda-window-setup 'current-window) ;; Following 2 lines are needed to exclude parent heading from table of contents but still export the content ;; https://emacs.stackexchange.com/questions/30183/orgmode-export-skip-ignore-first-headline-level (require 'ox-extra) (ox-extras-activate '(ignore-headlines)) ;; Allows exporting bibtex citations to html (require 'ox-bibtex) ;; Exclude default CSS from html export and add external stylesheet (setq org-html-head-include-default-style nil) ;; Omit inline css as we use an imported stylesheet (setq org-html-htmlize-output-type 'css) ;; https://www.taingram.org/blog/org-mode-blog.html (setq org-export-global-macros '(("timestamp" . "@@html:<span class=\"timestamp\">[$1]</span>@@"))) (defun my/org-sitemap-date-entry-format (entry style project) "Format ENTRY in org-publish PROJECT Sitemap format ENTRY ENTRY STYLE format that includes date." (let ((filename (org-publish-find-title entry project))) (if (= (length filename) 0) (format "*%s*" entry) (format "{{{timestamp(%s)}}} [[file:%s][%s]]" (format-time-string "%Y-%m-%d" (org-publish-find-date entry project)) entry filename)))) (setf org-publish-project-alist '(("blog" :components ("blog-content" "blog-rss")) ("blog-content" :base-directory "~/project-maria/blog" :html-extension "html" :base-extension "org" :recursive t :publishing-function org-html-publish-to-html :publishing-directory "~/common-lisp/project-isidore/assets/blog" :section-numbers t :table-of-contents t :exclude "rss.org" :with-title nil :auto-sitemap t :sitemap-filename "archive.org" :sitemap-title "Blog Archive" :sitemap-sort-files anti-chronologically :sitemap-style tree :sitemap-format-entry my/org-sitemap-date-entry-format ;; Use HTML5 ;; https://orgmode.org/manual/HTML-doctypes.html#HTML-doctypes :html-doctype "html5" :html-html5-fancy t ;; Link to external custom stylesheet ;; If you need code highlight from highlight.js, include the latter three lines. :html-head " <link rel=\"stylesheet\" type=\"text/css\" href=\"../global.css\"/> <link rel=\"stylesheet\" href=\"//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/styles/base16/solarized-light.min.css\"> <script src=\"//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/highlight.min.js\" defer></script> <script>var hlf=function(){Array.prototype.forEach.call(document.querySelectorAll(\"pre.src\"),function(t){var e;e=t.getAttribute(\"class\"),e=e.replace(/src-(\w+)/,\"src-$1 $1\"),console.log(e),t.setAttribute(\"class\",e),hljs.highlightBlock(t)})};addEventListener(\"DOMContentLoaded\",hlf);</script>" :html-preamble " <div class=\"header header-fixed\"> <div class=\"navbar container\"> <div class=\"logo\"><a href=\"/\">BHW</a></div> <input type=\"checkbox\" id=\"navbar-toggle\" > <label for=\"navbar-toggle\"><i></i></label> <nav class=\"menu\"> <ul> <li><a href=\"/about\">About</a></li> <li><a href=\"/work\">Work</a></li> <li><a href=\"/assets/blog/archive.html\">Blog</a></li> <li><a href=\"/contact\">Contact</a></li> </ul> </nav> </div> </div> <h1 class=\"title\">%t</h1> <p class=\"subtitle\">%s</p> <br/> <p class=\"updated\"><a href=\"/contact#article-history\">Updated:</a> %C</p>" ;; Article Postamble includes ;; Javascript snippet to insert anchor links to Table of Contents ;; HTML Footer :html-postamble "<script> const headers = Array.from( document.querySelectorAll('h2, h3, h4, h5, h6') ); headers.forEach( header => { header.insertAdjacentHTML('afterbegin', '<a href=\"#table-of-contents\">⇱</a>' ); }); </script> <hr/> <footer> <div class=\"copyright-container\"> Comments? Corrections? <a href=\"https://bhw.name/contact\"> Please do reach out.</a><a href=\"https://bhw.name/blog/rss.xml\"> RSS Feed. </a><a href=\"https://bhw.name/subscribe\"> Mailing List. </a><br/> Copyright 2021 Benedict H. Wang. <br/> Blog content is available under <a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/4.0/\"> CC-BY-SA 4.0 </a> unless otherwise noted.<br/> Created with %c on <a href=\"https://www.gnu.org\">GNU</a>/<a href=\"https://www.kernel.org/\">Linux</a><br/> </div> </footer>" ) ("blog-rss" :base-directory "~/project-maria/blog" :base-extension "org" :publishing-directory "~/common-lisp/project-isidore/assets/blog" :publishing-function publish-posts-rss-feed :rss-extension "xml" :html-link-home "http://bhw.name/" :html-link-use-abs-url t :html-link-org-files-as-html t :exclude "archive.org" :auto-sitemap t :sitemap-function posts-rss-feed :sitemap-title "Benedict H. Wang Blog RSS" :sitemap-filename "rss.org" :sitemap-style list :sitemap-sort-files anti-chronologically :sitemap-format-entry format-posts-rss-feed-entry) )) ;; https://alhassy.github.io/AlBasmala#Clickable-Headlines (defun my/ensure-headline-ids (&rest _) "Org trees without a custom ID will have All non-alphanumeric characters are cleverly replaced with ‘-’. If multiple trees end-up with the same id property, issue a message and undo any property insertion thus far. E.g., ↯ We'll go on a ∀∃⇅ adventure ↦ We'll-go-on-a-adventure " (interactive) (let ((ids)) (org-map-entries (lambda () (org-with-point-at (point) (let ((id (org-entry-get nil "CUSTOM_ID"))) (unless id (thread-last (nth 4 (org-heading-components)) (s-replace-regexp "[^[:alnum:]']" "-") (s-replace-regexp "-+" "-") (s-chop-prefix "-") (s-chop-suffix "-") (setq id)) (if (not (member id ids)) (push id ids) (message-box "Oh no, a repeated id!\n\n\t%s" id) (undo) (setq quit-flag t)) (org-entry-put nil "CUSTOM_ID" id)))))))) ;; Whenever html & md export happens, ensure we have headline ids. (advice-add 'org-html-export-to-html :before 'my/ensure-headline-ids) (advice-add 'org-md-export-to-markdown :before 'my/ensure-headline-ids) ;; https://nicolasknoebber.com/posts/blogging-with-emacs-and-org.html (defun format-posts-rss-feed-entry (entry _style project) "Format ENTRY for the posts RSS feed in PROJECT." (org-publish-initialize-cache "blog-rss") (let* ((title (org-publish-find-title entry project)) (link (concat "blog/" (file-name-sans-extension entry) ".html")) (author (org-publish-find-property entry :author project)) (pubdate (format-time-string (car org-time-stamp-formats) (org-publish-find-date entry project)))) (message pubdate) (format "%s :properties: :rss_permalink: %s :author: %s :pubdate: %s :end:\n" title link author pubdate))) (defun posts-rss-feed (title list) "Generate a sitemap of posts that is exported as a RSS feed. TITLE is the title of the RSS feed. LIST is an internal representation for the files to include. PROJECT is the current project." (concat "#+TITLE: " title "\n#+EMAIL: seneschal@bhw.name" "\n\n" (org-list-to-subtree list))) (defun publish-posts-rss-feed (plist filename dir) "Publish PLIST to RSS when FILENAME is rss.org. DIR is the location of the output." (if (equal "rss.org" (file-name-nondirectory filename)) (org-rss-publish-to-rss plist filename dir))) (add-hook 'org-mode 'org-tanglesync-mode) (add-hook 'prog-mode 'org-tanglesync-watch-mode) (add-hook 'text-mode 'org-tanglesync-watch-mode) (setf org-tanglesync-default-diff-action ':diff org-tanglesync-watch-files '("dotfiles.org")) (spacemacs/set-leader-keys-for-major-mode 'org-mode "bS" 'org-tanglesync-process-buffer-interactive) ;; Fix for wget option flags, as per https://github.com/alphapapa/org-web-tools/issues/35 (setq org-web-tools-archive-wget-options '("--ignore-tags=script,iframe" "--reject=eot,ttf,svg,otf,*.woff*" "--execute" "robots=off" "--adjust-extension" "--span-hosts" "--convert-links" "--page-requisites" "--timestamping" "--no-directories")) (setq org-web-tools-archive-wget-html-only-options '("--execute" "robots=off" "--adjust-extension" "--timestamping" "--no-directories")) ;; For when you are lost in a long code block (spacemacs/set-leader-keys "aob" 'org-babel-goto-src-block-head) ;; Used below to rename org edit blocks ;; https://emacs.stackexchange.com/questions/2483/referring-to-the-org-babel-src-block-name-from-within-the-script ;; EDIT please change function so that src blocks with no name get a temporary ;;name. otherwise code highlighting is broken. (defun org-src--construct-edit-buffer-name (org-buffer-name lang) "Construct the buffer name for a source editing buffer." (concat (nth 4 (org-babel-get-src-block-info)) " [" lang "]")) ;; =SPC h d v "org-babel-load-languages" shows that emacs-lisp and ;; shell code is already enabled in org-babel. (org-babel-do-load-languages 'org-babel-load-languages (append org-babel-load-languages '((ledger . t) (calc . t) (js . t) (emacs-lisp . t) (shell . t) (lisp . t) ;; (mathematica . t) (latex . t) ;; (jupyter . t) ;; must be last ))) ;; Sanitize output and deal with paths (setq org-babel-mathematica-command (concat +project-maria-dir+ "mash.pl")) ;; Font-locking ;; (add-to-list 'org-src-lang-modes '("mathematica" . wolfram)) ;; (autoload 'wolfram-mode "wolfram-mode" nil t) ;; (autoload 'run-wolfram "wolfram-mode" nil t) ;; (setq wolfram-program "/home/ben/Wolfram/WolframEngine/12.2/Executables/WolframKernel") ;; (add-to-list 'auto-mode-alist '("\.m$" . wolfram-mode)) ;; (setq wolfram-path "~/.WolframEngine/Applications") ;; e.g. on Linux ~/.Mathematica/Applications ;; For wolfram-mode ;; (setq mathematica-command-line "~/project-maria/mash.pl") ;; (setq org-babel-python-command "/usr/bin/python3") ;; enable proper mode for sagemath code blocks ;; (add-to-list 'org-src-lang-modes '("jupyter-sage" . python)) ;; See library of babel > org babel org heading for more detail (defun org-in-tangle-dir (sub-path) "Expand the SUB-PATH into the directory given by the tangle-dir property if that property exists, else use the `default-directory'." (expand-file-name sub-path (or (org-entry-get (point) "tangle-dir" 'inherit) (default-directory)))) ;; (load "~/.emacs.d/private/local/org-recoll.el") ;; (setq org-recoll-results-num 50) ;; (spacemacs/set-leader-keys "ss" 'org-recoll-search) (setf org-attach-id-dir "~/project-jerome/org-attach-data/" ;; https://helpdeskheadesk.net/2022-03-13/ ;; For org attach, change org timestamps to more human readable format. org-id-method 'ts org-attach-id-to-path-function-list '(org-attach-id-ts-folder-format org-attach-id-uuid-folder-format)) (setf org-noter-always-create-frame nil org-noter-hide-other nil org-noter-auto-save-last-location t) (spacemacs/set-leader-keys "aon" 'org-noter) (require 'org-brain) (require 'org-expiry) ;; Add CREATED property when adding a new org-brain headline entry (add-hook 'org-brain-new-entry-hook #'org-expiry-insert-created) (spacemacs/set-leader-keys "o SPC" 'org-brain-visualize-dwim) ;; For evil users, (with-eval-after-load 'evil (evil-set-initial-state 'org-brain-visualize-mode 'emacs)) ;; Automatically add ID properties to all org headlines when saving ;; Disabled because of slowdown, use org-id-get-create instead ;; (add-hook 'before-save-hook #'org-brain-ensure-ids-in-buffer) (defun org-expiry-created-comp (a b) "Compare `org-expiry-created-property-name' properties of A and B." (let ((ta (ignore-errors (org-time-string-to-seconds (org-entry-get (get-text-property 0 'org-marker a) org-expiry-created-property-name)))) (tb (ignore-errors (org-time-string-to-seconds (org-entry-get (get-text-property 0 'org-marker b) org-expiry-created-property-name))))) (cond ((if ta (and tb (< ta tb)) tb) -1) ((if tb (and ta (< tb ta)) ta) +1)))) (defun org-brain-timeline () "List all org-brain headlines in chronological order." (interactive) (let ((org-agenda-files (org-brain-files)) (org-agenda-cmp-user-defined #'org-expiry-created-comp) (org-agenda-sorting-strategy '(user-defined-down))) (org-tags-view nil (format "+%s>\"\"" org-expiry-created-property-name)))) (defun org-brain-cliplink-resource () "Add a URL from the clipboard as an org-brain resource. Suggest the URL title as a description for resource." (interactive) (let ((url (org-cliplink-clipboard-content))) (org-brain-add-resource url (org-cliplink-retrieve-title-synchronously url) t))) (define-key org-brain-visualize-mode-map (kbd "L") #'org-brain-cliplink-resource) ;; Prettify the lines via aa2u package, or ascii art to unicode (defface aa2u-face '((t . nil)) "Face for aa2u box drawing characters") (advice-add #'aa2u-1c :filter-return (lambda (str) (propertize str 'face 'aa2u-face))) (defun aa2u-org-brain-buffer () (let ((inhibit-read-only t)) (make-local-variable 'face-remapping-alist) (add-to-list 'face-remapping-alist '(aa2u-face . org-brain-wires)) (ignore-errors (aa2u (point-min) (point-max))))) (with-eval-after-load 'org-brain (add-hook 'org-brain-after-visualize-hook #'aa2u-org-brain-buffer)) (define-key org-brain-visualize-mode-map (kbd "j") #'evil-scroll-page-down) (define-key org-brain-visualize-mode-map (kbd "k") #'evil-scroll-page-up) (define-key org-brain-visualize-mode-map (kbd "i") #'org-brain-select-map) (define-key org-brain-visualize-mode-map (kbd "I") #'org-brain-select-dwim) (define-key org-brain-visualize-mode-map (kbd "s") #'link-hint-open-link) ;; Org-brain initialization (setf org-brain-path +project-maria-dir+ org-id-track-globally t org-brain-data-file "~/.emacs.d/.cache/.org-brain-data.el" org-id-locations-file "~/.emacs.d/.cache/.org-id-locations" org-brain-visualize-default-choices 'all org-brain-title-max-length 90 org-brain-include-file-entries nil org-brain-file-entries-use-title nil org-brain-headline-entry-name-format-string "%2$s" org-brain-quit-after-goto t org-brain-backlink "<--" org-expiry-inactive-timestamps t) (use-package poly-org :after org) ; Should be after org mode config. ;; https://old.reddit.com/r/emacs/comments/g8ecpj/advice_for_auclatex_what_keybinds_do_you_find/foo64ge/ ;; What really increased my speed is having snippets (yasnippet) for ;; frequently used patterns, auto paired parentheses ;; (electric-pair-local-mode or smartparens), and cd-latex ;; (org-cdlatex-mode) which auto inserts brackets for ;; subscript/superscripts. There's still a lot more to be done for speed, ;; learning these packages and creating keybindings though. All in due ;; time! Turns on unicode characters for org-mode (setf org-pretty-entities t org-pretty-entities-include-sub-superscripts nil ;; Bigger latex fragment org-format-latex-options (plist-put org-format-latex-options :scale 3)) ;; It generates a a png and overlays it onto the text as soon as your cursor ;; moves away from the math mode dollar signs. Automatically toggle org-mode ;; latex fragment previews as the cursor enters and exits them (add-hook 'org-mode-hook 'org-fragtog-mode) (require 'org-ref) (require 'org-ref-helm) (defun my/org-ref-open-pdf-at-point () "Open the pdf for bibtex key under point if it exists." (interactive) (let* ((results (org-ref-get-bibtex-key-and-file)) (key (car results)) (pdf-file (funcall org-ref-get-pdf-filename-function key))) (if (file-exists-p pdf-file) (find-file pdf-file) (message "No PDF found for %s" key)))) (spacemacs/set-leader-keys "s SPC" 'helm-bibtex) (setf org-bibtex-file (concat +project-maria-dir+ "project-jerome.bib") reftex-default-bibliography (list (concat +project-maria-dir+ "project-jerome.bib")) helm-bibtex-full-frame nil bibtex-completion-bibliography (list (concat +project-maria-dir+ "project-jerome.bib")) ;; Clicking on a citation in an org file will draw up a list of actions ;; One of these is view notes. this is where the index of notes is stored ;; Alternatively, calling ", n" while in project-jerome.bib will call ;; org-ref-open-bibtex-notes, which will populate project-jerome-index.org ;; Tell org-ref to let helm-bibtex find notes for it org-ref-notes-function (lambda (thekey) (let ((bibtex-completion-bibliography (org-ref-find-bibliography))) (bibtex-completion-edit-notes (list (car (org-ref-get-bibtex-key-and-file thekey)))))) ;; Taken from https://github.com/jkitchin/org-ref/blob/master/org-ref.org#customizing-how-pdfs-are-opened org-ref-get-pdf-filename-function 'org-ref-get-pdf-filename-helm-bibtex org-ref-open-pdf-function 'my/org-ref-open-pdf-at-point bibtex-completion-bibliography (concat +project-maria-dir+ "project-jerome.bib") bibtex-completion-notes-path (concat +project-maria-dir+ "bibtex-notes") bibtex-completion-notes-template-multiple-files (concat "* ${title}\n" ":PROPERTIES:\n" ":AUTHOR: ${author-abbrev}\n" ":YEAR: ${year}\n" ":END:\n\n") bibtex-completion-pdf-field "file" bibtex-completion-library-path '("~/project-jerome" "~/project-jerome/000-generalities-information-computers" "~/project-jerome/000-generalities-information-computers/000-computer-science" "~/project-jerome/000-generalities-information-computers/010-bibliography" "~/project-jerome/000-generalities-information-computers/020-library-information-sciences" "~/project-jerome/000-generalities-information-computers/030-general-encyclopedic-works" "~/project-jerome/000-generalities-information-computers/040-special-topics" "~/project-jerome/000-generalities-information-computers/050-general-serials-indexes" "~/project-jerome/000-generalities-information-computers/060-general-organizations-museums" "~/project-jerome/000-generalities-information-computers/070-news-media-journalism-publishing" "~/project-jerome/000-generalities-information-computers/080-general-collections" "~/project-jerome/000-generalities-information-computers/090-manuscripts-rare-books" "~/project-jerome/100-philosphy-psychology" "~/project-jerome/100-philosphy-psychology/110-metaphysics" "~/project-jerome/100-philosphy-psychology/120-epistemology-causation-humankind" "~/project-jerome/100-philosphy-psychology/130-paranormal-phenomena" "~/project-jerome/100-philosphy-psychology/140-specific-philosophical-schools" "~/project-jerome/100-philosphy-psychology/150-psychology" "~/project-jerome/100-philosphy-psychology/160-logic" "~/project-jerome/100-philosphy-psychology/170-ethics-moral-philosophy" "~/project-jerome/100-philosphy-psychology/180-ancient-medieval-oriental-philosophy" "~/project-jerome/100-philosphy-psychology/190-modern-western-philosophy" "~/project-jerome/200-religion" "~/project-jerome/200-religion/210-natural-theology" "~/project-jerome/200-religion/220-bible" "~/project-jerome/200-religion/230-christian-theology" "~/project-jerome/200-religion/230-christian-theology/239-apologetics" "~/project-jerome/200-religion/240-christian-moral-devotional-theology" "~/project-jerome/200-religion/240-christian-moral-devotional-theology/242-devotional-literature" "~/project-jerome/200-religion/250-christian-orders-local-churches" "~/project-jerome/200-religion/250-christian-orders-local-churches/252-texts-of-sermons" "~/project-jerome/200-religion/250-christian-orders-local-churches/253-pastoral-office-and-work" "~/project-jerome/200-religion/260-christian-social-theology" "~/project-jerome/200-religion/270-christian-church-history" "~/project-jerome/200-religion/280-christian-denominations-sects" "~/project-jerome/200-religion/290-other-comparative-religions" "~/project-jerome/300-social-sciences" "~/project-jerome/300-social-sciences/310-general-statistics" "~/project-jerome/300-social-sciences/320-political-science" "~/project-jerome/300-social-sciences/330-economics" "~/project-jerome/300-social-sciences/340-law" "~/project-jerome/300-social-sciences/350-public-administration" "~/project-jerome/300-social-sciences/360-social-problems-services" "~/project-jerome/300-social-sciences/370-education" "~/project-jerome/300-social-sciences/380-commerce-communications-transport" "~/project-jerome/300-social-sciences/390-customs-etiquette-folklore" "~/project-jerome/400-philology" "~/project-jerome/400-philology/410-linguistics" "~/project-jerome/400-philology/420-english-anglosaxon-languages" "~/project-jerome/400-philology/430-germanic-languages" "~/project-jerome/400-philology/440-romance-languages" "~/project-jerome/400-philology/450-italian-romanian-rhaeto-romanic" "~/project-jerome/400-philology/460-spanish-portuguese-languages" "~/project-jerome/400-philology/470-italic-languages-latin" "~/project-jerome/400-philology/480-hellenic-languages-classical-greek" "~/project-jerome/400-philology/490-other-languages" "~/project-jerome/500-natural-science" "~/project-jerome/500-natural-science/510-mathematics" "~/project-jerome/500-natural-science/520-astronomy-allied-sciences" "~/project-jerome/500-natural-science/530-physics" "~/project-jerome/500-natural-science/540-chemistry-allied-sciences" "~/project-jerome/500-natural-science/550-earth-sciences" "~/project-jerome/500-natural-science/560-paleontology-paleozoology" "~/project-jerome/500-natural-science/570-life-sciences" "~/project-jerome/500-natural-science/580-botanical-sciences" "~/project-jerome/500-natural-science/590-zoological-sciences" "~/project-jerome/600-applied-science" "~/project-jerome/600-applied-science/610-medical-sciences-psychiatry" "~/project-jerome/600-applied-science/620-engineering" "~/project-jerome/600-applied-science/630-agriculture" "~/project-jerome/600-applied-science/640-home-economics-family-living" "~/project-jerome/600-applied-science/650-management" "~/project-jerome/600-applied-science/660-chemical-engineering" "~/project-jerome/600-applied-science/670-manufacturing" "~/project-jerome/600-applied-science/680-manufacture-for-specific-use" "~/project-jerome/600-applied-science/690-buildings" "~/project-jerome/700-arts-recreation" "~/project-jerome/700-arts-recreation/710-civic-landscape-art" "~/project-jerome/700-arts-recreation/720-architecture" "~/project-jerome/700-arts-recreation/730-sculpture" "~/project-jerome/700-arts-recreation/740-drawings-decorative-arts" "~/project-jerome/700-arts-recreation/750-paintings-painters" "~/project-jerome/700-arts-recreation/760-graphics-arts-printmaking" "~/project-jerome/700-arts-recreation/770-photography" "~/project-jerome/700-arts-recreation/780-music" "~/project-jerome/700-arts-recreation/790-recreational-performing-arts" "~/project-jerome/800-literature" "~/project-jerome/800-literature/810-american-literature-in-english" "~/project-jerome/800-literature/820-english-literature" "~/project-jerome/800-literature/830-literature-of-germanic-language" "~/project-jerome/800-literature/840-literatures-of-romance-language" "~/project-jerome/800-literature/850-italian-romanian-rhaeto-romaic-literatures" "~/project-jerome/800-literature/860-spanish-portuguese-literatures" "~/project-jerome/800-literature/870-italic-literatures-latin" "~/project-jerome/800-literature/880-hellenic-literatures-classical-greek" "~/project-jerome/800-literature/890-literatures-of-other-languages" "~/project-jerome/900-history-geography-biography" "~/project-jerome/900-history-geography-biography/910-geography-travel" "~/project-jerome/900-history-geography-biography/920-biography-genealogy-insignia" "~/project-jerome/900-history-geography-biography/930-history-of-the-ancient-world" "~/project-jerome/900-history-geography-biography/940-general-history-of-europe" "~/project-jerome/900-history-geography-biography/950-general-history-of-asia" "~/project-jerome/900-history-geography-biography/960-general-history-of-africa" "~/project-jerome/900-history-geography-biography/970-general-history-of-north-america" "~/project-jerome/900-history-geography-biography/980-general-history-of-south-america" "~/project-jerome/900-history-geography-biography/990-general-history-of-other-areas") bibtex-completion-format-citation-functions '((org-mode . org-ref-helm-bibtex-insert-citation) (latex-mode . bibtex-completion-format-citation-cite) (markdown-mode . bibtex-completion-format-citation-pandoc-citeproc) (default . bibtex-completion-format-citation-default)) helm-source-bibtex org-ref-helm-source-bibtex) (defun mu4e-headers-mark-all-unread-read () "Put a ! \(read) mark on all visible unread messages." (interactive) (mu4e-headers-mark-for-each-if (cons 'read nil) (lambda (msg _param) (memq 'unread (mu4e-msg-field msg :flags)))) (mu4e-mark-execute-all t)) (defun mu4e-headers-refile-all () "Refile all messages in buffer." (interactive) (mu4e-headers-mark-for-each-if (cons 'refile nil) (lambda (_msg _param) t)) (mu4e-mark-execute-all t) (mu4e-search-prev)) (setf mu4e-change-filenames-when-moving t ; mbsync specific. ;; see an ASCII table for the character decimal codes mu4e-bookmarks '(("maildir:/INBOX" "Inbox" 105 ) ("\"maildir:/[Gmail]/All Mail\" and flag:unread" "Unread" 85)) user-mail-address (get-authinfo-password "personal.gmail" "ben") user-full-name "Benedict H. Wang" ;; mu4e-compose-signature mail-user-agent 'mu4e-user-agent mu4e-attachment-dir "/mnt/c/Users/bened/Downloads/" mu4e-drafts-folder "/[Gmail]/Drafts" mu4e-sent-folder "/[Gmail]/Sent Mail" mu4e-trash-folder "/[Gmail]/Trash" mu4e-refile-folder "/[Gmail]/All Mail" send-mail-function 'smtpmail-send-it smtpmail-stream-type 'starttls smtpmail-default-smtp-server "smtp.gmail.com" smtpmail-smtp-server "smtp.gmail.com" smtpmail-smtp-service 587 message-sendmail-f-is-evil t mu4e-index-update-in-background t mu4e-update-interval 900 mu4e-autorun-background-at-startup t mu4e-get-mail-command "mbsync -a" mu4e-hide-index-messages t mu4e-enable-mode-line nil ;; If this is enabled, prompts for new gpg fingerprints will not show up. ;; Instead emails will silently fail to send. mu4e-enable-async-operations nil mu4e-search-skip-duplicates t ;; Multipart html/plaintext email default, if the html portion is larger ;; by a factor of 5, it is assumed the user wants to view html. This ;; sets the factor to the largest possible fixnum, for we prefer the ;; plaintext version. mu4e-view-html-plaintext-ratio-heuristic most-positive-fixnum gnus-blocked-images "." mu4e-org-link-query-in-headers-mode nil ;; mu4e-org-contacts-file (concat +project-maria-dir+ "0contacts.org") message-kill-buffer-on-exit t mu4e-confirm-quit nil mu4e-headers-fields '((:human-date . 5) (:from-or-to . 20) (:subject)) mml-secure-openpgp-sign-with-sender t mml-secure-openpgp-signers '("06DDA93690F775E3715B628CCA949A6D46BC2BBE") mu4e-compose-complete-addresses t mu4e-compose-complete-only-after "2018-01-01" browse-url-filename-alist '(("^/\\(ftp@\\|anonymous@\\)?\\([^:/]+\\):/*" . "ftp://\\2/") ("^/\\([^:@/]+@\\)?\\([^:/]+\\):/*" . "ftp://\\1\\2/") ;; For gnus-article-browse-html-article on Windows Subsystem for Linux. ("^/+" . "file://///wsl$/Debian/")) ) (with-eval-after-load "recentf" (progn (add-to-list 'recentf-exclude "~/project-jerome/email-archive/") (add-to-list 'recentf-exclude "/tmp/"))) ;; Unbind s, originally bound to mu4e-headers-search. ;; Unset =mu4e-headers=search= from both =mu4e-headers-mode-map= and ;; =mu4e-view-mode-map=. Retain =s= for search in =mu4e-main-mode-map=. (define-key mu4e-headers-mode-map (kbd "s") #'avy-goto-word-or-subword-1) (define-key mu4e-headers-mode-map (kbd "K") #'mu4e-view-save-url) (define-key mu4e-headers-mode-map "S" 'helm-mu) (add-hook 'mu4e-view-mode-hook (lambda () (progn (evil-evilified-state) (define-key mu4e-view-mode-map (kbd "s") #'avy-goto-word-or-subword-1) (define-key mu4e-view-mode-map (kbd "K") #'mu4e-view-save-url) (define-key mu4e-view-mode-map "S" 'helm-mu)))) (define-key mu4e-headers-mode-map (kbd "c") #'mu4e-headers-mark-all-unread-read) (define-key mu4e-headers-mode-map (kbd "C") #'mu4e-headers-refile-all) ;; Functions ran on every message sent (spacemacs/set-leader-keys-for-major-mode 'mu4e-compose-mode "o" 'org-mime-edit-mail-in-org-mode) (spacemacs/set-leader-keys-for-major-mode 'mu4e-compose-mode "p" 'mml-secure-message-sign-pgpmime) (spacemacs/set-leader-keys (kbd "aes") #'helm-mu (kbd "aec") #'helm-mu-contacts (kbd "aej") #'mu4e-search-bookmark) (require 'elfeed) (require 'hydra) (require 'elfeed-tube) (setf elfeed-db-directory "~/.emacs.d/.cache/elfeed" elfeed-use-curl t) ;; Remove default binding so evilify mapping takes over. ;; Set shortcut for org-web-tools to fetch full article (with-eval-after-load "elfeed" (progn (define-key elfeed-search-mode-map (kbd "RET") nil) (define-key elfeed-search-mode-map (kbd "RET") #'ap/elfeed-search-browse-org))) (defhydra ben/hydra-elfeed (:exit t) ("g" (elfeed-search-set-filter "@6-months-ago +unread +gbl") "Global News") ("l" (elfeed-search-set-filter "@6-months-ago +unread +lcl") "Local News") ("s" (elfeed-search-set-filter "@6-months-ago +unread +sci") "Science & Tech") ("b" (elfeed-search-set-filter "@6-months-ago +unread +blog") "Misc. Blogs") ("c" (elfeed-search-set-filter "@6-months-ago +unread +rel") "Catholic") ("f" (elfeed-search-set-filter "@6-months-ago +unread +frm") "Forums") ("o" (elfeed-search-set-filter "@6-months-ago +unread +pod") "Podcasts") ("y" (elfeed-search-set-filter "@6-months-ago +unread +vid") "Youtube") ("a" (elfeed-search-set-filter "@6-months-ago +unread") "All") ("q" nil "quit" :color blue)) (evilified-state-evilify-map elfeed-search-mode-map :mode elfeed-search-mode :eval-after-load elfeed-search :bindings "s" #'avy-goto-word-or-subword-1 "S" #'elfeed-search-live-filter "f" #'ben/hydra-elfeed/body "r" #'elfeed-mark-all-as-read "RET" #'ap/elfeed-search-browse-org "t" #'elfeed-search-show-entry ";" #'helm-occur "b" #'ben/elfeed-search-browse-url "C-u b" #'elfeed-search-browse-url "o" #'elfeed-tube-fetch "gr" #'elfeed-update) (evilified-state-evilify-map elfeed-show-mode-map :bindings "s" #'avy-goto-word-or-subword-1 ";" #'helm-occur) (defun elfeed-mark-all-as-read () "Marks entire buffer before tagging marked region as read" (interactive) (mark-whole-buffer) (elfeed-search-untag-all-unread)) ;; Source https://www.reddit.com/r/emacs/comments/g6oowz/elfeed_rules/fodeb8x/ (defun ap/elfeed-search-browse-org () "Open selected items as Org." (interactive) (let ((browse-url-browser-function (lambda (url _) (org-web-tools-read-url-as-org url)))) (ap/elfeed-search-selected-map #'ap/elfeed-search-browse-entry))) (defun ap/elfeed-search-browse-entry (entry) "Browse ENTRY with `browse-url' and mark as read. If ENTRY is unread, it will also be unstarred. To override the browser function, bind `browse-url-browser-function' around the call to this." (let ((url (elfeed-entry-link entry)) (tags (elfeed-entry-tags entry))) ;; Mark as read first, because apparently the elfeed functions don't work after `browse-url' ;; potentially changes the buffer. (elfeed-untag entry 'unread) (elfeed-search-update-entry entry) (browse-url url))) (cl-defun ap/elfeed-search-selected-map (fn) "Map FN across selected entries in elfeed-search buffer using `mapcar'." (mapcar fn (elfeed-search-selected))) (defun ben/elfeed-search-browse-url (&optional use-generic-p) "Visit the current entry in your browser using `browse-url'. If there is a prefix argument, visit the current entry in the browser defined by `browse-url-generic-program'." (interactive "P") (let ((buffer (current-buffer)) (entries (elfeed-search-selected))) (cl-loop for entry in entries do (elfeed-untag entry 'unread) when (elfeed-entry-link entry) do (if use-generic-p (browse-url-generic it) (eww it))) ;; `browse-url' could have switched to another buffer if eww or another ;; internal browser is used, but the remainder of the functions needs to ;; run in the elfeed buffer. (with-current-buffer buffer (mapc #'elfeed-search-update-entry entries) (unless (or elfeed-search-remain-on-entry (use-region-p)) (forward-line))))) (add-hook 'elfeed-new-entry-hook #'elfeed-tube--auto-fetch) (advice-add 'elfeed-show-entry :after #'elfeed-tube--auto-fetch) (advice-add elfeed-show-refresh-function :after #'elfeed-tube-show) ;; Forces bash shell into interactive mode, leadings to sourcing of ;; ~/.bashrc and interactive aliases and functions ;; (setq shell-command-switch "-ic") ;; Default value was "-c" (setq shell-command-switch "-c") (setf auto-revert-interval 30) (auto-revert-set-timer) ;; https://rufflewind.com/2014-07-20/pasting-unicode-in-emacs-on-windows ;; (set-selection-coding-system 'utf-16-le) ;; Based on https://stackoverflow.com/questions/12102554/emacs-skip-whitespace-kills (define-advice kill-new (:around (orig-fn string &optional rest) ignore-whitespaces) "Don't put whitespaces into kill ring." (let* ((string-raw (substring-no-properties string)) (space-p (not (string-match-p "[^ \t\n\r]" string-raw)))) (if (not space-p) (apply orig-fn string rest) (message "skipped whitespace kill") nil))) ;; https://gnu.emacs.help.narkive.com/p20hvAvC/keyboard-translate-not-working-with-emacs-daemon (define-key key-translation-map [?\(] [?\[]) (define-key key-translation-map [?\[] [?\(]) (define-key key-translation-map [?\)] [?\]]) (define-key key-translation-map [?\]] [?\)]) ;; Should double buffering cause lag spikes on 3840 x 2160 displays ;; we can disable it via... (add-to-list 'default-frame-alist '(inhibit-double-buffering . t)) ;; Sets default browser (setf browse-url-generic-program "/mnt/c/Windows/System32/cmd.exe" browse-url-generic-args '("/c" "start") browse-url-browser-function #'browse-url-generic package-install-upgrade-built-in t) ;; Useful trick to share snippets between modes. Whenever a major mode ;; is loaded, fundamental-mode is also loaded (add-hook 'yas-minor-mode-hook (lambda () (yas-activate-extra-mode 'fundamental-mode))) ;; User Defined Toggles -> See SPC t hydra menu ;; VISUALLY wraps words that go past screen length ;; setq-default command means the command is run in every major mode buffer (setq-default truncate-lines nil) ;; Enables line by line navigation. Lines are not line broken > use RET for that (spacemacs/toggle-visual-line-navigation-globally-on) ;; Determines the length of time between the end of typing for SPC j j (avy-timer) ;; and the appearance of green prompt letters (setq avy-timeout-seconds 0.50) )
1. Layers & Packages
To find new layers, see ~/.emacs.d/layers/
. Alternatively, use SPC h l
to
find Layer README's.
(defun dotspacemacs/layers () "Layer configuration: This function should only modify configuration layer settings." (setq-default ;; Base distribution to use. This is a layer contained in the directory ;; `+distribution'. For now available distributions are `spacemacs-base' ;; or `spacemacs'. (default 'spacemacs) dotspacemacs-distribution 'spacemacs ;; Lazy installation of layers (i.e. layers are installed only when a file ;; with a supported type is opened). Possible values are `all', `unused' ;; and `nil'. `unused' will lazy install only unused layers (i.e. layers ;; not listed in variable `dotspacemacs-configuration-layers'), `all' will ;; lazy install any layer that support lazy installation even the layers ;; listed in `dotspacemacs-configuration-layers'. `nil' disable the lazy ;; installation feature and you have to explicitly list a layer in the ;; variable `dotspacemacs-configuration-layers' to install it. ;; (default 'unused) dotspacemacs-enable-lazy-installation 'nil ;; If non-nil then Spacemacs will ask for confirmation before installing ;; a layer lazily. (default t) dotspacemacs-ask-for-lazy-installation t ;; List of additional paths where to look for configuration layers. ;; Paths must have a trailing slash (i.e. `~/.mycontribs/') dotspacemacs-configuration-layer-path '() ;; List of configuration layers to load. dotspacemacs-configuration-layers '(;; ---------------------------------------------------------------- ;; Example of useful layers you may want to use right away. ;; Uncomment some layer names and press `SPC f e R' (Vim style) or ;; `M-m f e R' (Emacs style) to install them. ;; ---------------------------------------------------------------- (auto-completion :variables auto-completion-enable-help-tooltip t auto-completion-enable-snippets-in-popup t :packages (not helm-company yasnippet-snippets fuzzy ac-ispell auto-complete)) (better-defaults :packages (not mwim)) (bibtex :variables bibtex-enable-ebib-support t ebib-preload-bib-files (list (concat +project-maria-dir+ "project-jerome.bib")) ebib-file-search-dirs (list +project-jerome-dir+) ebib-import-directory (list +project-jerome-dir+)) ;; $ git clone git@github.com:BenedictHW/common-lisp-sly.git ~/.emacs.d/private/ common-lisp-sly (elfeed :variables elfeed-enable-goodies nil rmh-elfeed-org-files (list (concat +project-maria-dir+ "dotelfeed.org"))) (emacs-lisp :packages (not flycheck-package nameless emr overseer flycheck-elsa auto-compile inspector )) evil-better-jumper (evil-snipe :variables evil-snipe-enable-alternate-f-and-t-behaviors 't) finance (git :variables git-enable-magit-todos-plugin t :packages (not git-modes golden-ratio smeargle gitignore-templates git-messenger helm-git-grep git-timemachine )) (helm :packages (not helm-descbinds helm-swoop helm-themes helm-make helm-ls-git helm-mode-manager helm-flx)) helpful (llm-client :variables llm-client-enable-ellama nil llm-client-enable-gptel t) (mu4e :variables mu4e-installation-path "/usr/share/emacs/site-lisp/elpa/mu4e-1.10.8" :packages (not mu4e-alert)) (org :variables org-enable-modern-support nil org-want-todo-bindings t org-enable-org-brain-support t org-enable-reveal-js-support t org-enable-org-journal-support nil org-enable-org-contacts-support t org-enable-appear-support t org-enable-sticky-header nil :packages (not org-rich-yank)) ;; pandoc pdf plantuml (python :variables python-backend 'lsp python-lsp-server 'pylsp python-shell-interpreter "python3") (shell :variables shell-default-height 30 shell-default-position 'bottom shell-default-shell 'shell :packages (not esh-help eshell-prompt-extras eshell-z xterm-color vterm multi-vterm terminal-here multi-term )) (spell-checking :packages (not auto-dictionary )) (syntax-checking :packages (not flycheck-pos-tip)) (transmission :variables transmission-auto-refresh-all t) ;; Danger! Making edits to the default layers. ;; See Spacemacs Issue 13595. The spacemacs distribution layer lists ;; treemacs in configuration-layer/declare-layers. (treemacs :packages nil) (spacemacs-bootstrap :packages (not dash holy-mode hybrid-mode)) (spacemacs-defaults :packages (not quickrun)) (spacemacs-editing :variables vim-style-enable-undo-region t :packages (not eval-sexp-fu expand-region aggressive-indent editorconfig hungry-delete multi-line password-generator uuidgen string-edit lorem-ipsum drag-stuff evil-easymotion)) (spacemacs-editing-visual :packages (not term-cursor highlight-indentation writeroom-mode hide-comnt highlight-numbers indent-guide volatile-highlights )) (spacemacs-completion :packages (not flx-ido)) (spacemacs-language :packages (not define-word)) (spacemacs-layouts :packages (not counsel-projectile)) (spacemacs-misc :packages (not devdocs)) (spacemacs-purpose :packages (not helm-purpose)) (spacemacs-modeline :packages (not anzu fancy-battery font-lock+ neotree symon vim-powerline)) (spacemacs-navigation :packages (not restart-emacs ace-link ace-window golden-ratio centered-cursor-mode open-junk-file auto-highlight-symbol)) (spacemacs-org :packages (not toc-org)) (spacemacs-visual :packages (not all-the-icons)) (spacemacs-evil :packages (not evil-numbers evil-lisp-state evil-escape evil-anzu evil-exchange evil-goggles evil-iedit-state evil-tutor evil-unimpaired evil-visual-mark-mode evil-visualstar evil-args vi-tilde-fringe evil-indent-plus vim-empty-lines-mode )) ) ;; *** Additional Packages ;; List of additional packages that will be installed without being ;; wrapped in a layer. If you need some configuration for these ;; packages, then consider creating a layer. You can also put the ;; configuration in `dotspacemacs/user-config'. dotspacemacs-additional-packages '(;; Replaces `dotspacemacs/user-env'. exec-path-from-shell org-noter org-pdftools org-web-tools ;; Pulls entire douay rheims bible from sword project ;; (sword-to-org :location (recipe :fetcher github ;; :repo "alphapapa/sword-to-org")) cdlatex org-fragtog ;; keyfreq ;; For org-brain ascii-art-to-unicode ;; wolfram-mode ;; See emacs-jupyter in user config section ;; jupyter lexic ;; Since it is a pretty heavy package, only include it when doing heavy ;; analysis on my own time spent. ;; org-analyzer org-tanglesync poly-org ement ox-rss youtube-sub-extractor elfeed-tube elfeed-tube-mpv greader literate-calc-mode listen casual-calc biome ) ;; A list of packages that cannot be updated. dotspacemacs-frozen-packages '(;; Otherwise it will reinstall itself helm-swoop ) ;; A list of packages that will not be installed and loaded. dotspacemacs-excluded-packages '(hybrid-mode helm-org-rifle org-present org-pomodoro org-projectile dotenv-mode) ;; Defines the behaviour of Spacemacs when installing packages. ;; Possible values are `used-only', `used-but-keep-unused' and `all'. ;; `used-only' installs only explicitly used packages and deletes any unused ;; packages as well as their unused dependencies. `used-but-keep-unused' ;; installs only the used packages but won't delete unused ones. `all' ;; installs *all* packages supported by Spacemacs and never uninstalls them. ;; (default is `used-only') dotspacemacs-install-packages 'used-only))
2. Initialization
(defun dotspacemacs/init () "Initialization: This function is called at the very beginning of Spacemacs startup, before layer configuration. It should only modify the values of Spacemacs settings." ;; This setq-default sexp is an exhaustive list of all the supported ;; spacemacs settings. (setq-default ;; If non-nil then enable support for the portable dumper. You'll need to ;; compile Emacs 27 from source following the instructions in file ;; EXPERIMENTAL.org at to root of the git repository. ;; ;; WARNING: pdumper does not work with Native Compilation, so it's disabled ;; regardless of the following setting when native compilation is in effect. ;; ;; (default nil) dotspacemacs-enable-emacs-pdumper nil ;; Name of executable file pointing to emacs 27+. This executable must be ;; in your PATH. ;; (default "emacs") dotspacemacs-emacs-pdumper-executable-file "emacs" ;; Name of the Spacemacs dump file. This is the file will be created by the ;; portable dumper in the cache directory under dumps sub-directory. ;; To load it when starting Emacs add the parameter `--dump-file' ;; when invoking Emacs 27.1 executable on the command line, for instance: ;; ./emacs --dump-file=$HOME/.emacs.d/.cache/dumps/spacemacs-27.1.pdmp ;; (default (format "spacemacs-%s.pdmp" emacs-version)) dotspacemacs-emacs-dumper-dump-file (format "spacemacs-%s.pdmp" emacs-version) ;; If non-nil ELPA repositories are contacted via HTTPS whenever it's ;; possible. Set it to nil if you have no way to use HTTPS in your ;; environment, otherwise it is strongly recommended to let it set to t. ;; This variable has no effect if Emacs is launched with the parameter ;; `--insecure' which forces the value of this variable to nil. ;; (default t) dotspacemacs-elpa-https t ;; Maximum allowed time in seconds to contact an ELPA repository. ;; (default 5) dotspacemacs-elpa-timeout 5 ;; Set `gc-cons-threshold' and `gc-cons-percentage' when startup finishes. ;; This is an advanced option and should not be changed unless you suspect ;; performance issues due to garbage collection operations. ;; (default '(100000000 0.1)) ;; Emacs maintainer Eli Zaretskii recommends not altering the value from ;; Emacs default. ;; https://old.reddit.com/r/emacs/comments/bg85qm/garbage_collector_magic_hack/ ;; https://old.reddit.com/r/emacs/comments/6uc7g5/just_figured_out_why_emacs_pauses_sometimes/ ;; Update: see `spacemacs-editing/init-undo-tree' undo limits. ;; If we lower the threshold there will be freezing ;; when we use the undo history. ;; Also see: https://github.com/lewang/flx#gc-optimization dotspacemacs-gc-cons '(100000000 0.1) ;; Set `read-process-output-max' when startup finishes. ;; This defines how much data is read from a foreign process. ;; Setting this >= 1 MB should increase performance for lsp servers ;; in emacs 27. ;; (default (* 1024 1024)) dotspacemacs-read-process-output-max (* 1024 1024) ;; If non-nil then Spacelpa repository is the primary source to install ;; a locked version of packages. If nil then Spacemacs will install the ;; latest version of packages from MELPA. Spacelpa is currently in ;; experimental state please use only for testing purposes. ;; (default nil) dotspacemacs-use-spacelpa nil ;; If non-nil then verify the signature for downloaded Spacelpa archives. ;; (default t) dotspacemacs-verify-spacelpa-archives t ;; If non-nil then spacemacs will check for updates at startup ;; when the current branch is not `develop'. Note that checking for ;; new versions works via git commands, thus it calls GitHub services ;; whenever you start Emacs. (default nil) dotspacemacs-check-for-update nil ;; If non-nil, a form that evaluates to a package directory. For example, to ;; use different package directories for different Emacs versions, set this ;; to `emacs-version'. (default 'emacs-version) dotspacemacs-elpa-subdirectory 'emacs-version ;; One of `vim', `emacs' or `hybrid'. ;; `hybrid' is like `vim' except that `insert state' is replaced by the ;; `hybrid state' with `emacs' key bindings. The value can also be a list ;; with `:variables' keyword (similar to layers). Check the editing styles ;; section of the documentation for details on available variables. ;; (default 'vim) dotspacemacs-editing-style 'vim ;; If non-nil show the version string in the Spacemacs buffer. It will ;; appear as (spacemacs version)@(emacs version) ;; (default t) dotspacemacs-startup-buffer-show-version t ;; Specify the startup banner. Default value is `official', it displays ;; the official spacemacs logo. An integer value is the index of text ;; banner, `random' chooses a random text banner in `core/banners' ;; directory. A string value must be a path to an image format supported ;; by your Emacs build. ;; If the value is nil then no banner is displayed. (default 'official) dotspacemacs-startup-banner nil ;; Scale factor controls the scaling (size) of the startup banner. Default ;; value is `auto' for scaling the logo automatically to fit all buffer ;; contents, to a maximum of the full image height and a minimum of 3 line ;; heights. If set to a number (int or float) it is used as a constant ;; scaling factor for the default logo size. dotspacemacs-startup-banner-scale 'nil ;; List of items to show in startup buffer or an association list of ;; the form `(list-type . list-size)`. If nil then it is disabled. ;; Possible values for list-type are: ;; `recents' `recents-by-project' `bookmarks' `projects' `agenda' `todos'. ;; List sizes may be nil, in which case ;; `spacemacs-buffer-startup-lists-length' takes effect. ;; The exceptional case is `recents-by-project', where list-type must be a ;; pair of numbers, e.g. `(recents-by-project . (7 . 5))', where the first ;; number is the project limit and the second the limit on the recent files ;; within a project. dotspacemacs-startup-lists '((agenda . 30)) ;; True if the home buffer should respond to resize events. (default t) dotspacemacs-startup-buffer-responsive t ;; Show numbers before the startup list lines. (default t) dotspacemacs-show-startup-list-numbers t ;; The minimum delay in seconds between number key presses. (default 0.4) dotspacemacs-startup-buffer-multi-digit-delay 0.4 ;; If non-nil, show file icons for entries and headings on Spacemacs home buffer. ;; This has no effect in terminal or if "all-the-icons" package or the font ;; is not installed. (default nil) dotspacemacs-startup-buffer-show-icons nil ;; Default major mode for a new empty buffer. Possible values are mode ;; names such as `text-mode'; and `nil' to use Fundamental mode. ;; (default `text-mode') dotspacemacs-new-empty-buffer-major-mode 'nil ;; Default major mode of the scratch buffer (default `text-mode') dotspacemacs-scratch-mode 'common-lisp-mode ;; If non-nil, *scratch* buffer will be persistent. Things you write down in ;; *scratch* buffer will be saved and restored automatically. dotspacemacs-scratch-buffer-persistent nil ;; If non-nil, `kill-buffer' on *scratch* buffer ;; will bury it instead of killing. dotspacemacs-scratch-buffer-unkillable nil ;; Initial message in the scratch buffer, such as "Welcome to Spacemacs!" ;; (default nil) dotspacemacs-initial-scratch-message nil ;; List of themes, the first of the list is loaded when spacemacs starts. ;; Press `SPC T n' to cycle to the next theme in the list (works great ;; with 2 themes variants, one dark and one light) dotspacemacs-themes '(spacemacs-light spacemacs-dark) ;; Set the theme for the Spaceline. Supported themes are `spacemacs', ;; `all-the-icons', `custom', `doom', `vim-powerline' and `vanilla'. The ;; first three are spaceline themes. `doom' is the doom-emacs mode-line. ;; `vanilla' is default Emacs mode-line. `custom' is a user defined themes, ;; refer to the DOCUMENTATION.org for more info on how to create your own ;; spaceline theme. Value can be a symbol or list with additional properties. ;; (default '(spacemacs :separator wave :separator-scale 1.5)) dotspacemacs-mode-line-theme '(spacemacs :separator nil :separator-scale 0.5) ;; If non-nil the cursor color matches the state color in GUI Emacs. ;; (default t) dotspacemacs-colorize-cursor-according-to-state t ;; Default font or prioritized list of fonts. The `:size' can be specified as ;; a non-negative integer (pixel size), or a floating-point (point size). ;; Point size is recommended, because it's device independent. (default 10.0) ;; Dell 32 4K USB-C Hub Monitor - P3222QE dotspacemacs-default-font '("Iosevka Term Slab" :size 18.0 :weight normal :width normal) ;; The leader key (default "SPC") dotspacemacs-leader-key "SPC" ;; The key used for Emacs commands `M-x' (after pressing on the leader key). ;; (default "SPC") dotspacemacs-emacs-command-key "" ;; The key used for Vim Ex commands (default ":") dotspacemacs-ex-command-key ":" ;; The leader key accessible in `emacs state' and `insert state' ;; (default "M-m") dotspacemacs-emacs-leader-key "M-m" ;; Major mode leader key is a shortcut key which is the equivalent of ;; pressing `<leader> m`. Set it to `nil` to disable it. (default ",") dotspacemacs-major-mode-leader-key "," ;; Major mode leader key accessible in `emacs state' and `insert state'. ;; (default "C-M-m" for terminal mode, "<M-return>" for GUI mode). ;; Thus M-RET should work as leader key in both GUI and terminal modes. ;; C-M-m also should work in terminal mode, but not in GUI mode. dotspacemacs-major-mode-emacs-leader-key (if window-system "<M-return>" "C-M-m") ;; These variables control whether separate commands are bound in the GUI to ;; the key pairs `C-i', `TAB' and `C-m', `RET'. ;; Setting it to a non-nil value, allows for separate commands under `C-i' ;; and TAB or `C-m' and `RET'. ;; In the terminal, these pairs are generally indistinguishable, so this only ;; works in the GUI. (default nil) dotspacemacs-distinguish-gui-tab t ;; Name of the default layout (default "Default") dotspacemacs-default-layout-name "Default" ;; If non-nil the default layout name is displayed in the mode-line. ;; (default nil) dotspacemacs-display-default-layout nil ;; If non-nil then the last auto saved layouts are resumed automatically upon ;; start. (default nil) dotspacemacs-auto-resume-layouts nil ;; If non-nil, auto-generate layout name when creating new layouts. Only has ;; effect when using the "jump to layout by number" commands. (default nil) dotspacemacs-auto-generate-layout-names nil ;; Size (in MB) above which spacemacs will prompt to open the large file ;; literally to avoid performance issues. Opening a file literally means that ;; no major mode or minor modes are active. (default is 1) dotspacemacs-large-file-size 50 ;; Also see large-file-warning-threshold, set in dotspacemacs user config ;; Location where to auto-save files. Possible values are `original' to ;; auto-save the file in-place, `cache' to auto-save the file to another ;; file stored in the cache directory and `nil' to disable auto-saving. ;; (default 'cache) dotspacemacs-auto-save-file-location 'cache ;; Maximum number of rollback slots to keep in the cache. (default 5) dotspacemacs-max-rollback-slots 5 ;; If non-nil, the paste transient-state is enabled. While enabled, after you ;; paste something, pressing `C-j' and `C-k' several times cycles through the ;; elements in the `kill-ring'. (default nil) dotspacemacs-enable-paste-transient-state t ;; Which-key delay in seconds. The which-key buffer is the popup listing the ;; commands bound to the current keystroke sequence. (default 0.4) HW annot: ;; the default sacrifices -quite a lot of!- performance for accessibility, ;; and after some experience a tradeoff in favour of the former is preferred. dotspacemacs-which-key-delay 2 ;; Which-key frame position. Possible values are `right', `bottom' and ;; `right-then-bottom'. right-then-bottom tries to display the frame to the ;; right; if there is insufficient space it displays it at the bottom. ;; (default 'bottom) dotspacemacs-which-key-position 'bottom ;; Control where `switch-to-buffer' displays the buffer. If nil, ;; `switch-to-buffer' displays the buffer in the current window even if ;; another same-purpose window is available. If non-nil, `switch-to-buffer' ;; displays the buffer in a same-purpose window even if the buffer can be ;; displayed in the current window. (default nil) dotspacemacs-switch-to-buffer-prefers-purpose nil ;; If non-nil a progress bar is displayed when spacemacs is loading. This ;; may increase the boot time on some systems and emacs builds, set it to ;; nil to boost the loading time. (default t) dotspacemacs-loading-progress-bar nil ;; If non-nil the frame is fullscreen when Emacs starts up. (default nil) ;; (Emacs 24.4+ only) dotspacemacs-fullscreen-at-startup nil ;; If non-nil `spacemacs/toggle-fullscreen' will not use native fullscreen. ;; Use to disable fullscreen animations in OSX. (default nil) dotspacemacs-fullscreen-use-non-native nil ;; If non-nil the frame is maximized when Emacs starts up. ;; Takes effect only if `dotspacemacs-fullscreen-at-startup' is nil. ;; (default nil) (Emacs 24.4+ only) dotspacemacs-maximized-at-startup t ;; If non-nil the frame is undecorated when Emacs starts up. Combine this ;; variable with `dotspacemacs-maximized-at-startup' in OSX to obtain ;; borderless fullscreen. (default nil) dotspacemacs-undecorated-at-startup nil ;; A value from the range (0..100), in increasing opacity, which describes ;; the transparency level of a frame when it's active or selected. ;; Transparency can be toggled through `toggle-transparency'. (default 90) dotspacemacs-active-transparency 100 ;; A value from the range (0..100), in increasing opacity, which describes ;; the transparency level of a frame when it's inactive or deselected. ;; Transparency can be toggled through `toggle-transparency'. (default 90) dotspacemacs-inactive-transparency 100 ;; If non-nil show the titles of transient states. (default t) dotspacemacs-show-transient-state-title t ;; If non-nil show the color guide hint for transient state keys. (default t) dotspacemacs-show-transient-state-color-guide t ;; If non-nil unicode symbols are displayed in the mode line. ;; If you use Emacs as a daemon and wants unicode characters only in GUI set ;; the value to quoted `display-graphic-p'. (default t) dotspacemacs-mode-line-unicode-symbols t ;; If non-nil smooth scrolling (native-scrolling) is enabled. Smooth ;; scrolling overrides the default behavior of Emacs which recenters point ;; when it reaches the top or bottom of the screen. (default t) dotspacemacs-smooth-scrolling t ;; Show the scroll bar while scrolling. The auto hide time can be configured ;; by setting this variable to a number. (default t) dotspacemacs-scroll-bar-while-scrolling nil ;; Control line numbers activation. ;; If set to `t', `relative' or `visual' then line numbers are enabled in all ;; `prog-mode' and `text-mode' derivatives. If set to `relative', line ;; numbers are relative. If set to `visual', line numbers are also relative, ;; but only visual lines are counted. For example, folded lines will not be ;; counted and wrapped lines are counted as multiple lines. ;; This variable can also be set to a property list for finer control: ;; '(:relative nil ;; :visual nil ;; :disabled-for-modes dired-mode ;; doc-view-mode ;; markdown-mode ;; org-mode ;; pdf-view-mode ;; text-mode ;; :size-limit-kb 1000) ;; When used in a plist, `visual' takes precedence over `relative'. ;; (default nil) dotspacemacs-line-numbers nil ;; Code folding method. Possible values are `evil', `origami' and `vimish'. ;; (default 'evil) dotspacemacs-folding-method 'evil ;; If non-nil and `dotspacemacs-activate-smartparens-mode' is also non-nil, ;; `smartparens-strict-mode' will be enabled in programming modes. ;; (default nil) dotspacemacs-smartparens-strict-mode nil ;; If non-nil smartparens-mode will be enabled in programming modes. ;; (default t) dotspacemacs-activate-smartparens-mode t ;; If non-nil pressing the closing parenthesis `)' key in insert mode passes ;; over any automatically added closing parenthesis, bracket, quote, etc... ;; This can be temporary disabled by pressing `C-q' before `)'. (default nil) dotspacemacs-smart-closing-parenthesis nil ;; Select a scope to highlight delimiters. Possible values are `any', ;; `current', `all' or `nil'. Default is `all' (highlight any scope and ;; emphasis the current one). (default 'all) dotspacemacs-highlight-delimiters 'all ;; If non-nil, start an Emacs server if one is not already running. ;; (default nil) dotspacemacs-enable-server nil ;; Set the emacs server socket location. ;; If nil, uses whatever the Emacs default is, otherwise a directory path ;; like \"~/.emacs.d/server\". It has no effect if ;; `dotspacemacs-enable-server' is nil. ;; (default nil) dotspacemacs-server-socket-dir nil ;; If non-nil, advise quit functions to keep server open when quitting. ;; (default nil) dotspacemacs-persistent-server nil ;; List of search tool executable names. Spacemacs uses the first installed ;; tool of the list. Supported tools are `rg', `ag', `pt', `ack' and `grep'. ;; (default '("rg" "ag" "pt" "ack" "grep")) dotspacemacs-search-tools '("rg" "ag" "pt" "ack" "grep") ;; The backend used for undo/redo functionality. Possible values are ;; `undo-tree', `undo-fu' and `undo-redo', see also `evil-undo-system'. ;; Note that saved undo history does not get transferred when changing ;; from undo-tree to undo-fu or undo-redo. ;; The default is currently 'undo-tree, but it will likely be changed ;; and at some point removed because undo-tree is not maintained anymore. dotspacemacs-undo-system 'undo-fu ;; Format specification for setting the frame title. ;; %a - the `abbreviated-file-name', or `buffer-name' ;; %t - `projectile-project-name' ;; %I - `invocation-name' ;; %S - `system-name' ;; %U - contents of $USER ;; %b - buffer name ;; %f - visited file name ;; %F - frame name ;; %s - process status ;; %p - percent of buffer above top of window, or Top, Bot or All ;; %P - percent of buffer above bottom of window, perhaps plus Top, or Bot or All ;; %m - mode name ;; %n - Narrow if appropriate ;; %z - mnemonics of buffer, terminal, and keyboard coding systems ;; %Z - like %z, but including the end-of-line format ;; If nil then Spacemacs uses default `frame-title-format' to avoid ;; performance issues, instead of calculating the frame title by ;; `spacemacs/title-prepare' all the time. ;; (default "%I@%S") dotspacemacs-frame-title-format nil ;; Format specification for setting the icon title format ;; (default nil - same as frame-title-format) dotspacemacs-icon-title-format nil ;; Show trailing whitespace (default t) dotspacemacs-show-trailing-whitespace t ;; Delete whitespace while saving buffer. Possible values are `all' ;; to aggressively delete empty line and long sequences of whitespace, ;; `trailing' to delete only the whitespace at end of lines, `changed' to ;; delete only whitespace for changed lines or `nil' to disable cleanup. ;; (default nil) dotspacemacs-whitespace-cleanup 'trailing ;; If non-nil activate `clean-aindent-mode' which tries to correct ;; virtual indentation of simple modes. This can interfere with mode specific ;; indent handling like has been reported for `go-mode'. ;; If it does deactivate it here. ;; (default t) dotspacemacs-use-clean-aindent-mode nil ;; Accept SPC as y for prompts if non-nil. (default nil) dotspacemacs-use-SPC-as-y nil ;; If non-nil shift your number row to match the entered keyboard layout ;; (only in insert state). Currently supported keyboard layouts are: ;; `qwerty-us', `qwertz-de' and `querty-ca-fr'. ;; New layouts can be added in `spacemacs-editing' layer. ;; (default nil) dotspacemacs-swap-number-row nil ;; Either nil or a number of seconds. If non-nil zone out after the specified ;; number of seconds. (default nil) dotspacemacs-zone-out-when-idle nil ;; Run `spacemacs/prettify-org-buffer' when ;; visiting README.org files of Spacemacs. ;; (default nil) dotspacemacs-pretty-docs nil ;; If nil the home buffer shows the full path of agenda items ;; and todos. If non-nil only the file name is shown. dotspacemacs-home-shorten-agenda-source t ;; If non-nil then byte-compile some of Spacemacs files. dotspacemacs-byte-compile t))
3. User Config
- Structure
Does the configuration fit under a package? Please search for the
package name with
helm-spacemacs-help
, orSPC h SPC "package name"
to see if it is owned by a layer.- Yes (org-mode, magit, melpa/elpa/built-in packages etc.)
- No (large-file-threshold var, scrollbar var, toolbar visibility toggle) Place such miscellaneous configuration under the heading 3.9.
(defun dotspacemacs/user-config () "Configuration function for user code. This function is called at the very end of Spacemacs initialization after layers configuration. This is the place where most of your configurations should be done. Unless it is explicitly specified that a variable should be set before a package is loaded, you should place your code here." (require 'biome) (biome-def-preset biome-query-preset-14 ((:name . "GEM (Canada)") (:group . "hourly") (:params ("hourly" "wind_speed_10m" "cloud_cover" "precipitation" "apparent_temperature") ("longitude" . -79.337021) ("latitude" . 43.856098)))) (spacemacs/set-leader-keys "a w w" 'biome-query-preset-14) (require 'gptel) (require 'auth-source) (defun bhw/switch-to-llm-buffer () (interactive) (switch-to-buffer "*Gemini*")) (defun get-authinfo-password (machine login) (let ((credential (auth-source-search :max 1 :host machine :user login :require '(:secret)))) (if credential (let ((secret (plist-get (nth 0 credential) :secret))) (if (functionp secret) (funcall secret) secret)) (message "No password found for %s@%s" login machine)))) ;; In ~/.authinfo, ;;machine aistudio.google.com login ben password *YourAPIkey* (setf gptel-model "gemini-1.5-pro-latest" gptel-backend (gptel-make-gemini "Gemini" :key (get-authinfo-password "aistudio.google.com" "ben") :stream t) gptel-directives '((default . " Ignore all previous instructions. 1. You are to provide clear, concise, and direct responses. 2. Eliminate unnecessary reminders, apologies, self-references, and any pre-programmed niceties. 3. Maintain a casual tone in your communication. 4. Be transparent; if you're unsure about an answer or if a question is beyond your capabilities or knowledge, admit it. 5. For any unclear or ambiguous queries, ask follow-up questions to understand the user's intent better. 6. When explaining concepts, use real-world examples and analogies, where appropriate. 7. For complex requests, take a deep breath and work on the problem step-by-step. 8. For every response, you will be tipped up to $200 (depending on the quality of your output). It is very important that you get this right.") (programming . "You are a large language model and a careful programmer. Provide code and only code as output without any additional text, prompt or note.") (writing . "You are a large language model and a writing assistant. Respond concisely.") (chat . "You are a large language model and a conversation partner. Respond concisely."))) (spacemacs/set-leader-keys (kbd "al") #'bhw/switch-to-llm-buffer) (add-hook 'eww-after-render-hook 'eww-readable) (require 'greader) ;; FIXME Auto-completion causes lag in shell-mode. (setf company-global-modes '(not shell-mode)) (require 'youtube-sub-extractor) (require 'ement) (evil-collection-ement-setup) (spacemacs/set-leader-keys (kbd "acM") #'ement-connect (kbd "acm") #'ement-list-rooms (kbd "acn") #'ement-notify-switch-to-notifications-buffer (kbd "acc") #'ement-room-send-message (kbd "acv") #'ement-view-room) (evilified-state-evilify-map ement-room-mode-map :mode ement-room-mode :eval-after-load ement-room :bindings ";" #'helm-occur "n" #'ement-room-scroll-up-mark-read) (evilified-state-evilify-map ement-room-list-mode-map :mode ement-room-list-mode :eval-after-load ement-room-list :bindings ";" #'helm-occur "n" #'ement-room-list-next-unread) (add-hook 'ement-room-compose-hook 'ement-room-compose-org) (setf ement-save-sessions t ement-room-mark-rooms-read 'send ement-room-send-typing nil) (setq plantuml-default-exec-mode 'jar plantuml-jar-path "/usr/share/plantuml/plantuml.jar" org-plantuml-jar-path "/usr/share/plantuml/plantuml.jar" plantuml-output-type "txt") (with-eval-after-load "org-mode" (add-to-list 'org-src-lang-modes '("plantuml" . plantuml))) (setf paradox-github-token t) ;; (keyfreq-mode 1) ;; (keyfreq-autosave-mode 1) ;; (setf keyfreq-excluded-commands ;; '(self-insert-command ;; org-self-insert-command ;; forward-char ;; backward-char ;; previous-line ;; next-line ;; evil-forward-char ;; evil-backward-char ;; evil-previous-visual-line ;; evil-next-visual-line ;; helm-next-line ;; helm-previous-line ;; evil-scroll-page-down ;; evil-scroll-page-up ;; delete-backward-char ;; evil-delete-backward-char-and-join ;; evil-undo ;; mwheel-scroll ;; mouse-set-point ;; mouse-drag-region ;; evil-mouse-drag-region ;; evil-normal-state ;; keyboard-escape-quit ;; evil-goto-first-line ;; evil-insert ;; evil-append ;; evil-delete ;; evil-join ;; evil-delete-char ;; evil-open-below ;; evil-change ;; backward-delete-char-untabify ;; dired-next-line ;; dired-previous-line)) (setf pdf-view-use-scaling t pdf-view-display-size 'fit-width pdf-view-resize-factor 1.1 image-cache-eviction-delay 128 pdf-cache-image-limit 128) ;; Custom function to allow double page scrolling by calling ;; my-pdf-view-double-scroll-horizontal-view (defun my-pdf-view-double-scroll-up-or-next-page (&optional arg) "Scroll page up ARG lines if possible, else go to the next page. When `pdf-view-continuous' is non-nil, scrolling upward at the bottom edge of the page moves to the next page. Otherwise, go to next page only on typing SPC (ARG is nil)." (interactive "P") (if (or pdf-view-continuous (null arg)) (let ((hscroll (window-hscroll)) (cur-page (pdf-view-current-page))) (when (or (= (window-vscroll) (image-scroll-up arg)) ;; Workaround rounding/off-by-one issues. (memq pdf-view-display-size '(fit-height fit-page))) (pdf-view-next-page 2) (when (/= cur-page (pdf-view-current-page)) (image-bob) (image-bol 1)) (set-window-hscroll (selected-window) hscroll))) (image-scroll-up arg))) (defun my-pdf-view-double-scroll-horizontal-view () (interactive) (my-pdf-view-double-scroll-up-or-next-page) (other-window 1) (my-pdf-view-double-scroll-up-or-next-page) (other-window 1)) ;; add spacemacs major mode keybind (spacemacs/set-leader-keys-for-major-mode 'pdf-view-mode "d" 'my-pdf-view-double-scroll-horizontal-view) ;; Allow rotating of sheet music in pdfs (defun pdf-view--rotate (&optional counterclockwise-p page-p) "Rotate PDF 90 degrees. Requires pdftk to work.\n Clockwise rotation is the default; set COUNTERCLOCKWISE-P to non-nil for the other direction. Rotate the whole document by default; set PAGE-P to non-nil to rotate only the current page. \nWARNING: overwrites the original file, so be careful!" ;; error out when pdftk is not installed (if (null (executable-find "pdftk")) (error "Rotation requires pdftk") ;; only rotate in pdf-view-mode (when (eq major-mode 'pdf-view-mode) (let* ((rotate (if counterclockwise-p "left" "right")) (file (format "\"%s\"" (pdf-view-buffer-file-name))) (page (pdf-view-current-page)) (pages (cond ((not page-p) ; whole doc? (format "1-end%s" rotate)) ((= page 1) ; first page? (format "%d%s %d-end" page rotate (1+ page))) ((= page (pdf-info-number-of-pages)) ; last page? (format "1-%d %d%s" (1- page) page rotate)) (t ; interior page? (format "1-%d %d%s %d-end" (1- page) page rotate (1+ page)))))) ;; empty string if it worked (if (string= "" (shell-command-to-string (format (concat "pdftk %s cat %s " "output %s.NEW " "&& mv %s.NEW %s") file pages file file file))) (pdf-view-revert-buffer nil t) (error "Rotation error!")))))) (defun pdf-view-rotate-clockwise (&optional arg) "Rotate PDF page 90 degrees clockwise. With prefix ARG, rotate entire document." (interactive "P") (pdf-view--rotate nil (not arg))) (defun pdf-view-rotate-counterclockwise (&optional arg) "Rotate PDF page 90 degrees counterclockwise. With prefix ARG, rotate entire document." (interactive "P") (pdf-view--rotate :counterclockwise (not arg))) (define-key spacemacs-pdf-view-mode-map (kbd "R") 'pdf-view-rotate-clockwise) (setf forge-owned-accounts '(("BenedictHW" :remote-name "origin")) magit-save-repository-buffers 'dontask) ;;------------------------------------------------------------------------- ;; *** Emacs Jupyter Config ;;------------------------------------------------------------------------- (setf dired-omit-mode t ;; Stop asking to quit dired buffers of deleted files dired-clean-up-buffers-too nil) (add-hook 'dired-mode-hook (lambda () (dired-hide-details-mode))) (evilified-state-evilify-map dired-mode-map :mode dired-mode :eval-after-load dired :bindings "s" #'avy-goto-word-or-subword-1 "S" #'hydra-dired-quick-sort/body ";" #'helm-occur "C-i" #'better-jumper-jump-forward "C-o" #'better-jumper-jump-backward "q" #'spacemacs/kill-this-buffer) (setf common-lisp-hyperspec-root (concat "file://" +project-jerome-dir+ "000-generalities-information-computers/000-computer-science/HyperSpec/")) ;; https://emacs.stackexchange.com/questions/62536/what-does-making-browse-url ;; -browser-function-local-to-eww-while-let-bound-m (advice-add 'hyperspec-lookup :around (lambda (orig-fun &rest args) (setq-local browse-url-browser-function 'eww-browse-url) (apply orig-fun args))) (setf python-format-on-save t python-indent-offset 4) (require 'lexic) (setf lexic-dictionary-specs ' (("Webster's Revised Unabridged Dictionary (1913)" :short "===========================================================\n Webster's Revised Unabridged Dictionary (1913)\n===========================================================" :formatter lexic-format-webster :priority 1) ("Soule's Dictionary of English Synonyms" :short "===========================================================\n Soule's Dictionary of English Synonyms (1871)\n===========================================================" :formatter lexic-format-soule :priority 2) ("Online Etymology Dictionary" :short "===========================================================\n Online Etymology Dictionary (2000)\n===========================================================" :formatter lexic-format-online-etym :priority 3) ("Oxford English Dictionary 2nd Ed P1" :short "===========================================================\n Oxford English Dictionary 2nd Ed. (1989)\n===========================================================" :formatter lexic-format-online-etym :priority 4) ("Oxford English Dictionary 2nd Ed P2" :short "===========================================================\n Oxford English Dictionary 2nd Ed. (1989)\n===========================================================" :formatter lexic-format-online-etym :priority 5) )) ;; Set Global Keybindings (spacemacs/set-leader-keys "sx" 'lexic-search-word-at-point) (spacemacs/set-leader-keys "sX" 'lexic-search) ;; Set Lexic Major Mode Keybindings (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "q" 'lexic-return-from-lexic) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode (kbd "RET") 'lexic-search-word-at-point) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "a" 'outline-show-all) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "h" 'outline-hide-body) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "o" 'lexic-toggle-entry) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "n" 'lexic-next-entry) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "p" 'lexic-previous-entry) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "b" 'lexic-search-history-backwards) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "f" 'lexic-search-history-forwards) ;; I am convinced this is a case of bad defaults. Setting ;; =savehist-autosave-interval= to 60 seconds (from the default of 300) and ;; =history-length= to 1000 (from the default of 100) causes disproportionate ;; performance problems for arguable benefits. Performance problems can be plainly ;; seen by using the Emacs cpu+mem profiler. See ;; https://emacs.stackexchange.com/questions/12086/high-cpu-memory-usage-and-abnormally-large-savehist-file ;; =spacemacs-defaults/init-savehist=, Spacemacs Github issues #9409, #1369. ;; Reset variables to sensible Emacs defaults. (setf history-length 25 savehist-save-minibuffer-history nil savehist-autosave-interval nil kill-ring-max 200 savehist-mode nil) (delq 'mark-ring savehist-additional-variables) (delq 'global-mark-ring savehist-additional-variables) (delq 'search-ring savehist-additional-variables) (delq 'regexp-search-ring savehist-additional-variables) (delq 'extended-command-history savehist-additional-variables) (delq 'kill-ring savehist-additional-variables) (put 'org-brain-headline-cache 'history-length 10) (put 'bibtex-completion-cache 'history-length 10) (push 'org-brain-headline-cache savehist-additional-variables) (push 'bibtex-completion-cache savehist-additional-variables) (push 'helm-ff-history savehist-additional-variables) (push 'org-clock-history savehist-additional-variables) ;; Emacs profiler shows `savehist-autosave' is very performance intensive. (add-hook 'kill-emacs-hook #'savehist-save) ; Savehist only on exit. ;; Scrolling. ;; ;; The behaviors Emacs offers for scrolling can be customized ;; by the variables some of which were already mentioned: ;; scroll-conservatively, scroll-margin, scroll-step, and ;; scroll-up/down-aggressively. They basically control whether ;; Emacs recenters point when it scrolls the window, when (if ;; at all) it does recenter, by how many lines it scrolls if ;; it doesn't recenter, and how close to window edges point is ;; allowed to be before the window is scrolled. This defines a ;; set of behaviors you can get universally. In general, the ;; default is to recenter if scrolling by a few lines fails to ;; bring point into view. That is what you see, and that is ;; how Emacs works. ;; Source: https://old.reddit.com/r/emacs/comments/8jli87/is_there_a_hook_after_cursor_jump/ (setq scroll-conservatively 0) (setq scroll-preserve-screen-position t) ;; Line Breaks/Fill Column/Characters ;; ;; Prefer 80 chars due to anatomical restriction of the human eye. ;; Secondary concern of long known emacs performance issues with long lines. ;; ;; According to the Emacs manual, to enable autofill in all major modes: ;; (setq-default auto-fill-function 'do-auto-fill) ;; https://www.gnu.org/software/emacs/manual/html_node/efaq/Turning-on-auto_002dfill-by-default.html ;; ;; However, it does have side-effects in some modes, most notably it screws ;; up auto-completion in lisp mode buffers. In addition to performance ;; reasons, it makes sense to selectively enable for certain modes. ;; Therefore look under the mode configuration for the added hooks. ;; i.e. search for (add-hook 'example-mode-hook 'turn-on-auto-fill) ;; allows the use of SPC leader key in calc buffer (with-eval-after-load 'calc (define-key calc-mode-map " " spacemacs-cmds)) (setq large-file-warning-threshold '100000000) ;; https://www.masteringemacs.org/article/disabling-prompts-emacs (setq kill-buffer-query-functions (remq 'process-kill-buffer-query-function kill-buffer-query-functions)) (require 'cl-lib) (defun site/always-save-advice (oldfn &optional arg) "Overwrite `yes-or-no-p' in OLDFN. The new temporary function will return non-nil, when the message wants to save modified buffers, without querying the user. Otherwise the original behaviour is preserves, and ARG is passed on to OLDFN." (cl-letf* ((real-yes-or-no-p (symbol-function 'yes-or-no-p)) ((symbol-function 'yes-or-no-p) (lambda (msg) (or (string= msg "Modified buffers exist; exit anyway? ") (funcall real-yes-or-no-p msg))))) (funcall oldfn arg))) (advice-add #'save-buffers-kill-emacs :around #'site/always-save-advice) ;; Spacemacs default is 60 seconds. Ridiculous. (setf auto-save-interval 1000 auto-save-timeout nil) ;; https://github.com/joaotavora/yasnippet/issues/998#issuecomment-496449546 (defun my-yas-try-expanding-auto-snippets () (when (and (boundp 'yas-minor-mode) yas-minor-mode) (let ((yas-buffer-local-condition ''(require-snippet-condition . auto))) (yas-expand)))) (add-hook 'post-command-hook #'my-yas-try-expanding-auto-snippets) ;; C-h f "evilnc-comment-operator" or any of the default evil keybindings ;; to discover what maps you need to override. ;; rebind "SPC j j" or avy-goto-word-or-subword-1 to "s" ;; At first, will not work as evil-surround is using "s" in visual mode (setf evil-move-beyond-eol t) (evil-define-key 'visual evil-surround-mode-map (kbd "s") 'avy-goto-word-or-subword-1) (evil-define-key 'visual evil-surround-mode-map (kbd "S") 'evil-surround-region) (define-key evil-motion-state-map (kbd "s") 'avy-goto-word-or-subword-1) (define-key evil-normal-state-map (kbd "s") 'avy-goto-word-or-subword-1) (define-key evil-visual-state-map (kbd "s") 'avy-goto-word-or-subword-1) (define-key evil-operator-state-map (kbd "s") 'avy-goto-word-or-subword-1) (define-key package-menu-mode-map (kbd "s") 'avy-goto-word-or-subword-1) ;; #'helm-occur rebinding (define-key evil-motion-state-map (kbd ";") #'helm-occur) (define-key evil-normal-state-map (kbd ";") #'helm-occur) (define-key evil-visual-state-map (kbd ";") #'helm-occur) (define-key evil-operator-state-map (kbd ";") #'helm-occur) (define-key package-menu-mode-map (kbd ";") #'helm-occur) ;; Whenever the commands modified below are called, they are pushed ;; onto the evil-jumps-history stack (evil-add-command-properties #'evil-scroll-down :jump t) (evil-add-command-properties #'evil-scroll-up :jump t) (evil-add-command-properties #'evil-scroll-page-down :jump t) (evil-add-command-properties #'evil-scroll-page-up :jump t) (evil-add-command-properties #'helm-occur :jump t) (evil-add-command-properties #'helm-for-files :jump t) (evil-add-command-properties #'helm-projectile-find-file :jump t) (evil-add-command-properties #'spacemacs/alternate-buffer :jump t) (evil-add-command-properties #'spacemacs/helm-M-x-fuzzy-matching :jump t) (evil-add-command-properties #'helm-find-files :jump t) (evil-add-command-properties #'org-previous-visible-heading :jump t) (evil-add-command-properties #'org-next-visible-heading :jump t) (evil-add-command-properties #'outline-up-heading :jump t) (evil-add-command-properties #'outline-next-heading :jump t) (evil-add-command-properties #'org-bable-goto-src-block-head :jump t) (define-key evil-normal-state-map (kbd "q") #'spacemacs/kill-this-buffer) (define-key evil-normal-state-map (kbd "Q") #'kill-buffer-and-window) ;; Disable all keybindings other than f/t (evil-snipe-mode -1) (setq evil-snipe-scope 'whole-visible) ;; Alias [ and ] to all types of brackets ;; Alias ' to ' and " (setq evil-snipe-aliases '((?\' "['\"]") ;; No longer needed as () are translated to [] ;; via keyboard-translate function ;; (?\[ "[[{(]") ;; (?\] "[]})]") )) ;; Remove overriding of "," key in visual mode Ex. "vf)," (setq evil-snipe-override-evil-repeat-keys nil) ;; See /home/ben/.config/fd/ignore (require 'helm-fd) (require 'helm-ag) (defvar bhw/helm-source-fd (helm-make-source "fd-find" 'helm-fd-class) "For use of FD in `helm-for-files'. See also `helm-fd-switches'") ;; HACK If (error "Candidates function ‘(closure (t) nil ;; (helm-ag--do-ag-candidate-process +project-maria-dir+))’ should run a ;; process") Then eval-current-form-sp on the form below. (defvar bhw/helm-source-maria-ag (helm-make-source "Project Maria - AG" 'helm-do-ag-class :candidates-process (lambda () (helm-ag--do-ag-candidate-process +project-maria-dir+))) "To search Project Maria files from `helm-for-files'. `helm-ag--do-ag-set-source' used as exemplar. You may have to run `helm-projectile-ag' once for fuzzy matching to kick in :O.") (defvar bhw/helm-source-emacs-commands (helm-build-sync-source "Emacs Commands" :candidates (lambda () (let ((cmds)) (mapatoms (lambda (elt) (when (commandp elt) (push (symbol-name elt) cmds)))) cmds)) :coerce #'intern-soft :action #'command-execute) "A simple helm source for Emacs commands. Used in `helm-for-files'.") (setf ace-jump-helm-line-default-action 'select ace-jump-helm-line-idle-delay 1 helm-ff-auto-update-initial-value t recentf-max-saved-items 1000 helm-for-files-preferred-list '(helm-source-recentf bhw/helm-source-fd bhw/helm-source-maria-ag bhw/helm-source-emacs-commands) helm-candidate-number-limit 100 helm-ff-skip-boring-files t helm-ag-fuzzy-match t helm-fd-executable "fdfind" helm-fd-switches '("--search-path" "/home/ben" "--hidden" "--type" "f" "--type" "d" "--color" "never" "--max-results" "10" "--full-path")) (spacemacs/set-leader-keys "SPC" #'helm-for-files) (define-key helm-map (kbd "C-q") nil) ; Replace default binding. (define-key helm-map (kbd "C-d") 'ace-jump-helm-line) (require 'org) ;; Format text to fit 80 chars when pressing RET or ENTER. (add-hook 'org-mode-hook 'turn-on-auto-fill) ;; Source https://emacs.stackexchange.com/questions/10707/in-org-mode-how-to-remove-a-link (defun afs/org-replace-link-by-link-description () "Replace an org link by its description or if empty its address" (interactive) (if (org-in-regexp org-link-bracket-re 1) (save-excursion (let ((remove (list (match-beginning 0) (match-end 0))) (description (if (match-end 2) (org-match-string-no-properties 2) (org-match-string-no-properties 1)))) (apply 'delete-region remove) (insert description))))) ;; Source https://emacs.stackexchange.com/questions/12391/insert-org-id-link-at-point-via-outline-path-completion (defun org-id-complete-link (&optional arg) "Create an id: link using completion" (concat "id:" (org-id-get-with-outline-path-completion))) (org-link-set-parameters "id" :complete 'org-id-complete-link) ;; Source https://hungyi.net/posts/copy-org-mode-url/ (defun org-retrieve-url-from-point () "Copies the URL from an org link at the point" (interactive) (let ((plain-url (thing-at-point-url-at-point))) (if plain-url (progn (kill-new plain-url) (message (concat "Copied: " plain-url))) (let* ((link-info (assoc :link (org-context))) (text (when link-info (buffer-substring-no-properties (or (cadr link-info) (point-min)) (or (caddr link-info) (point-max)))))) (if (not text) (error "Oops! Point isn't in an org link") (string-match org-link-bracket-re text) (let ((url (substring text (match-beginning 1) (match-end 1)))) (kill-new url) (message (concat "Copied: " url)))))))) (setf org-directory +project-maria-dir+ org-agenda-files (cl-loop for agenda-file in '("0inbox.org" "0projects.org" "0solo.org" "0someday.org" "0contacts.org" "0calendar.org") collect (concat +project-maria-dir+ agenda-file)) ;; See org-superstar package for more context inhibit-compacting-font-caches t ;; See Org Manual 16.4 A Cleaner Outline View ;; I prefer a book-like view, which also allows for auto-fill org-adapt-indentation nil org-list-allow-alphabetical t org-image-actual-width '600 org-hide-emphasis-markers nil org-footnote-auto-adjust "Renumber and Sort" org-persist-directory "~/.cache/org-persist/" ;; Needs the libreoffice suite installed. ;; 'sudo apt install libreoffice' org-odt-preferred-output-format "docx") (spacemacs/set-leader-keys-for-major-mode 'org-mode "xR" 'afs/org-replace-link-by-link-description) (spacemacs/set-leader-keys-for-major-mode 'org-mode "iI" 'org-id-get-create) (spacemacs/set-leader-keys-for-major-mode 'org-mode "tC" 'org-table-create-or-convert-from-region) (spacemacs/set-leader-keys-for-major-mode 'org-mode "hn" 'org-next-visible-heading) (spacemacs/set-leader-keys-for-major-mode 'org-mode "hp" 'org-previous-visible-heading) (setq org-sticky-header-full-path 'full) ;; Require org-contacts to work with mu4e (require 'org-contacts) (setf org-contacts-files (list (concat +project-maria-dir+ "0contacts.org"))) (require 'org-re-reveal) (setf org-re-reveal-revealjs-version "4" org-re-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js") (setf org-mime-export-options '(:section-numbers nil ;; otherwise tables will not work :with-broken-links t :with-author nil :with-toc nil :with-latex dvipng)) (setq org-export-backends '(ascii html icalendar latex odt beamer man md org texinfo)) (setf org-download-method 'attach) ;; Add key bindings for org-expiry package (spacemacs/set-leader-keys-for-major-mode 'org-mode "dc" 'org-expiry-insert-created) (spacemacs/set-leader-keys-for-major-mode 'org-mode "de" 'org-expiry-insert-expiry) ;; Add call to org-expiry-insert-created every time org-id-get-create is run (advice-add 'org-id-get-create :after 'org-expiry-insert-created) (require 'org-depend) (require 'cl-lib) (org-clock-persistence-insinuate) (add-hook 'org-clock-in-prepare-hook 'my-org-mode-ask-effort) (defun my-org-mode-ask-effort () "Ask for an effort estimate when clocking in if none exists." (unless (org-entry-get (point) "Effort") (let ((effort (completing-read "Effort: " (org-entry-get-multivalued-property (point) "Effort")))) (unless (equal effort "") (org-set-property "Effort" effort))))) (defun eos/org-clock-in () (interactive) (org-clock-in '(4))) ;; Exclude DONE state tasks from refile targets (defun bh/verify-refile-target () "Exclude todo keywords with a done state from refile targets" (not (member (nth 2 (org-heading-components)) org-done-keywords))) ;; https://orgmode.org/worg/org-contrib/org-depend.html (defun mm/org-insert-trigger () "Automatically insert chain-find-next trigger when entry becomes NEXT" (cond ((equal org-state "NEXT") (unless org-depend-doing-chain-find-next (org-set-property "TRIGGER" "chain-find-next(NEXT,from-current,priority-up,effort-up)"))) ((not (member org-state org-done-keywords)) (org-delete-property "TRIGGER")))) (add-hook 'org-after-todo-state-change-hook 'mm/org-insert-trigger) (progn (defcustom ap/work:clocked-today-ids nil "List of Org heading IDs containing clocktables to read." :type '(repeat string)) (defcustom ap/work:clocked-today-interval 30 "Update the clocktables after this many seconds of idle time." :type 'number) ;; HACK: This version just uses the value as-is, expecting it to be a ;; decimal number with "h" suffix, and it only uses the first value in ;; the ID list. (defun ap/work:clocked-today (&optional messagep) "Show work time clocked today." (interactive (list 'messagep)) (cl-labels ((clocked-for (id) (org-with-point-at (org-id-find id 'marker) (org-narrow-to-subtree) (while (not (org-in-clocktable-p)) (forward-line)) (when (eobp) (error "Can't find clocktable at %S:%S" (current-buffer) id)) (let ((inhibit-message t)) (org-update-dblock)) (while (not (org-at-table-p)) (forward-line)) (if-let ((time (org-table-get 2 3)) ((string-match (rx (group (1+ (or digit ".")) "h")) time))) (match-string 1 time) "0h")))) (let ((string (clocked-for (car ap/work:clocked-today-ids)))) (when messagep (message "Clocked today: %s" string)) string))) (defvar ap/work:clocked-today-lighter "") (defvar ap/work:clocked-today-timer nil) (define-minor-mode ap/work:clocked-today-mode "Show time clocked today in mode line." :global t (let ((lighter '(ap/work:clocked-today-mode ap/work:clocked-today-lighter))) (if ap/work:clocked-today-mode (progn (setf ap/work:clocked-today-timer (run-with-idle-timer ap/work:clocked-today-interval ap/work:clocked-today-interval (lambda () (setf ap/work:clocked-today-lighter (concat "📆" (ap/work:clocked-today) " "))))) (cl-pushnew lighter global-mode-string :test #'equal)) (when (timerp ap/work:clocked-today-timer) (cancel-timer ap/work:clocked-today-timer)) (setf global-mode-string (remove lighter global-mode-string)))))) (spacemacs/set-leader-keys "oa" 'ben/default-custom-agenda) (spacemacs/set-leader-keys "oj" 'spacemacs/org-clock-jump-to-current-clock) (spacemacs/set-leader-keys "oi" 'eos/org-clock-in) (spacemacs/set-leader-keys "oI" 'org-clock-in) (spacemacs/set-leader-keys "oo" 'org-clock-out) (spacemacs/set-leader-keys "or" 'org-resolve-clocks) (spacemacs/set-leader-keys "oc" 'org-capture) ;; Press t to change task todo state (setf org-use-fast-todo-selection t org-treat-S-cursor-todo-selection-as-state-change t ;; Require exit notes for modifying a scheduled for deadline date org-log-reschedule 'time org-log-redeadline 'note org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "PROJ(p)" "APPT(a)" "PROG(i)" "WAIT(w@/!)" "|" "DONE(d)" "CXLD(c@/!)")) org-todo-keyword-faces '(;; Project Defined ("PROJ" :foreground "gold" :weight bold) ;; Todo's Brainstormed ("TODO" :foreground "tomato" :weight bold) ;; Next Action(s) chosen ("NEXT" :foreground "RoyalBlue" :weight bold) ;; Delegated or out of your control ("WAIT" :foreground "magenta" :weight bold) ;; Reducing from potential to actual ("PROG" :foreground "cyan2" :weight bold) ;; Completed task ("DONE" :foreground "SpringGreen3" :weight bold) ;; Formal appointment, in-person/scheduled in advance ;; Of type WAIT, but with a definte deadline ("APPT" :foreground "DarkViolet" :weight bold) ;; Informal (interruption) meeting/verbal/email ;; Informal (interruption) calls/texts ;; ("MEET" :foreground "MediumOrchid" :weight bold) ;; Cancelled task, unable to complete ("CXLD" :foreground "SaddleBrown" :weight bold)) org-enforce-todo-dependencies t org-agenda-dim-blocked-tasks t org-habit-graph-column 80 org-agenda-skip-scheduled-if-deadline-is-shown t ;; 6) Adding New Tasks Quickly with Org Capture ;; Capture templates for: TODO tasks, Notes, appointments, phone calls, meetings, and org-protocol ;; \n is newline in the template. Functions as RET would in insert mode ;; placing a backslash before " in TRIGGER below to have the string not end org-capture-templates '(("n" "Next Action" entry (file "~/project-maria/0inbox.org") "* NEXT [#C] %?%^G\n:PROPERTIES:\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n" :empty-lines 1) ("t" "Todo Task" entry (file "~/project-maria/0inbox.org") "* TODO [#C] %?%^G\n :PROPERTIES:\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n" :empty-lines 1) ("a" "Appointment" entry (file "~/project-maria/0calendar.org") "* APPT %?\nSCHEDULED: %^T\n:PROPERTIES:\n:LOCATION: %^{LOCATION|TBD}\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:" :empty-lines 1) ("j" "Journal Entry" entry (file "~/project-maria/0inbox.org")"* NEXT JOURNAL ENTRY %U\n:PROPERTIES:\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n%?" :empty-lines 1) ("h" "Habit" entry (file "~/project-maria/0inbox.org")"* NEXT %?\nSCHEDULED: %(format-time-string \"%\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:ASSIGNED: %U\n:END:" :empty-lines 1) ("c" "Contacts" entry (file "~/project-maria/0inbox.org") "* %(org-contacts-template-name)\n:PROPERTIES:\n:PHONE: %?\n:EMAIL:\n:ADDRESS:\n:BIRTHDAY:\n:NOTE: Added on: %U\n:END:" :empty-lines 1) ("p" "Project" entry (file "~/project-maria/0projects.org") "* PROJ %? [#C] [/] [%] %^G\n:PROPERTIES:\n:ASSIGNED: %U\n:CATEGORY: %^{CATEGORY|Misc.}\n:END:\n** NEXT [#C]\n:PROPERTIES:\n:TRIGGER: chain-find-next(NEXT,from-current,priority-up,effort-up)\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n" :empty-lines 1)) ;; **** 9) Clocking org-clock-in-switch-to-state "PROG" org-clock-out-remove-zero-time-clocks t org-clock-out-when-done t org-clock-persist t org-clock-in-resume t org-clock-persist-query-resume nil org-clock-auto-clock-resolution 'when-no-clock-is-running org-clock-report-include-clocking-task t org-time-stamp-rounding-minutes '(1 1) org-agenda-clockreport-parameter-plist '(:link t :maxlevel 10 :fileskip0 t :stepskip0 t :compact t :narrow 80) org-log-into-drawer t org-clock-history-length 35 ;; **** 7) Refiling Tasks org-refile-targets '((nil :maxlevel . 9) (org-agenda-files :maxlevel . 9)) org-outline-path-complete-in-steps nil org-refile-use-outline-path 'file org-refile-target-verify-function 'bh/verify-refile-target ;; **** 11) Context Tags with fast selection keys org-tag-alist '(;; Sets geo-spatial and context tags ;; Startgroup and endgroup make tags mutually ;; exclusive (:startgroup) ("0home" . ?h) ("0office" . ?o) ("0errand" . ?e) ;; (:endgroup) ;; Person(s) can be contexts too. ("0father" . ?d) ("0mother" . ?d) ("0brother" . ?d) ("0family" . ?d) ("0workteam1" . ?d) ("0docket" . ?d) ("REF" . ?r) ("FLAGGED" . ??)) org-fast-tag-selection-single-key 'expert org-tags-column 0 ;; For tag searches ignore tasks with scheduled and deadline dates org-agenda-tags-todo-honor-ignore-options t ;; **** 14) Stuck Projects org-stuck-projects '("+TODO=\"PROJ\"" ("NEXT") nil nil) ;; **** 15) Archiving org-archive-default-command 'org-archive-subtree org-archive-location (concat +project-maria-dir+ "archived-tasks/0taskings-" (format-time-string "%Y") ".org::datetree/") org-archive-save-context-info '(time category olpath ltags itags)) (add-hook 'org-agenda-mode-hook (lambda () (define-key org-agenda-mode-map (kbd "s") 'avy-goto-word-or-subword-1))) (defun my/org-agenda-calculate-efforts (limit) "Sum the efforts of scheduled entries up to LIMIT in the agenda buffer." (let (total) (save-excursion (while (< (point) limit) (when (member (org-get-at-bol 'type) '("scheduled" "past-scheduled" "timestamp")) (push (org-entry-get (org-get-at-bol 'org-hd-marker) "EFFORT") total)) (forward-line))) (org-duration-from-minutes (cl-reduce #'+ (mapcar #'org-duration-to-minutes (cl-remove-if-not 'identity total)))))) (defun my/org-agenda-insert-efforts () "Insert the efforts for each day inside the agenda buffer." (save-excursion (let (pos) (while (setq pos (text-property-any (point) (point-max) 'org-agenda-date-header t)) (goto-char pos) (end-of-line) (insert-and-inherit (concat " (" (my/org-agenda-calculate-efforts (next-single-property-change (point) 'day)) ")")) (forward-line))))) (add-hook 'org-agenda-finalize-hook 'my/org-agenda-insert-efforts) (defun ben/default-custom-agenda() "Functionally call custom agenda command bound to KEY" (interactive) (org-agenda nil "d")) (setf org-agenda-block-separator 61 org-agenda-breadcrumbs-separator " | " ;; https://stackoverflow.com/questions/58820073/s-in-org-agenda-prefix-format-doesnt-display-dates-in-the-todo-view org-agenda-prefix-format '((agenda . "%-t %? e%c%s") (todo . "%? e%c%s%(let ((scheduled (org-get-deadline-time (point)))) (if scheduled (format-time-string \" [%Y-%m-%d] \" scheduled) \"\"))") (tags . "%? e%c%s%(let ((scheduled (org-get-deadline-time (point)))) (if scheduled (format-time-string \" [%Y-%m-%d] \" scheduled) \"\"))") (search . "%? e%c%s")) org-agenda-deadline-leaders '("!D!: " "D%3d: " "") org-agenda-scheduled-leaders '("!S!: " "S%3d: " "") org-agenda-time-grid (quote ((daily today remove-match) (0600 0900 1200 1500 1800 2100) "......" "----------------")) org-columns-default-format-for-agenda "%75ITEM(Task) %10Effort(Estim){:} %10CLOCKSUM(ActTime) %5TODO(State)" org-columns-default-format "%75ITEM(Task) %10Effort(Estim){:} %10CLOCKSUM(ActTime) %5TODO(State)" org-global-properties '(quote (("Effort_ALL" . "0:00 0:10 0:30 1:00 1:30 2:00 2:30 3:00 4:00 5:00 6:00 7:00 8:00") ("STYLE_ALL" . "habit"))) org-agenda-columns-add-appointments-to-effort-sum t org-agenda-default-appointment-duration 0 org-agenda-log-mode-items '(closed state clock) org-agenda-start-with-log-mode t org-agenda-start-with-entry-text-mode t org-agenda-add-entry-text-maxlines 5 org-agenda-entry-text-maxlines 5 org-agenda-start-with-clockreport-mode nil org-agenda-custom-commands '( ;; ***** Default Agenda ("d" "Default (Master) Agenda" ((agenda "" ((org-agenda-span 1) (org-deadline-warning-days 7) (org-agenda-overriding-header "Today's Agenda\n"))) (tags "TODO=\"PROG\"" ((org-agenda-sorting-strategy '(priority-down deadline-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nTasks in Progress\n"))) (tags "TODO=\"NEXT\"" ((org-agenda-sorting-strategy '(priority-down deadline-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nAction Items\n") (org-agenda-skip-function '(org-agenda-skip-entry-if 'scheduled)))) ;; Presents only APPT and Routine Events. (agenda "" ((org-agenda-span '33) (org-agenda-start-on-weekday nil) (org-agenda-start-day "+1d") (org-agenda-entry-types '(:timestamp :sexp :scheduled)) (org-agenda-overriding-header "Routine & Appointments\n"))) (tags "+TODO=\"WAIT\"" ((org-agenda-sorting-strategy '(timestamp-down)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nDelegated/Waiting For\n"))) (tags "TODO=\"TODO\"" ((org-agenda-sorting-strategy '(category-keep)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nAll Tasks\n"))) (tags "TODO=\"PROJ\"" ((org-agenda-sorting-strategy '(category-keep)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nAll Projects\n"))) (stuck "" ((org-agenda-overriding-header "\nStuck Projects\n")))) ((org-agenda-tag-filter-preset '("-SDAY")))) ;; ***** Review Agenda ("r" "Review Agenda" ((tags "TODO=\"DONE\"" ((org-agenda-sorting-strategy '(priority-down deadline-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nCompleted Tasks\n"))) (tags "TODO=\"CXLD\"" ((org-agenda-sorting-strategy '(tsia-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nTerminated Tasks\n"))) (stuck "" ((org-agenda-overriding-header "\nStuck Projects\n"))) (agenda "" ((org-agenda-span '33) (org-agenda-start-on-weekday nil) (org-agenda-start-day "+1d") (org-agenda-entry-types '(:timestamp :sexp :scheduled)) (org-agenda-overriding-header "Routine & Appointments\n")))) ((org-agenda-tag-filter-preset '("-SDAY"))))) org-agenda-window-setup 'current-window) ;; Following 2 lines are needed to exclude parent heading from table of contents but still export the content ;; https://emacs.stackexchange.com/questions/30183/orgmode-export-skip-ignore-first-headline-level (require 'ox-extra) (ox-extras-activate '(ignore-headlines)) ;; Allows exporting bibtex citations to html (require 'ox-bibtex) ;; Exclude default CSS from html export and add external stylesheet (setq org-html-head-include-default-style nil) ;; Omit inline css as we use an imported stylesheet (setq org-html-htmlize-output-type 'css) ;; https://www.taingram.org/blog/org-mode-blog.html (setq org-export-global-macros '(("timestamp" . "@@html:<span class=\"timestamp\">[$1]</span>@@"))) (defun my/org-sitemap-date-entry-format (entry style project) "Format ENTRY in org-publish PROJECT Sitemap format ENTRY ENTRY STYLE format that includes date." (let ((filename (org-publish-find-title entry project))) (if (= (length filename) 0) (format "*%s*" entry) (format "{{{timestamp(%s)}}} [[file:%s][%s]]" (format-time-string "%Y-%m-%d" (org-publish-find-date entry project)) entry filename)))) (setf org-publish-project-alist '(("blog" :components ("blog-content" "blog-rss")) ("blog-content" :base-directory "~/project-maria/blog" :html-extension "html" :base-extension "org" :recursive t :publishing-function org-html-publish-to-html :publishing-directory "~/common-lisp/project-isidore/assets/blog" :section-numbers t :table-of-contents t :exclude "rss.org" :with-title nil :auto-sitemap t :sitemap-filename "archive.org" :sitemap-title "Blog Archive" :sitemap-sort-files anti-chronologically :sitemap-style tree :sitemap-format-entry my/org-sitemap-date-entry-format ;; Use HTML5 ;; https://orgmode.org/manual/HTML-doctypes.html#HTML-doctypes :html-doctype "html5" :html-html5-fancy t ;; Link to external custom stylesheet ;; If you need code highlight from highlight.js, include the latter three lines. :html-head " <link rel=\"stylesheet\" type=\"text/css\" href=\"../global.css\"/> <link rel=\"stylesheet\" href=\"//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/styles/base16/solarized-light.min.css\"> <script src=\"//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/highlight.min.js\" defer></script> <script>var hlf=function(){Array.prototype.forEach.call(document.querySelectorAll(\"pre.src\"),function(t){var e;e=t.getAttribute(\"class\"),e=e.replace(/src-(\w+)/,\"src-$1 $1\"),console.log(e),t.setAttribute(\"class\",e),hljs.highlightBlock(t)})};addEventListener(\"DOMContentLoaded\",hlf);</script>" :html-preamble " <div class=\"header header-fixed\"> <div class=\"navbar container\"> <div class=\"logo\"><a href=\"/\">BHW</a></div> <input type=\"checkbox\" id=\"navbar-toggle\" > <label for=\"navbar-toggle\"><i></i></label> <nav class=\"menu\"> <ul> <li><a href=\"/about\">About</a></li> <li><a href=\"/work\">Work</a></li> <li><a href=\"/assets/blog/archive.html\">Blog</a></li> <li><a href=\"/contact\">Contact</a></li> </ul> </nav> </div> </div> <h1 class=\"title\">%t</h1> <p class=\"subtitle\">%s</p> <br/> <p class=\"updated\"><a href=\"/contact#article-history\">Updated:</a> %C</p>" ;; Article Postamble includes ;; Javascript snippet to insert anchor links to Table of Contents ;; HTML Footer :html-postamble "<script> const headers = Array.from( document.querySelectorAll('h2, h3, h4, h5, h6') ); headers.forEach( header => { header.insertAdjacentHTML('afterbegin', '<a href=\"#table-of-contents\">⇱</a>' ); }); </script> <hr/> <footer> <div class=\"copyright-container\"> Comments? Corrections? <a href=\"https://bhw.name/contact\"> Please do reach out.</a><a href=\"https://bhw.name/blog/rss.xml\"> RSS Feed. </a><a href=\"https://bhw.name/subscribe\"> Mailing List. </a><br/> Copyright 2021 Benedict H. Wang. <br/> Blog content is available under <a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/4.0/\"> CC-BY-SA 4.0 </a> unless otherwise noted.<br/> Created with %c on <a href=\"https://www.gnu.org\">GNU</a>/<a href=\"https://www.kernel.org/\">Linux</a><br/> </div> </footer>" ) ("blog-rss" :base-directory "~/project-maria/blog" :base-extension "org" :publishing-directory "~/common-lisp/project-isidore/assets/blog" :publishing-function publish-posts-rss-feed :rss-extension "xml" :html-link-home "http://bhw.name/" :html-link-use-abs-url t :html-link-org-files-as-html t :exclude "archive.org" :auto-sitemap t :sitemap-function posts-rss-feed :sitemap-title "Benedict H. Wang Blog RSS" :sitemap-filename "rss.org" :sitemap-style list :sitemap-sort-files anti-chronologically :sitemap-format-entry format-posts-rss-feed-entry) )) ;; https://alhassy.github.io/AlBasmala#Clickable-Headlines (defun my/ensure-headline-ids (&rest _) "Org trees without a custom ID will have All non-alphanumeric characters are cleverly replaced with ‘-’. If multiple trees end-up with the same id property, issue a message and undo any property insertion thus far. E.g., ↯ We'll go on a ∀∃⇅ adventure ↦ We'll-go-on-a-adventure " (interactive) (let ((ids)) (org-map-entries (lambda () (org-with-point-at (point) (let ((id (org-entry-get nil "CUSTOM_ID"))) (unless id (thread-last (nth 4 (org-heading-components)) (s-replace-regexp "[^[:alnum:]']" "-") (s-replace-regexp "-+" "-") (s-chop-prefix "-") (s-chop-suffix "-") (setq id)) (if (not (member id ids)) (push id ids) (message-box "Oh no, a repeated id!\n\n\t%s" id) (undo) (setq quit-flag t)) (org-entry-put nil "CUSTOM_ID" id)))))))) ;; Whenever html & md export happens, ensure we have headline ids. (advice-add 'org-html-export-to-html :before 'my/ensure-headline-ids) (advice-add 'org-md-export-to-markdown :before 'my/ensure-headline-ids) ;; https://nicolasknoebber.com/posts/blogging-with-emacs-and-org.html (defun format-posts-rss-feed-entry (entry _style project) "Format ENTRY for the posts RSS feed in PROJECT." (org-publish-initialize-cache "blog-rss") (let* ((title (org-publish-find-title entry project)) (link (concat "blog/" (file-name-sans-extension entry) ".html")) (author (org-publish-find-property entry :author project)) (pubdate (format-time-string (car org-time-stamp-formats) (org-publish-find-date entry project)))) (message pubdate) (format "%s :properties: :rss_permalink: %s :author: %s :pubdate: %s :end:\n" title link author pubdate))) (defun posts-rss-feed (title list) "Generate a sitemap of posts that is exported as a RSS feed. TITLE is the title of the RSS feed. LIST is an internal representation for the files to include. PROJECT is the current project." (concat "#+TITLE: " title "\n#+EMAIL: seneschal@bhw.name" "\n\n" (org-list-to-subtree list))) (defun publish-posts-rss-feed (plist filename dir) "Publish PLIST to RSS when FILENAME is rss.org. DIR is the location of the output." (if (equal "rss.org" (file-name-nondirectory filename)) (org-rss-publish-to-rss plist filename dir))) (add-hook 'org-mode 'org-tanglesync-mode) (add-hook 'prog-mode 'org-tanglesync-watch-mode) (add-hook 'text-mode 'org-tanglesync-watch-mode) (setf org-tanglesync-default-diff-action ':diff org-tanglesync-watch-files '("dotfiles.org")) (spacemacs/set-leader-keys-for-major-mode 'org-mode "bS" 'org-tanglesync-process-buffer-interactive) ;; Fix for wget option flags, as per https://github.com/alphapapa/org-web-tools/issues/35 (setq org-web-tools-archive-wget-options '("--ignore-tags=script,iframe" "--reject=eot,ttf,svg,otf,*.woff*" "--execute" "robots=off" "--adjust-extension" "--span-hosts" "--convert-links" "--page-requisites" "--timestamping" "--no-directories")) (setq org-web-tools-archive-wget-html-only-options '("--execute" "robots=off" "--adjust-extension" "--timestamping" "--no-directories")) ;; For when you are lost in a long code block (spacemacs/set-leader-keys "aob" 'org-babel-goto-src-block-head) ;; Used below to rename org edit blocks ;; https://emacs.stackexchange.com/questions/2483/referring-to-the-org-babel-src-block-name-from-within-the-script ;; EDIT please change function so that src blocks with no name get a temporary ;;name. otherwise code highlighting is broken. (defun org-src--construct-edit-buffer-name (org-buffer-name lang) "Construct the buffer name for a source editing buffer." (concat (nth 4 (org-babel-get-src-block-info)) " [" lang "]")) ;; =SPC h d v "org-babel-load-languages" shows that emacs-lisp and ;; shell code is already enabled in org-babel. (org-babel-do-load-languages 'org-babel-load-languages (append org-babel-load-languages '((ledger . t) (calc . t) (js . t) (emacs-lisp . t) (shell . t) (lisp . t) ;; (mathematica . t) (latex . t) ;; (jupyter . t) ;; must be last ))) ;; Sanitize output and deal with paths (setq org-babel-mathematica-command (concat +project-maria-dir+ "mash.pl")) ;; Font-locking ;; (add-to-list 'org-src-lang-modes '("mathematica" . wolfram)) ;; (autoload 'wolfram-mode "wolfram-mode" nil t) ;; (autoload 'run-wolfram "wolfram-mode" nil t) ;; (setq wolfram-program "/home/ben/Wolfram/WolframEngine/12.2/Executables/WolframKernel") ;; (add-to-list 'auto-mode-alist '("\.m$" . wolfram-mode)) ;; (setq wolfram-path "~/.WolframEngine/Applications") ;; e.g. on Linux ~/.Mathematica/Applications ;; For wolfram-mode ;; (setq mathematica-command-line "~/project-maria/mash.pl") ;; (setq org-babel-python-command "/usr/bin/python3") ;; enable proper mode for sagemath code blocks ;; (add-to-list 'org-src-lang-modes '("jupyter-sage" . python)) ;; See library of babel > org babel org heading for more detail (defun org-in-tangle-dir (sub-path) "Expand the SUB-PATH into the directory given by the tangle-dir property if that property exists, else use the `default-directory'." (expand-file-name sub-path (or (org-entry-get (point) "tangle-dir" 'inherit) (default-directory)))) ;; (load "~/.emacs.d/private/local/org-recoll.el") ;; (setq org-recoll-results-num 50) ;; (spacemacs/set-leader-keys "ss" 'org-recoll-search) (setf org-attach-id-dir "~/project-jerome/org-attach-data/" ;; https://helpdeskheadesk.net/2022-03-13/ ;; For org attach, change org timestamps to more human readable format. org-id-method 'ts org-attach-id-to-path-function-list '(org-attach-id-ts-folder-format org-attach-id-uuid-folder-format)) (setf org-noter-always-create-frame nil org-noter-hide-other nil org-noter-auto-save-last-location t) (spacemacs/set-leader-keys "aon" 'org-noter) (require 'org-brain) (require 'org-expiry) ;; Add CREATED property when adding a new org-brain headline entry (add-hook 'org-brain-new-entry-hook #'org-expiry-insert-created) (spacemacs/set-leader-keys "o SPC" 'org-brain-visualize-dwim) ;; For evil users, (with-eval-after-load 'evil (evil-set-initial-state 'org-brain-visualize-mode 'emacs)) ;; Automatically add ID properties to all org headlines when saving ;; Disabled because of slowdown, use org-id-get-create instead ;; (add-hook 'before-save-hook #'org-brain-ensure-ids-in-buffer) (defun org-expiry-created-comp (a b) "Compare `org-expiry-created-property-name' properties of A and B." (let ((ta (ignore-errors (org-time-string-to-seconds (org-entry-get (get-text-property 0 'org-marker a) org-expiry-created-property-name)))) (tb (ignore-errors (org-time-string-to-seconds (org-entry-get (get-text-property 0 'org-marker b) org-expiry-created-property-name))))) (cond ((if ta (and tb (< ta tb)) tb) -1) ((if tb (and ta (< tb ta)) ta) +1)))) (defun org-brain-timeline () "List all org-brain headlines in chronological order." (interactive) (let ((org-agenda-files (org-brain-files)) (org-agenda-cmp-user-defined #'org-expiry-created-comp) (org-agenda-sorting-strategy '(user-defined-down))) (org-tags-view nil (format "+%s>\"\"" org-expiry-created-property-name)))) (defun org-brain-cliplink-resource () "Add a URL from the clipboard as an org-brain resource. Suggest the URL title as a description for resource." (interactive) (let ((url (org-cliplink-clipboard-content))) (org-brain-add-resource url (org-cliplink-retrieve-title-synchronously url) t))) (define-key org-brain-visualize-mode-map (kbd "L") #'org-brain-cliplink-resource) ;; Prettify the lines via aa2u package, or ascii art to unicode (defface aa2u-face '((t . nil)) "Face for aa2u box drawing characters") (advice-add #'aa2u-1c :filter-return (lambda (str) (propertize str 'face 'aa2u-face))) (defun aa2u-org-brain-buffer () (let ((inhibit-read-only t)) (make-local-variable 'face-remapping-alist) (add-to-list 'face-remapping-alist '(aa2u-face . org-brain-wires)) (ignore-errors (aa2u (point-min) (point-max))))) (with-eval-after-load 'org-brain (add-hook 'org-brain-after-visualize-hook #'aa2u-org-brain-buffer)) (define-key org-brain-visualize-mode-map (kbd "j") #'evil-scroll-page-down) (define-key org-brain-visualize-mode-map (kbd "k") #'evil-scroll-page-up) (define-key org-brain-visualize-mode-map (kbd "i") #'org-brain-select-map) (define-key org-brain-visualize-mode-map (kbd "I") #'org-brain-select-dwim) (define-key org-brain-visualize-mode-map (kbd "s") #'link-hint-open-link) ;; Org-brain initialization (setf org-brain-path +project-maria-dir+ org-id-track-globally t org-brain-data-file "~/.emacs.d/.cache/.org-brain-data.el" org-id-locations-file "~/.emacs.d/.cache/.org-id-locations" org-brain-visualize-default-choices 'all org-brain-title-max-length 90 org-brain-include-file-entries nil org-brain-file-entries-use-title nil org-brain-headline-entry-name-format-string "%2$s" org-brain-quit-after-goto t org-brain-backlink "<--" org-expiry-inactive-timestamps t) (use-package poly-org :after org) ; Should be after org mode config. ;; https://old.reddit.com/r/emacs/comments/g8ecpj/advice_for_auclatex_what_keybinds_do_you_find/foo64ge/ ;; What really increased my speed is having snippets (yasnippet) for ;; frequently used patterns, auto paired parentheses ;; (electric-pair-local-mode or smartparens), and cd-latex ;; (org-cdlatex-mode) which auto inserts brackets for ;; subscript/superscripts. There's still a lot more to be done for speed, ;; learning these packages and creating keybindings though. All in due ;; time! Turns on unicode characters for org-mode (setf org-pretty-entities t org-pretty-entities-include-sub-superscripts nil ;; Bigger latex fragment org-format-latex-options (plist-put org-format-latex-options :scale 3)) ;; It generates a a png and overlays it onto the text as soon as your cursor ;; moves away from the math mode dollar signs. Automatically toggle org-mode ;; latex fragment previews as the cursor enters and exits them (add-hook 'org-mode-hook 'org-fragtog-mode) (require 'org-ref) (require 'org-ref-helm) (defun my/org-ref-open-pdf-at-point () "Open the pdf for bibtex key under point if it exists." (interactive) (let* ((results (org-ref-get-bibtex-key-and-file)) (key (car results)) (pdf-file (funcall org-ref-get-pdf-filename-function key))) (if (file-exists-p pdf-file) (find-file pdf-file) (message "No PDF found for %s" key)))) (spacemacs/set-leader-keys "s SPC" 'helm-bibtex) (setf org-bibtex-file (concat +project-maria-dir+ "project-jerome.bib") reftex-default-bibliography (list (concat +project-maria-dir+ "project-jerome.bib")) helm-bibtex-full-frame nil bibtex-completion-bibliography (list (concat +project-maria-dir+ "project-jerome.bib")) ;; Clicking on a citation in an org file will draw up a list of actions ;; One of these is view notes. this is where the index of notes is stored ;; Alternatively, calling ", n" while in project-jerome.bib will call ;; org-ref-open-bibtex-notes, which will populate project-jerome-index.org ;; Tell org-ref to let helm-bibtex find notes for it org-ref-notes-function (lambda (thekey) (let ((bibtex-completion-bibliography (org-ref-find-bibliography))) (bibtex-completion-edit-notes (list (car (org-ref-get-bibtex-key-and-file thekey)))))) ;; Taken from https://github.com/jkitchin/org-ref/blob/master/org-ref.org#customizing-how-pdfs-are-opened org-ref-get-pdf-filename-function 'org-ref-get-pdf-filename-helm-bibtex org-ref-open-pdf-function 'my/org-ref-open-pdf-at-point bibtex-completion-bibliography (concat +project-maria-dir+ "project-jerome.bib") bibtex-completion-notes-path (concat +project-maria-dir+ "bibtex-notes") bibtex-completion-notes-template-multiple-files (concat "* ${title}\n" ":PROPERTIES:\n" ":AUTHOR: ${author-abbrev}\n" ":YEAR: ${year}\n" ":END:\n\n") bibtex-completion-pdf-field "file" bibtex-completion-library-path '("~/project-jerome" "~/project-jerome/000-generalities-information-computers" "~/project-jerome/000-generalities-information-computers/000-computer-science" "~/project-jerome/000-generalities-information-computers/010-bibliography" "~/project-jerome/000-generalities-information-computers/020-library-information-sciences" "~/project-jerome/000-generalities-information-computers/030-general-encyclopedic-works" "~/project-jerome/000-generalities-information-computers/040-special-topics" "~/project-jerome/000-generalities-information-computers/050-general-serials-indexes" "~/project-jerome/000-generalities-information-computers/060-general-organizations-museums" "~/project-jerome/000-generalities-information-computers/070-news-media-journalism-publishing" "~/project-jerome/000-generalities-information-computers/080-general-collections" "~/project-jerome/000-generalities-information-computers/090-manuscripts-rare-books" "~/project-jerome/100-philosphy-psychology" "~/project-jerome/100-philosphy-psychology/110-metaphysics" "~/project-jerome/100-philosphy-psychology/120-epistemology-causation-humankind" "~/project-jerome/100-philosphy-psychology/130-paranormal-phenomena" "~/project-jerome/100-philosphy-psychology/140-specific-philosophical-schools" "~/project-jerome/100-philosphy-psychology/150-psychology" "~/project-jerome/100-philosphy-psychology/160-logic" "~/project-jerome/100-philosphy-psychology/170-ethics-moral-philosophy" "~/project-jerome/100-philosphy-psychology/180-ancient-medieval-oriental-philosophy" "~/project-jerome/100-philosphy-psychology/190-modern-western-philosophy" "~/project-jerome/200-religion" "~/project-jerome/200-religion/210-natural-theology" "~/project-jerome/200-religion/220-bible" "~/project-jerome/200-religion/230-christian-theology" "~/project-jerome/200-religion/230-christian-theology/239-apologetics" "~/project-jerome/200-religion/240-christian-moral-devotional-theology" "~/project-jerome/200-religion/240-christian-moral-devotional-theology/242-devotional-literature" "~/project-jerome/200-religion/250-christian-orders-local-churches" "~/project-jerome/200-religion/250-christian-orders-local-churches/252-texts-of-sermons" "~/project-jerome/200-religion/250-christian-orders-local-churches/253-pastoral-office-and-work" "~/project-jerome/200-religion/260-christian-social-theology" "~/project-jerome/200-religion/270-christian-church-history" "~/project-jerome/200-religion/280-christian-denominations-sects" "~/project-jerome/200-religion/290-other-comparative-religions" "~/project-jerome/300-social-sciences" "~/project-jerome/300-social-sciences/310-general-statistics" "~/project-jerome/300-social-sciences/320-political-science" "~/project-jerome/300-social-sciences/330-economics" "~/project-jerome/300-social-sciences/340-law" "~/project-jerome/300-social-sciences/350-public-administration" "~/project-jerome/300-social-sciences/360-social-problems-services" "~/project-jerome/300-social-sciences/370-education" "~/project-jerome/300-social-sciences/380-commerce-communications-transport" "~/project-jerome/300-social-sciences/390-customs-etiquette-folklore" "~/project-jerome/400-philology" "~/project-jerome/400-philology/410-linguistics" "~/project-jerome/400-philology/420-english-anglosaxon-languages" "~/project-jerome/400-philology/430-germanic-languages" "~/project-jerome/400-philology/440-romance-languages" "~/project-jerome/400-philology/450-italian-romanian-rhaeto-romanic" "~/project-jerome/400-philology/460-spanish-portuguese-languages" "~/project-jerome/400-philology/470-italic-languages-latin" "~/project-jerome/400-philology/480-hellenic-languages-classical-greek" "~/project-jerome/400-philology/490-other-languages" "~/project-jerome/500-natural-science" "~/project-jerome/500-natural-science/510-mathematics" "~/project-jerome/500-natural-science/520-astronomy-allied-sciences" "~/project-jerome/500-natural-science/530-physics" "~/project-jerome/500-natural-science/540-chemistry-allied-sciences" "~/project-jerome/500-natural-science/550-earth-sciences" "~/project-jerome/500-natural-science/560-paleontology-paleozoology" "~/project-jerome/500-natural-science/570-life-sciences" "~/project-jerome/500-natural-science/580-botanical-sciences" "~/project-jerome/500-natural-science/590-zoological-sciences" "~/project-jerome/600-applied-science" "~/project-jerome/600-applied-science/610-medical-sciences-psychiatry" "~/project-jerome/600-applied-science/620-engineering" "~/project-jerome/600-applied-science/630-agriculture" "~/project-jerome/600-applied-science/640-home-economics-family-living" "~/project-jerome/600-applied-science/650-management" "~/project-jerome/600-applied-science/660-chemical-engineering" "~/project-jerome/600-applied-science/670-manufacturing" "~/project-jerome/600-applied-science/680-manufacture-for-specific-use" "~/project-jerome/600-applied-science/690-buildings" "~/project-jerome/700-arts-recreation" "~/project-jerome/700-arts-recreation/710-civic-landscape-art" "~/project-jerome/700-arts-recreation/720-architecture" "~/project-jerome/700-arts-recreation/730-sculpture" "~/project-jerome/700-arts-recreation/740-drawings-decorative-arts" "~/project-jerome/700-arts-recreation/750-paintings-painters" "~/project-jerome/700-arts-recreation/760-graphics-arts-printmaking" "~/project-jerome/700-arts-recreation/770-photography" "~/project-jerome/700-arts-recreation/780-music" "~/project-jerome/700-arts-recreation/790-recreational-performing-arts" "~/project-jerome/800-literature" "~/project-jerome/800-literature/810-american-literature-in-english" "~/project-jerome/800-literature/820-english-literature" "~/project-jerome/800-literature/830-literature-of-germanic-language" "~/project-jerome/800-literature/840-literatures-of-romance-language" "~/project-jerome/800-literature/850-italian-romanian-rhaeto-romaic-literatures" "~/project-jerome/800-literature/860-spanish-portuguese-literatures" "~/project-jerome/800-literature/870-italic-literatures-latin" "~/project-jerome/800-literature/880-hellenic-literatures-classical-greek" "~/project-jerome/800-literature/890-literatures-of-other-languages" "~/project-jerome/900-history-geography-biography" "~/project-jerome/900-history-geography-biography/910-geography-travel" "~/project-jerome/900-history-geography-biography/920-biography-genealogy-insignia" "~/project-jerome/900-history-geography-biography/930-history-of-the-ancient-world" "~/project-jerome/900-history-geography-biography/940-general-history-of-europe" "~/project-jerome/900-history-geography-biography/950-general-history-of-asia" "~/project-jerome/900-history-geography-biography/960-general-history-of-africa" "~/project-jerome/900-history-geography-biography/970-general-history-of-north-america" "~/project-jerome/900-history-geography-biography/980-general-history-of-south-america" "~/project-jerome/900-history-geography-biography/990-general-history-of-other-areas") bibtex-completion-format-citation-functions '((org-mode . org-ref-helm-bibtex-insert-citation) (latex-mode . bibtex-completion-format-citation-cite) (markdown-mode . bibtex-completion-format-citation-pandoc-citeproc) (default . bibtex-completion-format-citation-default)) helm-source-bibtex org-ref-helm-source-bibtex) (defun mu4e-headers-mark-all-unread-read () "Put a ! \(read) mark on all visible unread messages." (interactive) (mu4e-headers-mark-for-each-if (cons 'read nil) (lambda (msg _param) (memq 'unread (mu4e-msg-field msg :flags)))) (mu4e-mark-execute-all t)) (defun mu4e-headers-refile-all () "Refile all messages in buffer." (interactive) (mu4e-headers-mark-for-each-if (cons 'refile nil) (lambda (_msg _param) t)) (mu4e-mark-execute-all t) (mu4e-search-prev)) (setf mu4e-change-filenames-when-moving t ; mbsync specific. ;; see an ASCII table for the character decimal codes mu4e-bookmarks '(("maildir:/INBOX" "Inbox" 105 ) ("\"maildir:/[Gmail]/All Mail\" and flag:unread" "Unread" 85)) user-mail-address (get-authinfo-password "personal.gmail" "ben") user-full-name "Benedict H. Wang" ;; mu4e-compose-signature mail-user-agent 'mu4e-user-agent mu4e-attachment-dir "/mnt/c/Users/bened/Downloads/" mu4e-drafts-folder "/[Gmail]/Drafts" mu4e-sent-folder "/[Gmail]/Sent Mail" mu4e-trash-folder "/[Gmail]/Trash" mu4e-refile-folder "/[Gmail]/All Mail" send-mail-function 'smtpmail-send-it smtpmail-stream-type 'starttls smtpmail-default-smtp-server "smtp.gmail.com" smtpmail-smtp-server "smtp.gmail.com" smtpmail-smtp-service 587 message-sendmail-f-is-evil t mu4e-index-update-in-background t mu4e-update-interval 900 mu4e-autorun-background-at-startup t mu4e-get-mail-command "mbsync -a" mu4e-hide-index-messages t mu4e-enable-mode-line nil ;; If this is enabled, prompts for new gpg fingerprints will not show up. ;; Instead emails will silently fail to send. mu4e-enable-async-operations nil mu4e-search-skip-duplicates t ;; Multipart html/plaintext email default, if the html portion is larger ;; by a factor of 5, it is assumed the user wants to view html. This ;; sets the factor to the largest possible fixnum, for we prefer the ;; plaintext version. mu4e-view-html-plaintext-ratio-heuristic most-positive-fixnum gnus-blocked-images "." mu4e-org-link-query-in-headers-mode nil ;; mu4e-org-contacts-file (concat +project-maria-dir+ "0contacts.org") message-kill-buffer-on-exit t mu4e-confirm-quit nil mu4e-headers-fields '((:human-date . 5) (:from-or-to . 20) (:subject)) mml-secure-openpgp-sign-with-sender t mml-secure-openpgp-signers '("06DDA93690F775E3715B628CCA949A6D46BC2BBE") mu4e-compose-complete-addresses t mu4e-compose-complete-only-after "2018-01-01" browse-url-filename-alist '(("^/\\(ftp@\\|anonymous@\\)?\\([^:/]+\\):/*" . "ftp://\\2/") ("^/\\([^:@/]+@\\)?\\([^:/]+\\):/*" . "ftp://\\1\\2/") ;; For gnus-article-browse-html-article on Windows Subsystem for Linux. ("^/+" . "file://///wsl$/Debian/")) ) (with-eval-after-load "recentf" (progn (add-to-list 'recentf-exclude "~/project-jerome/email-archive/") (add-to-list 'recentf-exclude "/tmp/"))) ;; Unbind s, originally bound to mu4e-headers-search. ;; Unset =mu4e-headers=search= from both =mu4e-headers-mode-map= and ;; =mu4e-view-mode-map=. Retain =s= for search in =mu4e-main-mode-map=. (define-key mu4e-headers-mode-map (kbd "s") #'avy-goto-word-or-subword-1) (define-key mu4e-headers-mode-map (kbd "K") #'mu4e-view-save-url) (define-key mu4e-headers-mode-map "S" 'helm-mu) (add-hook 'mu4e-view-mode-hook (lambda () (progn (evil-evilified-state) (define-key mu4e-view-mode-map (kbd "s") #'avy-goto-word-or-subword-1) (define-key mu4e-view-mode-map (kbd "K") #'mu4e-view-save-url) (define-key mu4e-view-mode-map "S" 'helm-mu)))) (define-key mu4e-headers-mode-map (kbd "c") #'mu4e-headers-mark-all-unread-read) (define-key mu4e-headers-mode-map (kbd "C") #'mu4e-headers-refile-all) ;; Functions ran on every message sent (spacemacs/set-leader-keys-for-major-mode 'mu4e-compose-mode "o" 'org-mime-edit-mail-in-org-mode) (spacemacs/set-leader-keys-for-major-mode 'mu4e-compose-mode "p" 'mml-secure-message-sign-pgpmime) (spacemacs/set-leader-keys (kbd "aes") #'helm-mu (kbd "aec") #'helm-mu-contacts (kbd "aej") #'mu4e-search-bookmark) (require 'elfeed) (require 'hydra) (require 'elfeed-tube) (setf elfeed-db-directory "~/.emacs.d/.cache/elfeed" elfeed-use-curl t) ;; Remove default binding so evilify mapping takes over. ;; Set shortcut for org-web-tools to fetch full article (with-eval-after-load "elfeed" (progn (define-key elfeed-search-mode-map (kbd "RET") nil) (define-key elfeed-search-mode-map (kbd "RET") #'ap/elfeed-search-browse-org))) (defhydra ben/hydra-elfeed (:exit t) ("g" (elfeed-search-set-filter "@6-months-ago +unread +gbl") "Global News") ("l" (elfeed-search-set-filter "@6-months-ago +unread +lcl") "Local News") ("s" (elfeed-search-set-filter "@6-months-ago +unread +sci") "Science & Tech") ("b" (elfeed-search-set-filter "@6-months-ago +unread +blog") "Misc. Blogs") ("c" (elfeed-search-set-filter "@6-months-ago +unread +rel") "Catholic") ("f" (elfeed-search-set-filter "@6-months-ago +unread +frm") "Forums") ("o" (elfeed-search-set-filter "@6-months-ago +unread +pod") "Podcasts") ("y" (elfeed-search-set-filter "@6-months-ago +unread +vid") "Youtube") ("a" (elfeed-search-set-filter "@6-months-ago +unread") "All") ("q" nil "quit" :color blue)) (evilified-state-evilify-map elfeed-search-mode-map :mode elfeed-search-mode :eval-after-load elfeed-search :bindings "s" #'avy-goto-word-or-subword-1 "S" #'elfeed-search-live-filter "f" #'ben/hydra-elfeed/body "r" #'elfeed-mark-all-as-read "RET" #'ap/elfeed-search-browse-org "t" #'elfeed-search-show-entry ";" #'helm-occur "b" #'ben/elfeed-search-browse-url "C-u b" #'elfeed-search-browse-url "o" #'elfeed-tube-fetch "gr" #'elfeed-update) (evilified-state-evilify-map elfeed-show-mode-map :bindings "s" #'avy-goto-word-or-subword-1 ";" #'helm-occur) (defun elfeed-mark-all-as-read () "Marks entire buffer before tagging marked region as read" (interactive) (mark-whole-buffer) (elfeed-search-untag-all-unread)) ;; Source https://www.reddit.com/r/emacs/comments/g6oowz/elfeed_rules/fodeb8x/ (defun ap/elfeed-search-browse-org () "Open selected items as Org." (interactive) (let ((browse-url-browser-function (lambda (url _) (org-web-tools-read-url-as-org url)))) (ap/elfeed-search-selected-map #'ap/elfeed-search-browse-entry))) (defun ap/elfeed-search-browse-entry (entry) "Browse ENTRY with `browse-url' and mark as read. If ENTRY is unread, it will also be unstarred. To override the browser function, bind `browse-url-browser-function' around the call to this." (let ((url (elfeed-entry-link entry)) (tags (elfeed-entry-tags entry))) ;; Mark as read first, because apparently the elfeed functions don't work after `browse-url' ;; potentially changes the buffer. (elfeed-untag entry 'unread) (elfeed-search-update-entry entry) (browse-url url))) (cl-defun ap/elfeed-search-selected-map (fn) "Map FN across selected entries in elfeed-search buffer using `mapcar'." (mapcar fn (elfeed-search-selected))) (defun ben/elfeed-search-browse-url (&optional use-generic-p) "Visit the current entry in your browser using `browse-url'. If there is a prefix argument, visit the current entry in the browser defined by `browse-url-generic-program'." (interactive "P") (let ((buffer (current-buffer)) (entries (elfeed-search-selected))) (cl-loop for entry in entries do (elfeed-untag entry 'unread) when (elfeed-entry-link entry) do (if use-generic-p (browse-url-generic it) (eww it))) ;; `browse-url' could have switched to another buffer if eww or another ;; internal browser is used, but the remainder of the functions needs to ;; run in the elfeed buffer. (with-current-buffer buffer (mapc #'elfeed-search-update-entry entries) (unless (or elfeed-search-remain-on-entry (use-region-p)) (forward-line))))) (add-hook 'elfeed-new-entry-hook #'elfeed-tube--auto-fetch) (advice-add 'elfeed-show-entry :after #'elfeed-tube--auto-fetch) (advice-add elfeed-show-refresh-function :after #'elfeed-tube-show) ;; Forces bash shell into interactive mode, leadings to sourcing of ;; ~/.bashrc and interactive aliases and functions ;; (setq shell-command-switch "-ic") ;; Default value was "-c" (setq shell-command-switch "-c") (setf auto-revert-interval 30) (auto-revert-set-timer) ;; https://rufflewind.com/2014-07-20/pasting-unicode-in-emacs-on-windows ;; (set-selection-coding-system 'utf-16-le) ;; Based on https://stackoverflow.com/questions/12102554/emacs-skip-whitespace-kills (define-advice kill-new (:around (orig-fn string &optional rest) ignore-whitespaces) "Don't put whitespaces into kill ring." (let* ((string-raw (substring-no-properties string)) (space-p (not (string-match-p "[^ \t\n\r]" string-raw)))) (if (not space-p) (apply orig-fn string rest) (message "skipped whitespace kill") nil))) ;; https://gnu.emacs.help.narkive.com/p20hvAvC/keyboard-translate-not-working-with-emacs-daemon (define-key key-translation-map [?\(] [?\[]) (define-key key-translation-map [?\[] [?\(]) (define-key key-translation-map [?\)] [?\]]) (define-key key-translation-map [?\]] [?\)]) ;; Should double buffering cause lag spikes on 3840 x 2160 displays ;; we can disable it via... (add-to-list 'default-frame-alist '(inhibit-double-buffering . t)) ;; Sets default browser (setf browse-url-generic-program "/mnt/c/Windows/System32/cmd.exe" browse-url-generic-args '("/c" "start") browse-url-browser-function #'browse-url-generic package-install-upgrade-built-in t) ;; Useful trick to share snippets between modes. Whenever a major mode ;; is loaded, fundamental-mode is also loaded (add-hook 'yas-minor-mode-hook (lambda () (yas-activate-extra-mode 'fundamental-mode))) ;; User Defined Toggles -> See SPC t hydra menu ;; VISUALLY wraps words that go past screen length ;; setq-default command means the command is run in every major mode buffer (setq-default truncate-lines nil) ;; Enables line by line navigation. Lines are not line broken > use RET for that (spacemacs/toggle-visual-line-navigation-globally-on) ;; Determines the length of time between the end of typing for SPC j j (avy-timer) ;; and the appearance of green prompt letters (setq avy-timeout-seconds 0.50) )
3.1. Biome Config
(require 'biome) (biome-def-preset biome-query-preset-14 ((:name . "GEM (Canada)") (:group . "hourly") (:params ("hourly" "wind_speed_10m" "cloud_cover" "precipitation" "apparent_temperature") ("longitude" . -79.337021) ("latitude" . 43.856098)))) (spacemacs/set-leader-keys "a w w" 'biome-query-preset-14)
3.2. Bibtex Layer Config
Citations in org-mode: Org-cite and Citar | Kristoffer Balintona
(require 'org-ref) (require 'org-ref-helm) (defun my/org-ref-open-pdf-at-point () "Open the pdf for bibtex key under point if it exists." (interactive) (let* ((results (org-ref-get-bibtex-key-and-file)) (key (car results)) (pdf-file (funcall org-ref-get-pdf-filename-function key))) (if (file-exists-p pdf-file) (find-file pdf-file) (message "No PDF found for %s" key)))) (spacemacs/set-leader-keys "s SPC" 'helm-bibtex) (setf org-bibtex-file (concat +project-maria-dir+ "project-jerome.bib") reftex-default-bibliography (list (concat +project-maria-dir+ "project-jerome.bib")) helm-bibtex-full-frame nil bibtex-completion-bibliography (list (concat +project-maria-dir+ "project-jerome.bib")) ;; Clicking on a citation in an org file will draw up a list of actions ;; One of these is view notes. this is where the index of notes is stored ;; Alternatively, calling ", n" while in project-jerome.bib will call ;; org-ref-open-bibtex-notes, which will populate project-jerome-index.org ;; Tell org-ref to let helm-bibtex find notes for it org-ref-notes-function (lambda (thekey) (let ((bibtex-completion-bibliography (org-ref-find-bibliography))) (bibtex-completion-edit-notes (list (car (org-ref-get-bibtex-key-and-file thekey)))))) ;; Taken from https://github.com/jkitchin/org-ref/blob/master/org-ref.org#customizing-how-pdfs-are-opened org-ref-get-pdf-filename-function 'org-ref-get-pdf-filename-helm-bibtex org-ref-open-pdf-function 'my/org-ref-open-pdf-at-point bibtex-completion-bibliography (concat +project-maria-dir+ "project-jerome.bib") bibtex-completion-notes-path (concat +project-maria-dir+ "bibtex-notes") bibtex-completion-notes-template-multiple-files (concat "* ${title}\n" ":PROPERTIES:\n" ":AUTHOR: ${author-abbrev}\n" ":YEAR: ${year}\n" ":END:\n\n") bibtex-completion-pdf-field "file" bibtex-completion-library-path '("~/project-jerome" "~/project-jerome/000-generalities-information-computers" "~/project-jerome/000-generalities-information-computers/000-computer-science" "~/project-jerome/000-generalities-information-computers/010-bibliography" "~/project-jerome/000-generalities-information-computers/020-library-information-sciences" "~/project-jerome/000-generalities-information-computers/030-general-encyclopedic-works" "~/project-jerome/000-generalities-information-computers/040-special-topics" "~/project-jerome/000-generalities-information-computers/050-general-serials-indexes" "~/project-jerome/000-generalities-information-computers/060-general-organizations-museums" "~/project-jerome/000-generalities-information-computers/070-news-media-journalism-publishing" "~/project-jerome/000-generalities-information-computers/080-general-collections" "~/project-jerome/000-generalities-information-computers/090-manuscripts-rare-books" "~/project-jerome/100-philosphy-psychology" "~/project-jerome/100-philosphy-psychology/110-metaphysics" "~/project-jerome/100-philosphy-psychology/120-epistemology-causation-humankind" "~/project-jerome/100-philosphy-psychology/130-paranormal-phenomena" "~/project-jerome/100-philosphy-psychology/140-specific-philosophical-schools" "~/project-jerome/100-philosphy-psychology/150-psychology" "~/project-jerome/100-philosphy-psychology/160-logic" "~/project-jerome/100-philosphy-psychology/170-ethics-moral-philosophy" "~/project-jerome/100-philosphy-psychology/180-ancient-medieval-oriental-philosophy" "~/project-jerome/100-philosphy-psychology/190-modern-western-philosophy" "~/project-jerome/200-religion" "~/project-jerome/200-religion/210-natural-theology" "~/project-jerome/200-religion/220-bible" "~/project-jerome/200-religion/230-christian-theology" "~/project-jerome/200-religion/230-christian-theology/239-apologetics" "~/project-jerome/200-religion/240-christian-moral-devotional-theology" "~/project-jerome/200-religion/240-christian-moral-devotional-theology/242-devotional-literature" "~/project-jerome/200-religion/250-christian-orders-local-churches" "~/project-jerome/200-religion/250-christian-orders-local-churches/252-texts-of-sermons" "~/project-jerome/200-religion/250-christian-orders-local-churches/253-pastoral-office-and-work" "~/project-jerome/200-religion/260-christian-social-theology" "~/project-jerome/200-religion/270-christian-church-history" "~/project-jerome/200-religion/280-christian-denominations-sects" "~/project-jerome/200-religion/290-other-comparative-religions" "~/project-jerome/300-social-sciences" "~/project-jerome/300-social-sciences/310-general-statistics" "~/project-jerome/300-social-sciences/320-political-science" "~/project-jerome/300-social-sciences/330-economics" "~/project-jerome/300-social-sciences/340-law" "~/project-jerome/300-social-sciences/350-public-administration" "~/project-jerome/300-social-sciences/360-social-problems-services" "~/project-jerome/300-social-sciences/370-education" "~/project-jerome/300-social-sciences/380-commerce-communications-transport" "~/project-jerome/300-social-sciences/390-customs-etiquette-folklore" "~/project-jerome/400-philology" "~/project-jerome/400-philology/410-linguistics" "~/project-jerome/400-philology/420-english-anglosaxon-languages" "~/project-jerome/400-philology/430-germanic-languages" "~/project-jerome/400-philology/440-romance-languages" "~/project-jerome/400-philology/450-italian-romanian-rhaeto-romanic" "~/project-jerome/400-philology/460-spanish-portuguese-languages" "~/project-jerome/400-philology/470-italic-languages-latin" "~/project-jerome/400-philology/480-hellenic-languages-classical-greek" "~/project-jerome/400-philology/490-other-languages" "~/project-jerome/500-natural-science" "~/project-jerome/500-natural-science/510-mathematics" "~/project-jerome/500-natural-science/520-astronomy-allied-sciences" "~/project-jerome/500-natural-science/530-physics" "~/project-jerome/500-natural-science/540-chemistry-allied-sciences" "~/project-jerome/500-natural-science/550-earth-sciences" "~/project-jerome/500-natural-science/560-paleontology-paleozoology" "~/project-jerome/500-natural-science/570-life-sciences" "~/project-jerome/500-natural-science/580-botanical-sciences" "~/project-jerome/500-natural-science/590-zoological-sciences" "~/project-jerome/600-applied-science" "~/project-jerome/600-applied-science/610-medical-sciences-psychiatry" "~/project-jerome/600-applied-science/620-engineering" "~/project-jerome/600-applied-science/630-agriculture" "~/project-jerome/600-applied-science/640-home-economics-family-living" "~/project-jerome/600-applied-science/650-management" "~/project-jerome/600-applied-science/660-chemical-engineering" "~/project-jerome/600-applied-science/670-manufacturing" "~/project-jerome/600-applied-science/680-manufacture-for-specific-use" "~/project-jerome/600-applied-science/690-buildings" "~/project-jerome/700-arts-recreation" "~/project-jerome/700-arts-recreation/710-civic-landscape-art" "~/project-jerome/700-arts-recreation/720-architecture" "~/project-jerome/700-arts-recreation/730-sculpture" "~/project-jerome/700-arts-recreation/740-drawings-decorative-arts" "~/project-jerome/700-arts-recreation/750-paintings-painters" "~/project-jerome/700-arts-recreation/760-graphics-arts-printmaking" "~/project-jerome/700-arts-recreation/770-photography" "~/project-jerome/700-arts-recreation/780-music" "~/project-jerome/700-arts-recreation/790-recreational-performing-arts" "~/project-jerome/800-literature" "~/project-jerome/800-literature/810-american-literature-in-english" "~/project-jerome/800-literature/820-english-literature" "~/project-jerome/800-literature/830-literature-of-germanic-language" "~/project-jerome/800-literature/840-literatures-of-romance-language" "~/project-jerome/800-literature/850-italian-romanian-rhaeto-romaic-literatures" "~/project-jerome/800-literature/860-spanish-portuguese-literatures" "~/project-jerome/800-literature/870-italic-literatures-latin" "~/project-jerome/800-literature/880-hellenic-literatures-classical-greek" "~/project-jerome/800-literature/890-literatures-of-other-languages" "~/project-jerome/900-history-geography-biography" "~/project-jerome/900-history-geography-biography/910-geography-travel" "~/project-jerome/900-history-geography-biography/920-biography-genealogy-insignia" "~/project-jerome/900-history-geography-biography/930-history-of-the-ancient-world" "~/project-jerome/900-history-geography-biography/940-general-history-of-europe" "~/project-jerome/900-history-geography-biography/950-general-history-of-asia" "~/project-jerome/900-history-geography-biography/960-general-history-of-africa" "~/project-jerome/900-history-geography-biography/970-general-history-of-north-america" "~/project-jerome/900-history-geography-biography/980-general-history-of-south-america" "~/project-jerome/900-history-geography-biography/990-general-history-of-other-areas") bibtex-completion-format-citation-functions '((org-mode . org-ref-helm-bibtex-insert-citation) (latex-mode . bibtex-completion-format-citation-cite) (markdown-mode . bibtex-completion-format-citation-pandoc-citeproc) (default . bibtex-completion-format-citation-default)) helm-source-bibtex org-ref-helm-source-bibtex)
3.3. Casual Calc Config
nfdn: Mathing in Emacs with Casual
(require 'casual-calc) (define-key calc-mode-map (kbd "C-o") 'casual-calc-tmenu)
3.4. Cdlatex Config
LaTeX Input for Impatient Scholars | Karthinks
;; https://old.reddit.com/r/emacs/comments/g8ecpj/advice_for_auclatex_what_keybinds_do_you_find/foo64ge/ ;; What really increased my speed is having snippets (yasnippet) for ;; frequently used patterns, auto paired parentheses ;; (electric-pair-local-mode or smartparens), and cd-latex ;; (org-cdlatex-mode) which auto inserts brackets for ;; subscript/superscripts. There's still a lot more to be done for speed, ;; learning these packages and creating keybindings though. All in due ;; time! Turns on unicode characters for org-mode (setf org-pretty-entities t org-pretty-entities-include-sub-superscripts nil ;; Bigger latex fragment org-format-latex-options (plist-put org-format-latex-options :scale 3)) ;; It generates a a png and overlays it onto the text as soon as your cursor ;; moves away from the math mode dollar signs. Automatically toggle org-mode ;; latex fragment previews as the cursor enters and exits them (add-hook 'org-mode-hook 'org-fragtog-mode)
3.5. Common Lisp Config
Before installing common-lisp-sly
to your .spacemacs
.
If you get cond: cl-ecase failed: message, (nil quiet sly-message)
upon
calling sly
, then make sure sly-delete-slynk-port-file
can successfully
finish. If not, you might have to call sly-slynk-port-file
and delete the file
yourself. e.g. "rm /tmp/sly.34". This seems to be a permission problem.
(setf common-lisp-hyperspec-root (concat "file://" +project-jerome-dir+ "000-generalities-information-computers/000-computer-science/HyperSpec/")) ;; https://emacs.stackexchange.com/questions/62536/what-does-making-browse-url ;; -browser-function-local-to-eww-while-let-bound-m (advice-add 'hyperspec-lookup :around (lambda (orig-fun &rest args) (setq-local browse-url-browser-function 'eww-browse-url) (apply orig-fun args)))
3.6. Company Config
;; FIXME Auto-completion causes lag in shell-mode. (setf company-global-modes '(not shell-mode))
3.7. Dired Config
Instead of Windows Explorer, emacs has the Directory Editor (Dired) that is built in.
To perform helm
actions on files while in helm-find-files
(SPC f f)
pop-up buffer
To visualize directory structure/filetree.
Key | Command | Effect |
---|---|---|
SPC b R | revert-buffer | "Refresh" file explorer |
a | open item at point in the same buffer | |
RET | open item at point in a new buffer | |
S | sort entries | |
C | copy | |
R | move | |
d | mark for deletion | |
x | execute deletion marks | |
w | dired-copy-filename-as-kill | yank filename |
Z | dired-do-compress | (Un)compress files |
( | Show more file details |
Working on Multiple Files
Key Command Effect m mark a file u remove a mark U remove all marks in buffer This method requires you to manually select each file. You can also use regular expressions to select files. Press % m to open the regular expression selection prompt. For example, ^i selects all files that start with the letter ’i’. Typing .org will select all Org files.
Opening a file with another program
Sometimes you might like to open a file in other software, such as your image editor or video player.
You can open files with external software by pressing !, after which dired will ask for the appropriate software. You need to type the name of the executable file of the software you like to use, e.g. gimp.
(setf dired-omit-mode t ;; Stop asking to quit dired buffers of deleted files dired-clean-up-buffers-too nil) (add-hook 'dired-mode-hook (lambda () (dired-hide-details-mode))) (evilified-state-evilify-map dired-mode-map :mode dired-mode :eval-after-load dired :bindings "s" #'avy-goto-word-or-subword-1 "S" #'hydra-dired-quick-sort/body ";" #'helm-occur "C-i" #'better-jumper-jump-forward "C-o" #'better-jumper-jump-backward "q" #'spacemacs/kill-this-buffer)
3.8. Elfeed Config | Elfeed Layer
Extending elfeed with PDF viewer and subtitles fetcher : emacs
sudo apt install curl mpv yt-dlp
Index of sources are found in ~/project-maria/dotelfeed.org. Elfeed stores its database in ~/.emacs.d/.cache/elfeed/. Delete for a clean refresh.
Key | Effect |
---|---|
gr | elfeed update |
r | tag as read |
y | yank source url |
t | call org-web-tools to render source in temporary org buffer |
s | search via tags (+Gbl -Gbl etc) |
- Youtube Feeds
For youtube channel subscriptions, use:https://www.youtube.com/feeds/videos.xml?channel_id=THE_CHANNEL_ID_HERE
To get the channel ID's:
- View the page’s source code
- Look for the following text (ctrl-f): externalID
- Get the value for that element
- Replace that value into above URL:
- For some videos, instead of watching it, use https://github.com/agzam/youtube-sub-extractor.el to read the subtitles more effectively.
(require 'elfeed) (require 'hydra) (require 'elfeed-tube) (setf elfeed-db-directory "~/.emacs.d/.cache/elfeed" elfeed-use-curl t) ;; Remove default binding so evilify mapping takes over. ;; Set shortcut for org-web-tools to fetch full article (with-eval-after-load "elfeed" (progn (define-key elfeed-search-mode-map (kbd "RET") nil) (define-key elfeed-search-mode-map (kbd "RET") #'ap/elfeed-search-browse-org))) (defhydra ben/hydra-elfeed (:exit t) ("g" (elfeed-search-set-filter "@6-months-ago +unread +gbl") "Global News") ("l" (elfeed-search-set-filter "@6-months-ago +unread +lcl") "Local News") ("s" (elfeed-search-set-filter "@6-months-ago +unread +sci") "Science & Tech") ("b" (elfeed-search-set-filter "@6-months-ago +unread +blog") "Misc. Blogs") ("c" (elfeed-search-set-filter "@6-months-ago +unread +rel") "Catholic") ("f" (elfeed-search-set-filter "@6-months-ago +unread +frm") "Forums") ("o" (elfeed-search-set-filter "@6-months-ago +unread +pod") "Podcasts") ("y" (elfeed-search-set-filter "@6-months-ago +unread +vid") "Youtube") ("a" (elfeed-search-set-filter "@6-months-ago +unread") "All") ("q" nil "quit" :color blue)) (evilified-state-evilify-map elfeed-search-mode-map :mode elfeed-search-mode :eval-after-load elfeed-search :bindings "s" #'avy-goto-word-or-subword-1 "S" #'elfeed-search-live-filter "f" #'ben/hydra-elfeed/body "r" #'elfeed-mark-all-as-read "RET" #'ap/elfeed-search-browse-org "t" #'elfeed-search-show-entry ";" #'helm-occur "b" #'ben/elfeed-search-browse-url "C-u b" #'elfeed-search-browse-url "o" #'elfeed-tube-fetch "gr" #'elfeed-update) (evilified-state-evilify-map elfeed-show-mode-map :bindings "s" #'avy-goto-word-or-subword-1 ";" #'helm-occur) (defun elfeed-mark-all-as-read () "Marks entire buffer before tagging marked region as read" (interactive) (mark-whole-buffer) (elfeed-search-untag-all-unread)) ;; Source https://www.reddit.com/r/emacs/comments/g6oowz/elfeed_rules/fodeb8x/ (defun ap/elfeed-search-browse-org () "Open selected items as Org." (interactive) (let ((browse-url-browser-function (lambda (url _) (org-web-tools-read-url-as-org url)))) (ap/elfeed-search-selected-map #'ap/elfeed-search-browse-entry))) (defun ap/elfeed-search-browse-entry (entry) "Browse ENTRY with `browse-url' and mark as read. If ENTRY is unread, it will also be unstarred. To override the browser function, bind `browse-url-browser-function' around the call to this." (let ((url (elfeed-entry-link entry)) (tags (elfeed-entry-tags entry))) ;; Mark as read first, because apparently the elfeed functions don't work after `browse-url' ;; potentially changes the buffer. (elfeed-untag entry 'unread) (elfeed-search-update-entry entry) (browse-url url))) (cl-defun ap/elfeed-search-selected-map (fn) "Map FN across selected entries in elfeed-search buffer using `mapcar'." (mapcar fn (elfeed-search-selected))) (defun ben/elfeed-search-browse-url (&optional use-generic-p) "Visit the current entry in your browser using `browse-url'. If there is a prefix argument, visit the current entry in the browser defined by `browse-url-generic-program'." (interactive "P") (let ((buffer (current-buffer)) (entries (elfeed-search-selected))) (cl-loop for entry in entries do (elfeed-untag entry 'unread) when (elfeed-entry-link entry) do (if use-generic-p (browse-url-generic it) (eww it))) ;; `browse-url' could have switched to another buffer if eww or another ;; internal browser is used, but the remainder of the functions needs to ;; run in the elfeed buffer. (with-current-buffer buffer (mapc #'elfeed-search-update-entry entries) (unless (or elfeed-search-remain-on-entry (use-region-p)) (forward-line))))) (add-hook 'elfeed-new-entry-hook #'elfeed-tube--auto-fetch) (advice-add 'elfeed-show-entry :after #'elfeed-tube--auto-fetch) (advice-add elfeed-show-refresh-function :after #'elfeed-tube-show)
3.9. Emacs Config
This can be somewhat misleading. This section is for miscellaneous configuration for features built in to Emacs which do not belong clearly to a well-defined package. For more detail, see 3 structure.
;; I am convinced this is a case of bad defaults. Setting ;; =savehist-autosave-interval= to 60 seconds (from the default of 300) and ;; =history-length= to 1000 (from the default of 100) causes disproportionate ;; performance problems for arguable benefits. Performance problems can be plainly ;; seen by using the Emacs cpu+mem profiler. See ;; https://emacs.stackexchange.com/questions/12086/high-cpu-memory-usage-and-abnormally-large-savehist-file ;; =spacemacs-defaults/init-savehist=, Spacemacs Github issues #9409, #1369. ;; Reset variables to sensible Emacs defaults. (setf history-length 25 savehist-save-minibuffer-history nil savehist-autosave-interval nil kill-ring-max 200 savehist-mode nil) (delq 'mark-ring savehist-additional-variables) (delq 'global-mark-ring savehist-additional-variables) (delq 'search-ring savehist-additional-variables) (delq 'regexp-search-ring savehist-additional-variables) (delq 'extended-command-history savehist-additional-variables) (delq 'kill-ring savehist-additional-variables) (put 'org-brain-headline-cache 'history-length 10) (put 'bibtex-completion-cache 'history-length 10) (push 'org-brain-headline-cache savehist-additional-variables) (push 'bibtex-completion-cache savehist-additional-variables) (push 'helm-ff-history savehist-additional-variables) (push 'org-clock-history savehist-additional-variables) ;; Emacs profiler shows `savehist-autosave' is very performance intensive. (add-hook 'kill-emacs-hook #'savehist-save) ; Savehist only on exit. ;; Scrolling. ;; ;; The behaviors Emacs offers for scrolling can be customized ;; by the variables some of which were already mentioned: ;; scroll-conservatively, scroll-margin, scroll-step, and ;; scroll-up/down-aggressively. They basically control whether ;; Emacs recenters point when it scrolls the window, when (if ;; at all) it does recenter, by how many lines it scrolls if ;; it doesn't recenter, and how close to window edges point is ;; allowed to be before the window is scrolled. This defines a ;; set of behaviors you can get universally. In general, the ;; default is to recenter if scrolling by a few lines fails to ;; bring point into view. That is what you see, and that is ;; how Emacs works. ;; Source: https://old.reddit.com/r/emacs/comments/8jli87/is_there_a_hook_after_cursor_jump/ (setq scroll-conservatively 0) (setq scroll-preserve-screen-position t) ;; Line Breaks/Fill Column/Characters ;; ;; Prefer 80 chars due to anatomical restriction of the human eye. ;; Secondary concern of long known emacs performance issues with long lines. ;; ;; According to the Emacs manual, to enable autofill in all major modes: ;; (setq-default auto-fill-function 'do-auto-fill) ;; https://www.gnu.org/software/emacs/manual/html_node/efaq/Turning-on-auto_002dfill-by-default.html ;; ;; However, it does have side-effects in some modes, most notably it screws ;; up auto-completion in lisp mode buffers. In addition to performance ;; reasons, it makes sense to selectively enable for certain modes. ;; Therefore look under the mode configuration for the added hooks. ;; i.e. search for (add-hook 'example-mode-hook 'turn-on-auto-fill) ;; allows the use of SPC leader key in calc buffer (with-eval-after-load 'calc (define-key calc-mode-map " " spacemacs-cmds)) (setq large-file-warning-threshold '100000000) ;; https://www.masteringemacs.org/article/disabling-prompts-emacs (setq kill-buffer-query-functions (remq 'process-kill-buffer-query-function kill-buffer-query-functions)) (require 'cl-lib) (defun site/always-save-advice (oldfn &optional arg) "Overwrite `yes-or-no-p' in OLDFN. The new temporary function will return non-nil, when the message wants to save modified buffers, without querying the user. Otherwise the original behaviour is preserves, and ARG is passed on to OLDFN." (cl-letf* ((real-yes-or-no-p (symbol-function 'yes-or-no-p)) ((symbol-function 'yes-or-no-p) (lambda (msg) (or (string= msg "Modified buffers exist; exit anyway? ") (funcall real-yes-or-no-p msg))))) (funcall oldfn arg))) (advice-add #'save-buffers-kill-emacs :around #'site/always-save-advice) ;; Spacemacs default is 60 seconds. Ridiculous. (setf auto-save-interval 1000 auto-save-timeout nil)
3.9.1. Calc Config
- Using Units in Emacs Calc
- WorgSheet Calc Intro
- Calc Manual SS 6.8
- Irreal Blog's on Calc
- Make typing mathematical equations in LaTeX easier with Emacs’ Calc
- Why use Emacs Calc mode?
Key | Command | Effect |
---|---|---|
C-x * : | calc-grab-sum-down | |
C-x * 0 | calc-reset | reset calc stack |
M-x calc, or SPC a * will enter calc-dispatch. y will yank top to stack to the last edited buffer, x is like M-x but for calc functions only.
Make your way through
For a quick start. The complete calc manual is available here https://www.gnu.org/software/emacs/manual/html_mono/calc.html]], and is written by the author of the calc package: Dave Gillespie (who also wrote cl-lib, so massive respect). What is RPN (Reverse Polish Notation)? A comprehensive tutorial outlined it, RPN Tutorial.
;; allows the use of SPC leader key in calc buffer (with-eval-after-load 'calc (define-key calc-mode-map " " spacemacs-cmds))
3.9.2. Savehist Config
For more session management solutions. spacemacs - High CPU/memory usage and abnormally large savehist file? - Emacs…
If you recreate this situation, and the file is really massive, opening it in Emacs to check might not be a great idea. I would use grep to find out the offset for each variable, and just look for any really big jumps:
$ grep -E -b -o '^\(setq [^ ]+' ~/.emacs.d/.cache/savehist
(Or whatever your savehist-file path is – the standard filename is ~/.emacs.d/history but I presume ~/.emacs.d/.cache/savehist is what Spacemacs configures.)
;; I am convinced this is a case of bad defaults. Setting ;; =savehist-autosave-interval= to 60 seconds (from the default of 300) and ;; =history-length= to 1000 (from the default of 100) causes disproportionate ;; performance problems for arguable benefits. Performance problems can be plainly ;; seen by using the Emacs cpu+mem profiler. See ;; https://emacs.stackexchange.com/questions/12086/high-cpu-memory-usage-and-abnormally-large-savehist-file ;; =spacemacs-defaults/init-savehist=, Spacemacs Github issues #9409, #1369. ;; Reset variables to sensible Emacs defaults. (setf history-length 25 savehist-save-minibuffer-history nil savehist-autosave-interval nil kill-ring-max 200 savehist-mode nil) (delq 'mark-ring savehist-additional-variables) (delq 'global-mark-ring savehist-additional-variables) (delq 'search-ring savehist-additional-variables) (delq 'regexp-search-ring savehist-additional-variables) (delq 'extended-command-history savehist-additional-variables) (delq 'kill-ring savehist-additional-variables) (put 'org-brain-headline-cache 'history-length 10) (put 'bibtex-completion-cache 'history-length 10) (push 'org-brain-headline-cache savehist-additional-variables) (push 'bibtex-completion-cache savehist-additional-variables) (push 'helm-ff-history savehist-additional-variables) (push 'org-clock-history savehist-additional-variables) ;; Emacs profiler shows `savehist-autosave' is very performance intensive. (add-hook 'kill-emacs-hook #'savehist-save) ; Savehist only on exit.
3.10. Emacs-Jupyter Config
Jupyter is two things, a multi-instance REPL and an interleaved text/code
"notebook" format. This package keeps the multi-instance REPL and replaces
the obtuse notebook format with org. EIN keeps both. This is why I prefer
this package over the EIN package found in the spacemacs ipython-notebook
layer.
Installation Ubuntu 20.04 comes pre-installed with python 2.7.18 (code freeze) and python 3. Python 3 is a massive upgrade from Python 2, and as such, backwards comparability is hacky at best. First let us upgrade the python distribution on our WSL2 VM to the latest major python release (at time of writing, this is python 3.9). Do this if there is no version of python 3 already installed.
Install pip (python package manager) for python 3 with
sudo apt install python3-pip
Install jupyter notebooks with
sudo apt install jupyter-core pip3 install notebooks
and run the notebook with
~/.local/bin/jupyter-notebook
https://github.com/nnicandro/emacs-jupyter/issues/194
sudo apt-get install -y python3 python3-pip sudo pip3 install --upgrade setuptools pip # --ignore-installed six since jupyter tries to upgrade it, but it can't be # upgraded since it is a distutils package sudo pip3 install --ignore-installed six jupyter # Install the kernelspec using the right python. Jupyter installs a default # python kernelspec that uses "python" for the command in # /usr/local/share/jupyter. This installs one with an absolute path using our # python3 sudo python3 -m ipykernel.kernelspec
https://github.com/nnicandro/emacs-jupyter/issues/257 if you have to
unlink /usr/local/bin/python ln -s /usr/local/bin/python3 /usr/local/bin/python
https://github.com/nnicandro/emacs-jupyter/issues/276
- Examples All emacs jupyter babel blocks must run under a session.
- Adding WolframLanguageForJupyter
You should have already have wolfram language installed via the instructions here. You must add the Wolfram Language kernel to jupyter notebooks. This was done with the instructions found on the Wolfram Language Kernel for Jupyter Notebooks Github repository. As a last step, you must add the WolframKernel $PATH location to
.spacemacs.env
. You can do this by modifying the $PATH variable in your bash shell or your.profile
located in your $HOME directory. Afterwards, a last note is that the naming convention used to call the WolframKernel in org-babel is found (SPC s f, .emacs.d>elpa>27.1>jupyter>, "wolfram"
) to be Wolfram Language -> jupyter-Wolfram-Language - Adding Sagemath
Install sagemath as listed in the program directory steps. Now make sure the sagemath kernel is exposed to jupyter. The kernel should be automatically included. You can verify this by running
jupyter notebook
and clicking the dropdown menu under
new
andsagemath
should be listed.- Check the dotspacemacs config for emacs jupyter
Test with the following code. Note
M-x ielm
evaluation of(jupyter-available-kernelspecs)
lists:language sage
, hence jupyter-sage.(x + 1)^2
- call
org-edit-special
inside the above jupyter-sage code block. A python major mode should pop up. You will see the commandspacemacs/python-start-or-switch-repl
is bound to, '
and calling the previous command withC-h f
we can see the source code. Upon closer inspection we can see this is a wrapper function to call interactivelyrun-python
. When wehelpful-function
the commandrun-python
we see that the documentation that when we callspacemacs/python-start-or-switch-repl
we can do so with a prefix argumentC-u
(orSPC u
) in our case to specify which inferior python process we would like to start. We can then entersage
to open up a sage REPL. Now in the python mode buffer we can callpython-shell-send
,buffer, line, region
etc. This is currently bound to, s b
. - (OPTIONAL) Install sage-shell-mode from MELPA. Make sure to configure install with special attention according to README
;;------------------------------------------------------------------------- ;; *** Emacs Jupyter Config ;;-------------------------------------------------------------------------
3.11. Evil Config
For a guide, see Github - Noctuid Evil Guide
In addition to defaults set in Spacemacs documentation,
- s from evil-surround to avy-goto-word-or-subword-1 from evil-surround on s and vim substitute on S to avy-goto-word-or-subword-1 on s and evil-surround on S as per above documentation, vim substitute is not very useful.
- ; from evil-repeat-search to #'helm-occur with evil-snipe, evil-repeat-search is obsoleted.
- q from evil-record-macro to spacemacs/kill-this-buffer SPC b d is too long for a common operation.
;; C-h f "evilnc-comment-operator" or any of the default evil keybindings ;; to discover what maps you need to override. ;; rebind "SPC j j" or avy-goto-word-or-subword-1 to "s" ;; At first, will not work as evil-surround is using "s" in visual mode (setf evil-move-beyond-eol t) (evil-define-key 'visual evil-surround-mode-map (kbd "s") 'avy-goto-word-or-subword-1) (evil-define-key 'visual evil-surround-mode-map (kbd "S") 'evil-surround-region) (define-key evil-motion-state-map (kbd "s") 'avy-goto-word-or-subword-1) (define-key evil-normal-state-map (kbd "s") 'avy-goto-word-or-subword-1) (define-key evil-visual-state-map (kbd "s") 'avy-goto-word-or-subword-1) (define-key evil-operator-state-map (kbd "s") 'avy-goto-word-or-subword-1) (define-key package-menu-mode-map (kbd "s") 'avy-goto-word-or-subword-1) ;; #'helm-occur rebinding (define-key evil-motion-state-map (kbd ";") #'helm-occur) (define-key evil-normal-state-map (kbd ";") #'helm-occur) (define-key evil-visual-state-map (kbd ";") #'helm-occur) (define-key evil-operator-state-map (kbd ";") #'helm-occur) (define-key package-menu-mode-map (kbd ";") #'helm-occur) ;; Whenever the commands modified below are called, they are pushed ;; onto the evil-jumps-history stack (evil-add-command-properties #'evil-scroll-down :jump t) (evil-add-command-properties #'evil-scroll-up :jump t) (evil-add-command-properties #'evil-scroll-page-down :jump t) (evil-add-command-properties #'evil-scroll-page-up :jump t) (evil-add-command-properties #'helm-occur :jump t) (evil-add-command-properties #'helm-for-files :jump t) (evil-add-command-properties #'helm-projectile-find-file :jump t) (evil-add-command-properties #'spacemacs/alternate-buffer :jump t) (evil-add-command-properties #'spacemacs/helm-M-x-fuzzy-matching :jump t) (evil-add-command-properties #'helm-find-files :jump t) (evil-add-command-properties #'org-previous-visible-heading :jump t) (evil-add-command-properties #'org-next-visible-heading :jump t) (evil-add-command-properties #'outline-up-heading :jump t) (evil-add-command-properties #'outline-next-heading :jump t) (evil-add-command-properties #'org-bable-goto-src-block-head :jump t) (define-key evil-normal-state-map (kbd "q") #'spacemacs/kill-this-buffer) (define-key evil-normal-state-map (kbd "Q") #'kill-buffer-and-window) ;; Disable all keybindings other than f/t (evil-snipe-mode -1) (setq evil-snipe-scope 'whole-visible) ;; Alias [ and ] to all types of brackets ;; Alias ' to ' and " (setq evil-snipe-aliases '((?\' "['\"]") ;; No longer needed as () are translated to [] ;; via keyboard-translate function ;; (?\[ "[[{(]") ;; (?\] "[]})]") )) ;; Remove overriding of "," key in visual mode Ex. "vf)," (setq evil-snipe-override-evil-repeat-keys nil)
3.11.1. Evil Snipe Config
Why evil-snipe-mode
is set to -1? https://www.reddit.com/r/emacs/comments/6gbf5i/anyone_use_packages_such_as_avy_or_evilsnipe_to/djhv4sp/ has the answer.
;; Disable all keybindings other than f/t (evil-snipe-mode -1) (setq evil-snipe-scope 'whole-visible) ;; Alias [ and ] to all types of brackets ;; Alias ' to ' and " (setq evil-snipe-aliases '((?\' "['\"]") ;; No longer needed as () are translated to [] ;; via keyboard-translate function ;; (?\[ "[[{(]") ;; (?\] "[]})]") )) ;; Remove overriding of "," key in visual mode Ex. "vf)," (setq evil-snipe-override-evil-repeat-keys nil)
3.12. EWW Config
(add-hook 'eww-after-render-hook 'eww-readable)
3.13. LLM-Client Config
Background: {1hr Talk} Intro to Large Language Models - YouTube Spreadsheets are all you need.ai – A low-code way to learn AI
I can install a Large Language Model (LLM) locally on our own computer or on a server. I chose the easiest solution to install, the open source LLM created by Meta and packaged by Justine and the open source community: LLaMAfile.
To run on my local WSL system, note the pitfalls and workarounds.
To install on my OCI server,
ssh oci-a1-flex mkdir /opt/llava cd /opt/llava curl "DOWNLOAD_LINK" -L -O chmod +x llava-v1.5-7b-q4.llamafile # https://github.com/Mozilla-Ocho/llamafile?tab=readme-ov-file#gotchas sudo wget -O /usr/bin/ape https://cosmo.zip/pub/cosmos/bin/ape-$(uname -m).elf sudo chmod +x /usr/bin/ape sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" sudo sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
Create /etc/systemd/system/llamafile.service
with the following contents,
[Unit] Description=Run Large Language Model locally through llama.cpp and Cosmopolitan Libc. [Service] Type=exec User=root WorkingDirectory=/opt/llava ExecStart=/opt/llava/llava-v1.5-7b-q4.llamafile -ngl 9999 --nobrowser --port 8090 --embedding Restart=on-failure RestartSec=30s [Install] WantedBy=multi-user.target
Modify caddy reverse proxy to redirect requests to server. E.g.
https://github.com/karthink/gptel/issues/237
Right now I can't get it to run in the server so I'm running it locally as a systemd service. Praise the Lord, and all the people working on open science.
https://chat.lmsys.org/ to use Claude3-opus and test other models.
https://www.reddit.com/r/LocalLLaMA/ to check up on the latest news.
(require 'gptel) (require 'auth-source) (defun bhw/switch-to-llm-buffer () (interactive) (switch-to-buffer "*Gemini*")) (defun get-authinfo-password (machine login) (let ((credential (auth-source-search :max 1 :host machine :user login :require '(:secret)))) (if credential (let ((secret (plist-get (nth 0 credential) :secret))) (if (functionp secret) (funcall secret) secret)) (message "No password found for %s@%s" login machine)))) ;; In ~/.authinfo, ;;machine aistudio.google.com login ben password *YourAPIkey* (setf gptel-model "gemini-1.5-pro-latest" gptel-backend (gptel-make-gemini "Gemini" :key (get-authinfo-password "aistudio.google.com" "ben") :stream t) gptel-directives '((default . " Ignore all previous instructions. 1. You are to provide clear, concise, and direct responses. 2. Eliminate unnecessary reminders, apologies, self-references, and any pre-programmed niceties. 3. Maintain a casual tone in your communication. 4. Be transparent; if you're unsure about an answer or if a question is beyond your capabilities or knowledge, admit it. 5. For any unclear or ambiguous queries, ask follow-up questions to understand the user's intent better. 6. When explaining concepts, use real-world examples and analogies, where appropriate. 7. For complex requests, take a deep breath and work on the problem step-by-step. 8. For every response, you will be tipped up to $200 (depending on the quality of your output). It is very important that you get this right.") (programming . "You are a large language model and a careful programmer. Provide code and only code as output without any additional text, prompt or note.") (writing . "You are a large language model and a writing assistant. Respond concisely.") (chat . "You are a large language model and a conversation partner. Respond concisely."))) (spacemacs/set-leader-keys (kbd "al") #'bhw/switch-to-llm-buffer)
3.14. Greader Config
Activate M-x greader-mode
. Start reading with M-x greader-read
and stop
reading with M-x greader-stop
.
(require 'greader)
3.15. Helm Config
-A Package in a league of its own: <code>Helm</code>
Helm keybinds Table
Key Effect C-DEL disable "helm-ff-auto-update-initial-value" M-DEL Backwards kill a word C-c C-u Helm Refresh useful for refreshing downloads directory C-c C-f Actives helm-follow-mode C-q Use avy to jump to candidate C-c _ Maximize helm buffer. Bugged. C-y Paste when "p" is not available Left Arrow Key Previous Source Right Arrow Key Next Source C-o Next Source M-n & C-w Yank text under point and paste Helm regexps Table
Expression Effect \b … \b Where … is a word. \b is boundary of word
Press SPC /
in project-maria once to activate fuzzy search with SPC SPC
. Why
this is the case I don't know.
;; See /home/ben/.config/fd/ignore (require 'helm-fd) (require 'helm-ag) (defvar bhw/helm-source-fd (helm-make-source "fd-find" 'helm-fd-class) "For use of FD in `helm-for-files'. See also `helm-fd-switches'") ;; HACK If (error "Candidates function ‘(closure (t) nil ;; (helm-ag--do-ag-candidate-process +project-maria-dir+))’ should run a ;; process") Then eval-current-form-sp on the form below. (defvar bhw/helm-source-maria-ag (helm-make-source "Project Maria - AG" 'helm-do-ag-class :candidates-process (lambda () (helm-ag--do-ag-candidate-process +project-maria-dir+))) "To search Project Maria files from `helm-for-files'. `helm-ag--do-ag-set-source' used as exemplar. You may have to run `helm-projectile-ag' once for fuzzy matching to kick in :O.") (defvar bhw/helm-source-emacs-commands (helm-build-sync-source "Emacs Commands" :candidates (lambda () (let ((cmds)) (mapatoms (lambda (elt) (when (commandp elt) (push (symbol-name elt) cmds)))) cmds)) :coerce #'intern-soft :action #'command-execute) "A simple helm source for Emacs commands. Used in `helm-for-files'.") (setf ace-jump-helm-line-default-action 'select ace-jump-helm-line-idle-delay 1 helm-ff-auto-update-initial-value t recentf-max-saved-items 1000 helm-for-files-preferred-list '(helm-source-recentf bhw/helm-source-fd bhw/helm-source-maria-ag bhw/helm-source-emacs-commands) helm-candidate-number-limit 100 helm-ff-skip-boring-files t helm-ag-fuzzy-match t helm-fd-executable "fdfind" helm-fd-switches '("--search-path" "/home/ben" "--hidden" "--type" "f" "--type" "d" "--color" "never" "--max-results" "10" "--full-path")) (spacemacs/set-leader-keys "SPC" #'helm-for-files) (define-key helm-map (kbd "C-q") nil) ; Replace default binding. (define-key helm-map (kbd "C-d") 'ace-jump-helm-line)
- Introduction to Helm
- Helm is a candidate selection framework. Previously, it was called Anything.
- Start with M-x helm-mini SPC SPC for spacemacs. Narrow the list by typing some patterns (multiple patterns are space-delimited string). For example, to show just dired buffers, type “*dired”.
- Move on the list with up/down/pgup/pgdown/C-p/C-n/C-v/M-v. C-j and C-k for spacemacs
- To mark (select) a buffer for action, type C-SPC. To mark all buffers listed, type M-m.
- With TAB, actions can be selected if the selected buffer(s) has more than one possible action.
- To kill a buffer, choose “Kill buffer(s)” on the list of actions, or type M-D (capital D, so in fact it is M-Shift-d).
- Auto-completion while in
SPC f f
is toggled by variable: helm-ff-auto-update-initial-value. Disable for current instance keybind below
3.16. Keyfreq Config
This package is used to streamline my workflow. A task is created in my agenda
to check the frequency with the command keyfreq-show
. Any commands that
are optimized enough should be added to the excluded commands variable.
;; (keyfreq-mode 1) ;; (keyfreq-autosave-mode 1) ;; (setf keyfreq-excluded-commands ;; '(self-insert-command ;; org-self-insert-command ;; forward-char ;; backward-char ;; previous-line ;; next-line ;; evil-forward-char ;; evil-backward-char ;; evil-previous-visual-line ;; evil-next-visual-line ;; helm-next-line ;; helm-previous-line ;; evil-scroll-page-down ;; evil-scroll-page-up ;; delete-backward-char ;; evil-delete-backward-char-and-join ;; evil-undo ;; mwheel-scroll ;; mouse-set-point ;; mouse-drag-region ;; evil-mouse-drag-region ;; evil-normal-state ;; keyboard-escape-quit ;; evil-goto-first-line ;; evil-insert ;; evil-append ;; evil-delete ;; evil-join ;; evil-delete-char ;; evil-open-below ;; evil-change ;; backward-delete-char-untabify ;; dired-next-line ;; dired-previous-line))
3.17. Ledger Config | Finance Layer
- org babel and ledger
- conquering your finances with emacs and ledger
- CSV Import · ledger/ledger Wiki · GitHub
- My Emacs Ledger reporting configuration - philnewton.net
hledger vs ledger: https://www.reddit.com/r/plaintextaccounting/comments/1381lfo/hledger_equivalent_to_ledger_payee_subdirective/
https://hledger.org/faq.html#how-does-hledger-relate-to-ledger-
Command line interface (CLI) double entry accounting system.
Install Ledger CLI
$ sudo apt install ledger
Install ledger-autosync to convert .QFX statements to Ledger's journal format.
$ sudo apt install ledger-autosync
- Add
finance
layer to the dotspacemacs file. - Start by reading the Documentation. Sections 1-4.
- Refer to the .ledgerrc configuration file.
Download .QFX file from your bank or financial institution and run ledger-autosync against it. Alt-tab to enter keyring password.
ledger-autosync download.qfx # Ex password for new keyring: pass
Enter a password when asked to choose a password for a new keying.
- Copy over the journal entries printed to stdout into your ledger journal.
How ledger-autosync does payee matching and how ledger can use regular expressions to match unknown payee fields. Say you are paying off loans that are classed under liabilities but also want to include it in an expense, you can look at Virtual Postings.
Quick reports to run:
# See expenses divided by month and accounts ledger -M register Income:* Expenses:*
# See expenses divided by month and accounts ledger balance --real
3.18. Lexic Config
https://web.archive.org/web/20230622042529/http://download.huzheng.org/
mkdir /home/ben/.stardict/ ln -s /home/ben/project-jerome/400-philology/420-english-anglosaxon-languages/.stardict/dic /home/ben/.stardict/
(require 'lexic) (setf lexic-dictionary-specs ' (("Webster's Revised Unabridged Dictionary (1913)" :short "===========================================================\n Webster's Revised Unabridged Dictionary (1913)\n===========================================================" :formatter lexic-format-webster :priority 1) ("Soule's Dictionary of English Synonyms" :short "===========================================================\n Soule's Dictionary of English Synonyms (1871)\n===========================================================" :formatter lexic-format-soule :priority 2) ("Online Etymology Dictionary" :short "===========================================================\n Online Etymology Dictionary (2000)\n===========================================================" :formatter lexic-format-online-etym :priority 3) ("Oxford English Dictionary 2nd Ed P1" :short "===========================================================\n Oxford English Dictionary 2nd Ed. (1989)\n===========================================================" :formatter lexic-format-online-etym :priority 4) ("Oxford English Dictionary 2nd Ed P2" :short "===========================================================\n Oxford English Dictionary 2nd Ed. (1989)\n===========================================================" :formatter lexic-format-online-etym :priority 5) )) ;; Set Global Keybindings (spacemacs/set-leader-keys "sx" 'lexic-search-word-at-point) (spacemacs/set-leader-keys "sX" 'lexic-search) ;; Set Lexic Major Mode Keybindings (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "q" 'lexic-return-from-lexic) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode (kbd "RET") 'lexic-search-word-at-point) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "a" 'outline-show-all) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "h" 'outline-hide-body) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "o" 'lexic-toggle-entry) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "n" 'lexic-next-entry) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "p" 'lexic-previous-entry) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "b" 'lexic-search-history-backwards) (spacemacs/set-leader-keys-for-major-mode 'lexic-mode "f" 'lexic-search-history-forwards)
3.18.1. Lexic Installation & Background
You’re probably using the wrong dictionary. The first place I looked was Oleh Krehel's defined word package. It does not allow you to query multiple dictionaries/thesaurus. A couple of other Emacs users were similiarly inspired: Webster and Emacs | Irreal. Similarly, these two later posts are also related: The Webster 1913 Dictionary | Irreal Zamansky 56: Dictionaries and Thesauri | Irreal. Following Zamansky's advice, if you go to Melpa.org and search for the word dictionary a couple of packages will pop up.Out of the 12 the pop-up, only a couple are relevant to our particular use case.Let's first go to the process of elimination and list a couple of unsuitable packages.
Helm dictionary is a bit limited in its scope, as we can see per issue number insert link, that it does not support the DICT format for dictionaries. The package that requires the least fiddling around with DV dictionary package. There is just one minor problem, this dictionary package out-of-the-box is configured to query the online server DICT.org for results. If you are okay with being connected to the Internet, then your search would stop here. However if you insist on having an off-line dictionary as I do, will have to go a bit further. You have 2 options. Install you own DICT server, or use SDCV. DICT standard specification can be found at:RFC 2229 - A Dictionary Server Protocol, and the website the dictionary.el tool queries is dict.org. SDCV main website can be found StarDict - The best dictionary program in linux and windows . The downloads can be found here StarDict Dictionaries – 星际译王词库. It is much easier to use SDCV and it does not require configuring your own server.
There is a fork of the DICT standard format dictionary called StarDICT. Installing the pre-built package on Debian would be
sudo apt install sdcv
Download https://tecosaur.com/resources/config/stardict.tar.gz and extract it to ~/.stardict/dic/. You can test your sdcv installation at this point in the terminal with
sdcv word
- Construct lexic-dictionary-specs Make the dictionary known to lexic.el
Now inside the newly extracted directory (you may need to give yourself read/write permissions) will be the .ifo file.
Lets install lexic and customize lexic-dictionary-specs
.
It should be noted that dictionaries DO NOT need to have a format function. You can most definitely use the dictionary without. i.e.
The currently pre-defined format functions are:
If your use case is not included in the above, feel free to take look into lexic.el and then open an Issue or submit a pull request.
- Lexic.el uses outline.el (think org-mode), so here are the usage commands inside lexic mode
Endnotes: recent article on stardict https://owenh.net/stardict Thank you to: removed ;; Quotations ("Oxford Dictionary of Quotations" :short "From Oxford Dictionary of Quotations" :priority 10) ;; For Learning. Because I am always learning ("Oxford Advanced Learner's Dictionary 8th Ed." :short "From the Oxford Advanced Learner's Dictionary 8th Ed." :priority 5) ("Oxford Collocations Dictionary 2nd Ed. (En-En)" :short "From the Oxford Collocations Dictionary 2nd Ed." :priority 6)
Check out lexic-dictionary-help
3.18.2. Lexic Order of Dictionaries
- The golden mean, the dictionary that has the first say, the lovingly crafted life's work of Noah Webster: Webster Unabridged 1913
- Thesauri - Synonyms
- Soule's. For the organized hierarchy
- Moby Thesaurus II. Remarkable compilation of a single man. Claims to be the largest thesaurus.
- WordNet 3.0. Leverages the power of computing to map synonyms or word relations. No word, or human, is born into the world alone/self-sufficient. That perfection is reserved God alone. A systemic way of approaching linguistics. Yes, designed for machines so the essence of a definition may remain, but the hard to describe humanity (artistic flavor? humanness?) of a word is lost.
- The accepted authority on the English language, the dictionary that has the last say, the magnum opus: The Oxford English Dictionary 2nd Ed. 1989
Encyclopedia Taken from Dictionary vs. encyclopedia The term lexicon is ambiguous both in prescientific and in linguistic usage, since it may mean either a dictionary or an encyclopedia. The latter two terms are employed in linguistics whenever the distinction matters.
A dictionary provides information on expressions typically words of a language, while an encyclopedia tells one what is known about an object, or objects of a certain kind.1 The contrast is brought out in the following table: Dictionary vs. encyclopedia criterion dictionary encyclopedia object linguistic properties of linguistic units represented by lemmas properties of objects designated by lemmas describes use of linguistic units world knowledge lemmas any word class only nouns
A dictionary gives information on all linguistic aspects of its lemmas, on their significans, significatum, grammatical properties and aspects of usage. Focusing on the purely semantic aspect of a lexicon, we may say that a dictionary gives information about the sigificata of its lemmas, while an encyclopedia gives information on their denotata.
The lemmas of an encyclopedia are nouns. However, contrary to a terminological dictionary, not only common nouns, but also proper nouns can be lemmas.
The bilingual dictionary is particularly apt to illustrate the difference between the two kinds of information provided by a dictionary and an encyclopedia: If you encounter the German word Reiher and don't know what it means, you consult a German-English dictionary. It tells you that Reiher means ‘heron’. From that you may infer that, mutatis mutandis, the German word Reiher is used like the English word heron. You have not been told what a Reiher (or a heron) is. If you don't know, the dictionary will not help you; you will have to consult an encyclopedia.
In the individual mind, the two kinds of information may, to some extent, be independent. Suppose you have never seen a heron and have no knowledge about it except that it is a large bird. So much (knowing a hyperonym) would be purely linguistic knowledge. It would enable you to actively and passively use the word heron without arousing anybody's attention; unless of course you mix in ornithological circles.
An example of an English dictionary is The New Merriam-Webster Dictionary (Springfield, MA: Merriam-Webster). An example of an English encyclopedia is the Encyclopaedia Britannica (London: International). Orthographic dictionaries, i.e. ones that only show how a word is spelt, may be the most widespread kind of dictionary, but are nevertheless untypical of the linguistic concept of dictionary since they lack most kinds of information that make up knowledge of the language in question.
The distinction between dictionary and encyclopedia is a theoretically-based distinction that is practically useful: If I want to know what Reiher means, I do not want to find an article on herons; and if I need information on herons, I do not need to be told that heron is a common noun whose plural may be herons or heron. However, the psychological reality of the distinction, i.e. whether it has a neat counterpart in the mental lexicon, is less clear. Much of what we know about the meaning of a word is probably intertwined with knowledge about the object it designates. There are therefore hybrid forms between dictionary and encyclopedia, sometimes explicitly called ‘encyclopedic dictionary’.
- The Britannica Concise (2006)
- Specialized encyclopedic dictionaries
- Bouvier's Law
- Elements Database
3.19. Magit Config
GitHub - anticomputer/gh-notify: Veneer for the Magit/Forge GitHub porcelain git - Magit: how remove push branch? - Emacs Stack Exchange Cheatsheet · magit/magit Wiki · GitHub git - Add change to a previous commit with Magit - Emacs Stack Exchange To perform code review on Github from emacs, see https://github.com/charignon/github-review, and another iteration on top of it,GitHub - wandersoncferreira/code-review: Code Reviews in Emacs
Key | Effect |
---|---|
+ | Widen/Narrow hunk scope |
M-n/M-p | In a commit buffer, go back to previous commit messages |
\ or C-t | Switch to text mode in a magit buffer |
Thanks for linking the HN discussion, good stuff. The comments mention this functionality is already available in magit-blame, though not very well advertised.
- `M-x RET magit-blame RET m` (or `b`) inside a source code buffer to activate the magit blame minor mode and then move the pointer around. There should be blame context in the minibuffer.
- `M-x RET magit-blame-cycle-style` (`c` when in magit-blame mode). This is awesome. Might just replace `SPC g f l (magit-log-buffer-file)` and `C-x v g (vc-annotate)` for me.
("<remap> <vc-diff>" . magit-diff-buffer-file) ("<remap> <vc-print-log>" . magit-log-buffer-file) ("<remap> <vc-print-root-log>" . magit-log-all) ("<remap> <vc-annotate>" . magit-blame-addition)
(setf forge-owned-accounts '(("BenedictHW" :remote-name "origin")) magit-save-repository-buffers 'dontask)
3.19.1. Magit Layer
use magit-file-rename to rename files already tracked by git. Once again, Git in Spacemacs/Emacs with Magit - YouTube .
Key | Effect |
---|---|
SPC g s | Open Git Status |
s | to stage selected file SPC-u S to stage all changes. |
c | to commit |
,, | confirm final commit |
SPC g f l | Find history of all commits that affected the highlighted region |
C-x v g | To complement SPC g f l |
# Git is also garbage collected through other commands git gc --aggressive
Github Tutorial
- Git Fork Workflow Using Rebase. Here is a suggested git forking… | by Ruth M….
- Working with Git and patches in Emacs
- The advantages of an email-driven git workflow
- Pro Git Free Book
- Karl Broman Github Tutorial
- Version Control (Git) · Missing Semester
Setting up SSH
Get a github account. Download and install git.
sudo apt install git
Verify that ~/.gitconfig exists and the contents match Dotfiles & Configuration Files
Look to see if you have files ~/.ssh/idrsa and ~/.ssh/idrsa.pub. If not, create such public/private keys: Open a terminal/shell and type:
ssh-keygen -o -t ed25519 -C "your_email@example.com" # Github login email.
Copy your public key (the contents of the newly-created idrsa.pub file) into your clipboard. Paste your ssh public key into your github account settings.
Go to your github Account Settings Click “SSH Keys” on the left. Click “Add SSH Key” on the right. Add a label (like “My laptop”) and paste the public key into the big text box.
In a terminal/shell, type the following to test it:
ssh -T git@github.com
If it says something like the following, it worked:
Hi username! You've successfully authenticated, but Github does not provide shell access.
Now clone your repositories.
Reduce the size of the git folder:
git repack -a -d --depth=250 --window=250
Signing commits with gpg Assuming you already have a key pair created and Github knows about it.
# Search for "GPG" inside KeePass and write to private-key.asc. gpg --import private-key.asc # https://www.bhw.name/contact to find and write to public-key.asc. gpg --import public-key.asc # Verify that ~/.gnupg/gpg-agend.conf exists, see dotfile.org. # Edit gpg key to raise trust level to 5 - ultimate. gpglogin # see .bashrc.
git - How to automatically sign commits with magit? - Emacs Stack Exchange
- Syncing forked project
Add the remote (original repo that you forked) and call it “upstream”
git remote add upstream https://github.com/original-repo/goes-here.git
Fetch (not pull, remember that a pull = fetch and merge in git parlance) all branches of remote upstream
git fetch upstream
Make sure you are on the correct branch
git checkout master
Rewrite your master with upstream’s master using git rebase. Will preserve your commits on master, to replay those commits on top of the current upstream/master.
git rebase upstream/master
Rewrite your master with upstream’s master using git reset. Will NOT preserve your commits on master
git reset –hard upstream/master
Push your updates to master. You may need to force the push with “–force”, as rebasing recreates new versions of each commit. So if those same commits already exist on your origin repo, which is likely, git will not recognize them and assume your origin is ahead of local and ask you to pull before pushing. the "–force" flag overrides this behaviour.
git push origin master –force
- Read Pro Git At some point you will have to read https://git-scm.com/book/en/v2 pro git.
- Learn to use Ediff to resolve conflicts https://www.sentia.com.au/blog/ediff-for-the-brainically-challenged
- Cleanup Github Forks
Install
curl
andjq
. Use the following command line to get the names of all your repositories on your Github account. Paste list into new filerepo-delete-list.txt
sudo apt install jq # curl is probably installed by default # Note page number in URL. If number of repo > 100, change it. curl "https://api.github.com/users/YOUR_GITHUB_ACCOUNT/repos?per_page=100&page=1" | jq -r '.[] | .name'
- Add YOURGITHUBACCOUNT/ to the beginning of each line. From
example-repo
toBenedictHW/example-repo
. - Register a new personal access token with a deleterepo permission at https://github.com/settings/tokens/new and save it.
Execute the command in shell.
cd /path/to/repo-delete-list.txt while read repo; do curl -X DELETE -H "Authorization: token YOUR_TOKEN" "https://api.github.com/repos/$repo"; done < repo_list_deleting.txt sudo apt purge jq
On Windows:
get-content C:\repo_list_deleting.txt | ForEach-Object { Invoke-WebRequest -Uri https://api.github.com/repos/$_ -Method “DELETE” -Headers @{“Authorization”=”token Your_TOKEN”} }
Conventional Commits
Keeps my commit history tidy. Able to be used as extracted changelogs. Like essay or citation conventions.
Feat | A new feature |
Fix | A bug fix |
Docs | Documentation only changes |
Style | Changes that do not affect the meaning of the code (white-space formatting) |
Refactor | Refactoring A code change that neither fixes a bug nor adds a feature |
Perf | A code change that improves performance |
Tests | Adding missing tests or correcting existing tests |
Build | Changes that affect the build system or external dependencies (quicklisp) |
CI | Changes to our Continous Integration/Continous Delivery configuration files and scripts |
Chore | Other changes that don't modify src or test files |
Revert | Reverts a previous commit |
Magit Forged
Magit Forged is a way to view/and compose issues and pull requests of a particular git repository while remaining in Emacs.
- Setup
- Make sure to generate a personal access token from Github
Edit whatever file is designated as your .authinfo file. You can check this via
M-x describe-variable RET auth-sources
. The relevant entry for magit forged is,machine api.github.com login "insertusernamehere"forge password "insertyourpasswordhere"
- You may need to restart emacs.
- Run
M-x forge-pull
while inside a buffer of the relevant project. - By pressing
SPC g s
to invokemagit-status
we can then press?
to see that Forge commands are listed under@
3.20. Ement Config
(require 'ement) (evil-collection-ement-setup) (spacemacs/set-leader-keys (kbd "acM") #'ement-connect (kbd "acm") #'ement-list-rooms (kbd "acn") #'ement-notify-switch-to-notifications-buffer (kbd "acc") #'ement-room-send-message (kbd "acv") #'ement-view-room) (evilified-state-evilify-map ement-room-mode-map :mode ement-room-mode :eval-after-load ement-room :bindings ";" #'helm-occur "n" #'ement-room-scroll-up-mark-read) (evilified-state-evilify-map ement-room-list-mode-map :mode ement-room-list-mode :eval-after-load ement-room-list :bindings ";" #'helm-occur "n" #'ement-room-list-next-unread) (add-hook 'ement-room-compose-hook 'ement-room-compose-org) (setf ement-save-sessions t ement-room-mark-rooms-read 'send ement-room-send-typing nil)
3.21. Misc Config
For more detail on the browser config, visit The ultimate Emacs hacking tutorial in Windows 10 WSL 2 | Damon Chan's Blog, and syl20bnr/spacemacs#13382 spacemacs in wsl2 can't open links in windows browse…
(setf auto-revert-interval 30) (auto-revert-set-timer) ;; https://rufflewind.com/2014-07-20/pasting-unicode-in-emacs-on-windows ;; (set-selection-coding-system 'utf-16-le) ;; Based on https://stackoverflow.com/questions/12102554/emacs-skip-whitespace-kills (define-advice kill-new (:around (orig-fn string &optional rest) ignore-whitespaces) "Don't put whitespaces into kill ring." (let* ((string-raw (substring-no-properties string)) (space-p (not (string-match-p "[^ \t\n\r]" string-raw)))) (if (not space-p) (apply orig-fn string rest) (message "skipped whitespace kill") nil))) ;; https://gnu.emacs.help.narkive.com/p20hvAvC/keyboard-translate-not-working-with-emacs-daemon (define-key key-translation-map [?\(] [?\[]) (define-key key-translation-map [?\[] [?\(]) (define-key key-translation-map [?\)] [?\]]) (define-key key-translation-map [?\]] [?\)]) ;; Should double buffering cause lag spikes on 3840 x 2160 displays ;; we can disable it via... (add-to-list 'default-frame-alist '(inhibit-double-buffering . t)) ;; Sets default browser (setf browse-url-generic-program "/mnt/c/Windows/System32/cmd.exe" browse-url-generic-args '("/c" "start") browse-url-browser-function #'browse-url-generic package-install-upgrade-built-in t) ;; Useful trick to share snippets between modes. Whenever a major mode ;; is loaded, fundamental-mode is also loaded (add-hook 'yas-minor-mode-hook (lambda () (yas-activate-extra-mode 'fundamental-mode))) ;; User Defined Toggles -> See SPC t hydra menu ;; VISUALLY wraps words that go past screen length ;; setq-default command means the command is run in every major mode buffer (setq-default truncate-lines nil) ;; Enables line by line navigation. Lines are not line broken > use RET for that (spacemacs/toggle-visual-line-navigation-globally-on) ;; Determines the length of time between the end of typing for SPC j j (avy-timer) ;; and the appearance of green prompt letters (setq avy-timeout-seconds 0.50)
3.22. Mu4e Config
3.22.1. Gmail Configuration Tips
Use POP3 forwarding on proper emails. Then check box enabling us to send as those addresses. Inbox options should be default with all categories checked off. Finally must use custom filters to disable gmail auto spam filter. I don't want important messages auto tagged as spam. Let me decide for myself please gmail.
- Click Create a new filter.
- Enter {(to:me) (deliveredto:USERNAME@gmail.com)} in the Has the words field (replacing USERNAME with your actual Gmail username).
- Click Create filter.
- In addition, create another one with the Has the words field with "is:spam" and of course, set all filters to never send items to the spam folder.
3.22.2. Usage
Updating Inbox & Sorting Mail view mu4e-update process by list-process command in SPC a p.
Key Effect d mark for deletion r mark as read x execute marked actions * mark for unknown actions # resolve unknown actions Reading Mail For html mail, use the view in browser capability
Key Effect aV view email in browser (can be eww,firefox etc) K yank links, followed by a numerical argument use M-x customize-variable to find possible values for browse-url-browser-function
Composing Mail Emails are currently composed within org-mode and then exported to html. Search through 0contacts.org and then email the appropriate person. Make sure to edit the html before sending it out.
Locate recipient of email in 0contacts.org Compose emails first in org mode through email-template.org in project-maria export through "org-mime-org-subtree-htmlize Hit" ", e s" to export the subtree to mu4e compose Verify html renders correctly send with ", ," TIP: press tab to autocomplete addresses
- Switching Accounts
Make sure to edit:
- mu4e config in your dotspacemacs file and
- the .authinfo file found in the $HOME directory
- the .mbsyncrc file found in the $HOME directory
- Delete .mu as well as the dir contents of Maildir.
- Afterwards, run these commands.
- (1) create maildir with mu mkdir ~/Maildir/Inbox
- (2) (assuming you are using mbsync) setup your ~/.mbsyncrc file
and run the program mbsync -a
to download your email.
- (3) run
mu init --maildir=~/project-jerome/email-archive --my-address=REPLACEWITHYOUR@gmail.com
- (4) Now in emacs `M-x mu4e' should work.
Key | Effect |
---|---|
P | Toggle threading |
W | Show related messages |
S | Search while in mu4e header buffer |
SPC s e | Search all emails through helm completion |
\ | Mu4e headers search narrow. C-u to remove results limit for the next search |
M-left/right | Previous, next query |
o | Save email attachment - gnus-mime-save-part |
Key | Effect |
---|---|
OG | Search group |
(defun mu4e-headers-mark-all-unread-read () "Put a ! \(read) mark on all visible unread messages." (interactive) (mu4e-headers-mark-for-each-if (cons 'read nil) (lambda (msg _param) (memq 'unread (mu4e-msg-field msg :flags)))) (mu4e-mark-execute-all t)) (defun mu4e-headers-refile-all () "Refile all messages in buffer." (interactive) (mu4e-headers-mark-for-each-if (cons 'refile nil) (lambda (_msg _param) t)) (mu4e-mark-execute-all t) (mu4e-search-prev)) (setf mu4e-change-filenames-when-moving t ; mbsync specific. ;; see an ASCII table for the character decimal codes mu4e-bookmarks '(("maildir:/INBOX" "Inbox" 105 ) ("\"maildir:/[Gmail]/All Mail\" and flag:unread" "Unread" 85)) user-mail-address (get-authinfo-password "personal.gmail" "ben") user-full-name "Benedict H. Wang" ;; mu4e-compose-signature mail-user-agent 'mu4e-user-agent mu4e-attachment-dir "/mnt/c/Users/bened/Downloads/" mu4e-drafts-folder "/[Gmail]/Drafts" mu4e-sent-folder "/[Gmail]/Sent Mail" mu4e-trash-folder "/[Gmail]/Trash" mu4e-refile-folder "/[Gmail]/All Mail" send-mail-function 'smtpmail-send-it smtpmail-stream-type 'starttls smtpmail-default-smtp-server "smtp.gmail.com" smtpmail-smtp-server "smtp.gmail.com" smtpmail-smtp-service 587 message-sendmail-f-is-evil t mu4e-index-update-in-background t mu4e-update-interval 900 mu4e-autorun-background-at-startup t mu4e-get-mail-command "mbsync -a" mu4e-hide-index-messages t mu4e-enable-mode-line nil ;; If this is enabled, prompts for new gpg fingerprints will not show up. ;; Instead emails will silently fail to send. mu4e-enable-async-operations nil mu4e-search-skip-duplicates t ;; Multipart html/plaintext email default, if the html portion is larger ;; by a factor of 5, it is assumed the user wants to view html. This ;; sets the factor to the largest possible fixnum, for we prefer the ;; plaintext version. mu4e-view-html-plaintext-ratio-heuristic most-positive-fixnum gnus-blocked-images "." mu4e-org-link-query-in-headers-mode nil ;; mu4e-org-contacts-file (concat +project-maria-dir+ "0contacts.org") message-kill-buffer-on-exit t mu4e-confirm-quit nil mu4e-headers-fields '((:human-date . 5) (:from-or-to . 20) (:subject)) mml-secure-openpgp-sign-with-sender t mml-secure-openpgp-signers '("06DDA93690F775E3715B628CCA949A6D46BC2BBE") mu4e-compose-complete-addresses t mu4e-compose-complete-only-after "2018-01-01" browse-url-filename-alist '(("^/\\(ftp@\\|anonymous@\\)?\\([^:/]+\\):/*" . "ftp://\\2/") ("^/\\([^:@/]+@\\)?\\([^:/]+\\):/*" . "ftp://\\1\\2/") ;; For gnus-article-browse-html-article on Windows Subsystem for Linux. ("^/+" . "file://///wsl$/Debian/")) ) (with-eval-after-load "recentf" (progn (add-to-list 'recentf-exclude "~/project-jerome/email-archive/") (add-to-list 'recentf-exclude "/tmp/"))) ;; Unbind s, originally bound to mu4e-headers-search. ;; Unset =mu4e-headers=search= from both =mu4e-headers-mode-map= and ;; =mu4e-view-mode-map=. Retain =s= for search in =mu4e-main-mode-map=. (define-key mu4e-headers-mode-map (kbd "s") #'avy-goto-word-or-subword-1) (define-key mu4e-headers-mode-map (kbd "K") #'mu4e-view-save-url) (define-key mu4e-headers-mode-map "S" 'helm-mu) (add-hook 'mu4e-view-mode-hook (lambda () (progn (evil-evilified-state) (define-key mu4e-view-mode-map (kbd "s") #'avy-goto-word-or-subword-1) (define-key mu4e-view-mode-map (kbd "K") #'mu4e-view-save-url) (define-key mu4e-view-mode-map "S" 'helm-mu)))) (define-key mu4e-headers-mode-map (kbd "c") #'mu4e-headers-mark-all-unread-read) (define-key mu4e-headers-mode-map (kbd "C") #'mu4e-headers-refile-all) ;; Functions ran on every message sent (spacemacs/set-leader-keys-for-major-mode 'mu4e-compose-mode "o" 'org-mime-edit-mail-in-org-mode) (spacemacs/set-leader-keys-for-major-mode 'mu4e-compose-mode "p" 'mml-secure-message-sign-pgpmime) (spacemacs/set-leader-keys (kbd "aes") #'helm-mu (kbd "aec") #'helm-mu-contacts (kbd "aej") #'mu4e-search-bookmark)
3.23. Org Mode Config
- Org Mode Workshop Example Config
- Particle Physics Researcher - Advanced Emacs org-mode examples and cookbook
- Worg - Org Mode Community
- Org Babel & Org mode cookbook
- Setup Emacs on WSL 2
- Phil Newton Org mode use cases
- Official Org-Mode Documentation
- Org-mode features You May Not Know - Bastien Guerry
- Time Clocking See Org Manual 8.6, Timers (The Org Manual). We can insert notes relative to an arbitrary timer so starting both the audio (lecture) recording at the same time as the org timer allows us to take notes with reference to where exactly in a lecture it was found. See org-timer-item.
- Tree Manipulation Look at options under
, s
while in org mode for tree options. Of note is org-kill-note-or-show-branches (bound to C-c C-k). See also Org Manual 2.5 Sparse trees. This next tip is amazing for creating multiple subtrees with timestamps shifted. Try calling org-clone-subtree-with-time-shift. The first thing that comes to mind, is the creation of routine events. - Internal linking hyperlinks - Radio targets in external org mode file, for glossary applicatio… Org-mode Hidden Gems - 03 Hyperlinks
It is worth noting that packages like org gcal, which do not come in a pre-configured spacemacs layer, are kept separate from this org mode config tree. Packages which do contain some boilerplate configuration, such as org re reveal, can be found as a subtree to this heading. As well as org-plus-contrib packages.
(require 'org) ;; Format text to fit 80 chars when pressing RET or ENTER. (add-hook 'org-mode-hook 'turn-on-auto-fill) ;; Source https://emacs.stackexchange.com/questions/10707/in-org-mode-how-to-remove-a-link (defun afs/org-replace-link-by-link-description () "Replace an org link by its description or if empty its address" (interactive) (if (org-in-regexp org-link-bracket-re 1) (save-excursion (let ((remove (list (match-beginning 0) (match-end 0))) (description (if (match-end 2) (org-match-string-no-properties 2) (org-match-string-no-properties 1)))) (apply 'delete-region remove) (insert description))))) ;; Source https://emacs.stackexchange.com/questions/12391/insert-org-id-link-at-point-via-outline-path-completion (defun org-id-complete-link (&optional arg) "Create an id: link using completion" (concat "id:" (org-id-get-with-outline-path-completion))) (org-link-set-parameters "id" :complete 'org-id-complete-link) ;; Source https://hungyi.net/posts/copy-org-mode-url/ (defun org-retrieve-url-from-point () "Copies the URL from an org link at the point" (interactive) (let ((plain-url (thing-at-point-url-at-point))) (if plain-url (progn (kill-new plain-url) (message (concat "Copied: " plain-url))) (let* ((link-info (assoc :link (org-context))) (text (when link-info (buffer-substring-no-properties (or (cadr link-info) (point-min)) (or (caddr link-info) (point-max)))))) (if (not text) (error "Oops! Point isn't in an org link") (string-match org-link-bracket-re text) (let ((url (substring text (match-beginning 1) (match-end 1)))) (kill-new url) (message (concat "Copied: " url)))))))) (setf org-directory +project-maria-dir+ org-agenda-files (cl-loop for agenda-file in '("0inbox.org" "0projects.org" "0solo.org" "0someday.org" "0contacts.org" "0calendar.org") collect (concat +project-maria-dir+ agenda-file)) ;; See org-superstar package for more context inhibit-compacting-font-caches t ;; See Org Manual 16.4 A Cleaner Outline View ;; I prefer a book-like view, which also allows for auto-fill org-adapt-indentation nil org-list-allow-alphabetical t org-image-actual-width '600 org-hide-emphasis-markers nil org-footnote-auto-adjust "Renumber and Sort" org-persist-directory "~/.cache/org-persist/" ;; Needs the libreoffice suite installed. ;; 'sudo apt install libreoffice' org-odt-preferred-output-format "docx") (spacemacs/set-leader-keys-for-major-mode 'org-mode "xR" 'afs/org-replace-link-by-link-description) (spacemacs/set-leader-keys-for-major-mode 'org-mode "iI" 'org-id-get-create) (spacemacs/set-leader-keys-for-major-mode 'org-mode "tC" 'org-table-create-or-convert-from-region) (spacemacs/set-leader-keys-for-major-mode 'org-mode "hn" 'org-next-visible-heading) (spacemacs/set-leader-keys-for-major-mode 'org-mode "hp" 'org-previous-visible-heading) (setq org-sticky-header-full-path 'full) ;; Require org-contacts to work with mu4e (require 'org-contacts) (setf org-contacts-files (list (concat +project-maria-dir+ "0contacts.org"))) (require 'org-re-reveal) (setf org-re-reveal-revealjs-version "4" org-re-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js") (setf org-mime-export-options '(:section-numbers nil ;; otherwise tables will not work :with-broken-links t :with-author nil :with-toc nil :with-latex dvipng)) (setq org-export-backends '(ascii html icalendar latex odt beamer man md org texinfo)) (setf org-download-method 'attach) ;; Add key bindings for org-expiry package (spacemacs/set-leader-keys-for-major-mode 'org-mode "dc" 'org-expiry-insert-created) (spacemacs/set-leader-keys-for-major-mode 'org-mode "de" 'org-expiry-insert-expiry) ;; Add call to org-expiry-insert-created every time org-id-get-create is run (advice-add 'org-id-get-create :after 'org-expiry-insert-created) (require 'org-depend) (require 'cl-lib) (org-clock-persistence-insinuate) (add-hook 'org-clock-in-prepare-hook 'my-org-mode-ask-effort) (defun my-org-mode-ask-effort () "Ask for an effort estimate when clocking in if none exists." (unless (org-entry-get (point) "Effort") (let ((effort (completing-read "Effort: " (org-entry-get-multivalued-property (point) "Effort")))) (unless (equal effort "") (org-set-property "Effort" effort))))) (defun eos/org-clock-in () (interactive) (org-clock-in '(4))) ;; Exclude DONE state tasks from refile targets (defun bh/verify-refile-target () "Exclude todo keywords with a done state from refile targets" (not (member (nth 2 (org-heading-components)) org-done-keywords))) ;; https://orgmode.org/worg/org-contrib/org-depend.html (defun mm/org-insert-trigger () "Automatically insert chain-find-next trigger when entry becomes NEXT" (cond ((equal org-state "NEXT") (unless org-depend-doing-chain-find-next (org-set-property "TRIGGER" "chain-find-next(NEXT,from-current,priority-up,effort-up)"))) ((not (member org-state org-done-keywords)) (org-delete-property "TRIGGER")))) (add-hook 'org-after-todo-state-change-hook 'mm/org-insert-trigger) (progn (defcustom ap/work:clocked-today-ids nil "List of Org heading IDs containing clocktables to read." :type '(repeat string)) (defcustom ap/work:clocked-today-interval 30 "Update the clocktables after this many seconds of idle time." :type 'number) ;; HACK: This version just uses the value as-is, expecting it to be a ;; decimal number with "h" suffix, and it only uses the first value in ;; the ID list. (defun ap/work:clocked-today (&optional messagep) "Show work time clocked today." (interactive (list 'messagep)) (cl-labels ((clocked-for (id) (org-with-point-at (org-id-find id 'marker) (org-narrow-to-subtree) (while (not (org-in-clocktable-p)) (forward-line)) (when (eobp) (error "Can't find clocktable at %S:%S" (current-buffer) id)) (let ((inhibit-message t)) (org-update-dblock)) (while (not (org-at-table-p)) (forward-line)) (if-let ((time (org-table-get 2 3)) ((string-match (rx (group (1+ (or digit ".")) "h")) time))) (match-string 1 time) "0h")))) (let ((string (clocked-for (car ap/work:clocked-today-ids)))) (when messagep (message "Clocked today: %s" string)) string))) (defvar ap/work:clocked-today-lighter "") (defvar ap/work:clocked-today-timer nil) (define-minor-mode ap/work:clocked-today-mode "Show time clocked today in mode line." :global t (let ((lighter '(ap/work:clocked-today-mode ap/work:clocked-today-lighter))) (if ap/work:clocked-today-mode (progn (setf ap/work:clocked-today-timer (run-with-idle-timer ap/work:clocked-today-interval ap/work:clocked-today-interval (lambda () (setf ap/work:clocked-today-lighter (concat "📆" (ap/work:clocked-today) " "))))) (cl-pushnew lighter global-mode-string :test #'equal)) (when (timerp ap/work:clocked-today-timer) (cancel-timer ap/work:clocked-today-timer)) (setf global-mode-string (remove lighter global-mode-string)))))) (spacemacs/set-leader-keys "oa" 'ben/default-custom-agenda) (spacemacs/set-leader-keys "oj" 'spacemacs/org-clock-jump-to-current-clock) (spacemacs/set-leader-keys "oi" 'eos/org-clock-in) (spacemacs/set-leader-keys "oI" 'org-clock-in) (spacemacs/set-leader-keys "oo" 'org-clock-out) (spacemacs/set-leader-keys "or" 'org-resolve-clocks) (spacemacs/set-leader-keys "oc" 'org-capture) ;; Press t to change task todo state (setf org-use-fast-todo-selection t org-treat-S-cursor-todo-selection-as-state-change t ;; Require exit notes for modifying a scheduled for deadline date org-log-reschedule 'time org-log-redeadline 'note org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "PROJ(p)" "APPT(a)" "PROG(i)" "WAIT(w@/!)" "|" "DONE(d)" "CXLD(c@/!)")) org-todo-keyword-faces '(;; Project Defined ("PROJ" :foreground "gold" :weight bold) ;; Todo's Brainstormed ("TODO" :foreground "tomato" :weight bold) ;; Next Action(s) chosen ("NEXT" :foreground "RoyalBlue" :weight bold) ;; Delegated or out of your control ("WAIT" :foreground "magenta" :weight bold) ;; Reducing from potential to actual ("PROG" :foreground "cyan2" :weight bold) ;; Completed task ("DONE" :foreground "SpringGreen3" :weight bold) ;; Formal appointment, in-person/scheduled in advance ;; Of type WAIT, but with a definte deadline ("APPT" :foreground "DarkViolet" :weight bold) ;; Informal (interruption) meeting/verbal/email ;; Informal (interruption) calls/texts ;; ("MEET" :foreground "MediumOrchid" :weight bold) ;; Cancelled task, unable to complete ("CXLD" :foreground "SaddleBrown" :weight bold)) org-enforce-todo-dependencies t org-agenda-dim-blocked-tasks t org-habit-graph-column 80 org-agenda-skip-scheduled-if-deadline-is-shown t ;; 6) Adding New Tasks Quickly with Org Capture ;; Capture templates for: TODO tasks, Notes, appointments, phone calls, meetings, and org-protocol ;; \n is newline in the template. Functions as RET would in insert mode ;; placing a backslash before " in TRIGGER below to have the string not end org-capture-templates '(("n" "Next Action" entry (file "~/project-maria/0inbox.org") "* NEXT [#C] %?%^G\n:PROPERTIES:\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n" :empty-lines 1) ("t" "Todo Task" entry (file "~/project-maria/0inbox.org") "* TODO [#C] %?%^G\n :PROPERTIES:\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n" :empty-lines 1) ("a" "Appointment" entry (file "~/project-maria/0calendar.org") "* APPT %?\nSCHEDULED: %^T\n:PROPERTIES:\n:LOCATION: %^{LOCATION|TBD}\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:" :empty-lines 1) ("j" "Journal Entry" entry (file "~/project-maria/0inbox.org")"* NEXT JOURNAL ENTRY %U\n:PROPERTIES:\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n%?" :empty-lines 1) ("h" "Habit" entry (file "~/project-maria/0inbox.org")"* NEXT %?\nSCHEDULED: %(format-time-string \"%\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:ASSIGNED: %U\n:END:" :empty-lines 1) ("c" "Contacts" entry (file "~/project-maria/0inbox.org") "* %(org-contacts-template-name)\n:PROPERTIES:\n:PHONE: %?\n:EMAIL:\n:ADDRESS:\n:BIRTHDAY:\n:NOTE: Added on: %U\n:END:" :empty-lines 1) ("p" "Project" entry (file "~/project-maria/0projects.org") "* PROJ %? [#C] [/] [%] %^G\n:PROPERTIES:\n:ASSIGNED: %U\n:CATEGORY: %^{CATEGORY|Misc.}\n:END:\n** NEXT [#C]\n:PROPERTIES:\n:TRIGGER: chain-find-next(NEXT,from-current,priority-up,effort-up)\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n" :empty-lines 1)) ;; **** 9) Clocking org-clock-in-switch-to-state "PROG" org-clock-out-remove-zero-time-clocks t org-clock-out-when-done t org-clock-persist t org-clock-in-resume t org-clock-persist-query-resume nil org-clock-auto-clock-resolution 'when-no-clock-is-running org-clock-report-include-clocking-task t org-time-stamp-rounding-minutes '(1 1) org-agenda-clockreport-parameter-plist '(:link t :maxlevel 10 :fileskip0 t :stepskip0 t :compact t :narrow 80) org-log-into-drawer t org-clock-history-length 35 ;; **** 7) Refiling Tasks org-refile-targets '((nil :maxlevel . 9) (org-agenda-files :maxlevel . 9)) org-outline-path-complete-in-steps nil org-refile-use-outline-path 'file org-refile-target-verify-function 'bh/verify-refile-target ;; **** 11) Context Tags with fast selection keys org-tag-alist '(;; Sets geo-spatial and context tags ;; Startgroup and endgroup make tags mutually ;; exclusive (:startgroup) ("0home" . ?h) ("0office" . ?o) ("0errand" . ?e) ;; (:endgroup) ;; Person(s) can be contexts too. ("0father" . ?d) ("0mother" . ?d) ("0brother" . ?d) ("0family" . ?d) ("0workteam1" . ?d) ("0docket" . ?d) ("REF" . ?r) ("FLAGGED" . ??)) org-fast-tag-selection-single-key 'expert org-tags-column 0 ;; For tag searches ignore tasks with scheduled and deadline dates org-agenda-tags-todo-honor-ignore-options t ;; **** 14) Stuck Projects org-stuck-projects '("+TODO=\"PROJ\"" ("NEXT") nil nil) ;; **** 15) Archiving org-archive-default-command 'org-archive-subtree org-archive-location (concat +project-maria-dir+ "archived-tasks/0taskings-" (format-time-string "%Y") ".org::datetree/") org-archive-save-context-info '(time category olpath ltags itags)) (add-hook 'org-agenda-mode-hook (lambda () (define-key org-agenda-mode-map (kbd "s") 'avy-goto-word-or-subword-1))) (defun my/org-agenda-calculate-efforts (limit) "Sum the efforts of scheduled entries up to LIMIT in the agenda buffer." (let (total) (save-excursion (while (< (point) limit) (when (member (org-get-at-bol 'type) '("scheduled" "past-scheduled" "timestamp")) (push (org-entry-get (org-get-at-bol 'org-hd-marker) "EFFORT") total)) (forward-line))) (org-duration-from-minutes (cl-reduce #'+ (mapcar #'org-duration-to-minutes (cl-remove-if-not 'identity total)))))) (defun my/org-agenda-insert-efforts () "Insert the efforts for each day inside the agenda buffer." (save-excursion (let (pos) (while (setq pos (text-property-any (point) (point-max) 'org-agenda-date-header t)) (goto-char pos) (end-of-line) (insert-and-inherit (concat " (" (my/org-agenda-calculate-efforts (next-single-property-change (point) 'day)) ")")) (forward-line))))) (add-hook 'org-agenda-finalize-hook 'my/org-agenda-insert-efforts) (defun ben/default-custom-agenda() "Functionally call custom agenda command bound to KEY" (interactive) (org-agenda nil "d")) (setf org-agenda-block-separator 61 org-agenda-breadcrumbs-separator " | " ;; https://stackoverflow.com/questions/58820073/s-in-org-agenda-prefix-format-doesnt-display-dates-in-the-todo-view org-agenda-prefix-format '((agenda . "%-t %? e%c%s") (todo . "%? e%c%s%(let ((scheduled (org-get-deadline-time (point)))) (if scheduled (format-time-string \" [%Y-%m-%d] \" scheduled) \"\"))") (tags . "%? e%c%s%(let ((scheduled (org-get-deadline-time (point)))) (if scheduled (format-time-string \" [%Y-%m-%d] \" scheduled) \"\"))") (search . "%? e%c%s")) org-agenda-deadline-leaders '("!D!: " "D%3d: " "") org-agenda-scheduled-leaders '("!S!: " "S%3d: " "") org-agenda-time-grid (quote ((daily today remove-match) (0600 0900 1200 1500 1800 2100) "......" "----------------")) org-columns-default-format-for-agenda "%75ITEM(Task) %10Effort(Estim){:} %10CLOCKSUM(ActTime) %5TODO(State)" org-columns-default-format "%75ITEM(Task) %10Effort(Estim){:} %10CLOCKSUM(ActTime) %5TODO(State)" org-global-properties '(quote (("Effort_ALL" . "0:00 0:10 0:30 1:00 1:30 2:00 2:30 3:00 4:00 5:00 6:00 7:00 8:00") ("STYLE_ALL" . "habit"))) org-agenda-columns-add-appointments-to-effort-sum t org-agenda-default-appointment-duration 0 org-agenda-log-mode-items '(closed state clock) org-agenda-start-with-log-mode t org-agenda-start-with-entry-text-mode t org-agenda-add-entry-text-maxlines 5 org-agenda-entry-text-maxlines 5 org-agenda-start-with-clockreport-mode nil org-agenda-custom-commands '( ;; ***** Default Agenda ("d" "Default (Master) Agenda" ((agenda "" ((org-agenda-span 1) (org-deadline-warning-days 7) (org-agenda-overriding-header "Today's Agenda\n"))) (tags "TODO=\"PROG\"" ((org-agenda-sorting-strategy '(priority-down deadline-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nTasks in Progress\n"))) (tags "TODO=\"NEXT\"" ((org-agenda-sorting-strategy '(priority-down deadline-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nAction Items\n") (org-agenda-skip-function '(org-agenda-skip-entry-if 'scheduled)))) ;; Presents only APPT and Routine Events. (agenda "" ((org-agenda-span '33) (org-agenda-start-on-weekday nil) (org-agenda-start-day "+1d") (org-agenda-entry-types '(:timestamp :sexp :scheduled)) (org-agenda-overriding-header "Routine & Appointments\n"))) (tags "+TODO=\"WAIT\"" ((org-agenda-sorting-strategy '(timestamp-down)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nDelegated/Waiting For\n"))) (tags "TODO=\"TODO\"" ((org-agenda-sorting-strategy '(category-keep)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nAll Tasks\n"))) (tags "TODO=\"PROJ\"" ((org-agenda-sorting-strategy '(category-keep)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nAll Projects\n"))) (stuck "" ((org-agenda-overriding-header "\nStuck Projects\n")))) ((org-agenda-tag-filter-preset '("-SDAY")))) ;; ***** Review Agenda ("r" "Review Agenda" ((tags "TODO=\"DONE\"" ((org-agenda-sorting-strategy '(priority-down deadline-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nCompleted Tasks\n"))) (tags "TODO=\"CXLD\"" ((org-agenda-sorting-strategy '(tsia-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nTerminated Tasks\n"))) (stuck "" ((org-agenda-overriding-header "\nStuck Projects\n"))) (agenda "" ((org-agenda-span '33) (org-agenda-start-on-weekday nil) (org-agenda-start-day "+1d") (org-agenda-entry-types '(:timestamp :sexp :scheduled)) (org-agenda-overriding-header "Routine & Appointments\n")))) ((org-agenda-tag-filter-preset '("-SDAY"))))) org-agenda-window-setup 'current-window) ;; Following 2 lines are needed to exclude parent heading from table of contents but still export the content ;; https://emacs.stackexchange.com/questions/30183/orgmode-export-skip-ignore-first-headline-level (require 'ox-extra) (ox-extras-activate '(ignore-headlines)) ;; Allows exporting bibtex citations to html (require 'ox-bibtex) ;; Exclude default CSS from html export and add external stylesheet (setq org-html-head-include-default-style nil) ;; Omit inline css as we use an imported stylesheet (setq org-html-htmlize-output-type 'css) ;; https://www.taingram.org/blog/org-mode-blog.html (setq org-export-global-macros '(("timestamp" . "@@html:<span class=\"timestamp\">[$1]</span>@@"))) (defun my/org-sitemap-date-entry-format (entry style project) "Format ENTRY in org-publish PROJECT Sitemap format ENTRY ENTRY STYLE format that includes date." (let ((filename (org-publish-find-title entry project))) (if (= (length filename) 0) (format "*%s*" entry) (format "{{{timestamp(%s)}}} [[file:%s][%s]]" (format-time-string "%Y-%m-%d" (org-publish-find-date entry project)) entry filename)))) (setf org-publish-project-alist '(("blog" :components ("blog-content" "blog-rss")) ("blog-content" :base-directory "~/project-maria/blog" :html-extension "html" :base-extension "org" :recursive t :publishing-function org-html-publish-to-html :publishing-directory "~/common-lisp/project-isidore/assets/blog" :section-numbers t :table-of-contents t :exclude "rss.org" :with-title nil :auto-sitemap t :sitemap-filename "archive.org" :sitemap-title "Blog Archive" :sitemap-sort-files anti-chronologically :sitemap-style tree :sitemap-format-entry my/org-sitemap-date-entry-format ;; Use HTML5 ;; https://orgmode.org/manual/HTML-doctypes.html#HTML-doctypes :html-doctype "html5" :html-html5-fancy t ;; Link to external custom stylesheet ;; If you need code highlight from highlight.js, include the latter three lines. :html-head " <link rel=\"stylesheet\" type=\"text/css\" href=\"../global.css\"/> <link rel=\"stylesheet\" href=\"//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/styles/base16/solarized-light.min.css\"> <script src=\"//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/highlight.min.js\" defer></script> <script>var hlf=function(){Array.prototype.forEach.call(document.querySelectorAll(\"pre.src\"),function(t){var e;e=t.getAttribute(\"class\"),e=e.replace(/src-(\w+)/,\"src-$1 $1\"),console.log(e),t.setAttribute(\"class\",e),hljs.highlightBlock(t)})};addEventListener(\"DOMContentLoaded\",hlf);</script>" :html-preamble " <div class=\"header header-fixed\"> <div class=\"navbar container\"> <div class=\"logo\"><a href=\"/\">BHW</a></div> <input type=\"checkbox\" id=\"navbar-toggle\" > <label for=\"navbar-toggle\"><i></i></label> <nav class=\"menu\"> <ul> <li><a href=\"/about\">About</a></li> <li><a href=\"/work\">Work</a></li> <li><a href=\"/assets/blog/archive.html\">Blog</a></li> <li><a href=\"/contact\">Contact</a></li> </ul> </nav> </div> </div> <h1 class=\"title\">%t</h1> <p class=\"subtitle\">%s</p> <br/> <p class=\"updated\"><a href=\"/contact#article-history\">Updated:</a> %C</p>" ;; Article Postamble includes ;; Javascript snippet to insert anchor links to Table of Contents ;; HTML Footer :html-postamble "<script> const headers = Array.from( document.querySelectorAll('h2, h3, h4, h5, h6') ); headers.forEach( header => { header.insertAdjacentHTML('afterbegin', '<a href=\"#table-of-contents\">⇱</a>' ); }); </script> <hr/> <footer> <div class=\"copyright-container\"> Comments? Corrections? <a href=\"https://bhw.name/contact\"> Please do reach out.</a><a href=\"https://bhw.name/blog/rss.xml\"> RSS Feed. </a><a href=\"https://bhw.name/subscribe\"> Mailing List. </a><br/> Copyright 2021 Benedict H. Wang. <br/> Blog content is available under <a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/4.0/\"> CC-BY-SA 4.0 </a> unless otherwise noted.<br/> Created with %c on <a href=\"https://www.gnu.org\">GNU</a>/<a href=\"https://www.kernel.org/\">Linux</a><br/> </div> </footer>" ) ("blog-rss" :base-directory "~/project-maria/blog" :base-extension "org" :publishing-directory "~/common-lisp/project-isidore/assets/blog" :publishing-function publish-posts-rss-feed :rss-extension "xml" :html-link-home "http://bhw.name/" :html-link-use-abs-url t :html-link-org-files-as-html t :exclude "archive.org" :auto-sitemap t :sitemap-function posts-rss-feed :sitemap-title "Benedict H. Wang Blog RSS" :sitemap-filename "rss.org" :sitemap-style list :sitemap-sort-files anti-chronologically :sitemap-format-entry format-posts-rss-feed-entry) )) ;; https://alhassy.github.io/AlBasmala#Clickable-Headlines (defun my/ensure-headline-ids (&rest _) "Org trees without a custom ID will have All non-alphanumeric characters are cleverly replaced with ‘-’. If multiple trees end-up with the same id property, issue a message and undo any property insertion thus far. E.g., ↯ We'll go on a ∀∃⇅ adventure ↦ We'll-go-on-a-adventure " (interactive) (let ((ids)) (org-map-entries (lambda () (org-with-point-at (point) (let ((id (org-entry-get nil "CUSTOM_ID"))) (unless id (thread-last (nth 4 (org-heading-components)) (s-replace-regexp "[^[:alnum:]']" "-") (s-replace-regexp "-+" "-") (s-chop-prefix "-") (s-chop-suffix "-") (setq id)) (if (not (member id ids)) (push id ids) (message-box "Oh no, a repeated id!\n\n\t%s" id) (undo) (setq quit-flag t)) (org-entry-put nil "CUSTOM_ID" id)))))))) ;; Whenever html & md export happens, ensure we have headline ids. (advice-add 'org-html-export-to-html :before 'my/ensure-headline-ids) (advice-add 'org-md-export-to-markdown :before 'my/ensure-headline-ids) ;; https://nicolasknoebber.com/posts/blogging-with-emacs-and-org.html (defun format-posts-rss-feed-entry (entry _style project) "Format ENTRY for the posts RSS feed in PROJECT." (org-publish-initialize-cache "blog-rss") (let* ((title (org-publish-find-title entry project)) (link (concat "blog/" (file-name-sans-extension entry) ".html")) (author (org-publish-find-property entry :author project)) (pubdate (format-time-string (car org-time-stamp-formats) (org-publish-find-date entry project)))) (message pubdate) (format "%s :properties: :rss_permalink: %s :author: %s :pubdate: %s :end:\n" title link author pubdate))) (defun posts-rss-feed (title list) "Generate a sitemap of posts that is exported as a RSS feed. TITLE is the title of the RSS feed. LIST is an internal representation for the files to include. PROJECT is the current project." (concat "#+TITLE: " title "\n#+EMAIL: seneschal@bhw.name" "\n\n" (org-list-to-subtree list))) (defun publish-posts-rss-feed (plist filename dir) "Publish PLIST to RSS when FILENAME is rss.org. DIR is the location of the output." (if (equal "rss.org" (file-name-nondirectory filename)) (org-rss-publish-to-rss plist filename dir))) (add-hook 'org-mode 'org-tanglesync-mode) (add-hook 'prog-mode 'org-tanglesync-watch-mode) (add-hook 'text-mode 'org-tanglesync-watch-mode) (setf org-tanglesync-default-diff-action ':diff org-tanglesync-watch-files '("dotfiles.org")) (spacemacs/set-leader-keys-for-major-mode 'org-mode "bS" 'org-tanglesync-process-buffer-interactive)
3.23.1. Org Mode Export
- An Org-mode template for technical specification documents and HTML publishing
- nfdn: Running SQL Queries on Org Tables
(setq org-export-backends '(ascii html icalendar latex odt beamer man md org texinfo))
3.23.2. Org Mode Tutorial
- We all owe a great deal of debt to all our teachers and professors. Something in the human-to-human transmission of knowledge is lost when just reading text. Org mode and Spacemacs: The Absolute Minimum you need to know - YouTube
3.23.3. Org Agenda Config (GTD)
- Read Getting things Done by David Allen
- Orgmode for GTD
- Org Mode - Organize Your Life In Plain Text! This is how the configuration is structured.
- GitHub - et2010/org-gtd: Private spacemacs layer for GTD.
- Get Things Done with Emacs
Key | Effect |
---|---|
SPC m s r | org-agenda-refile |
From this, things are pretty self explanatory. Remember Meetings are given an active time stamp NOT with a :scheduled: date-stamp. Org Gcal solves calendar synchronization between laptop and phone.
Noteworthy Todo Keyword is PROG (formerly IN-MOTION) for IN-PROGRESS. Author has found this a nice feature for two reasons:
- Obvious reason is that it reminds you what you were working on in that
particular place/context.
- The interesting reason is that it restricts the amount of open loops,
as per little's law. Credit must be given here:. What qualifies as "too many" open loops is an individual quality, but a lower time is better.
There exists 3 priorities, A > B > C.
- If an item has a real deadline = B priority. Real deadline means not a
self-imposed deadline. Those are meaningless. To render a just accounting of your time before Christ is all the motivation you need, and if that is not enough, then a self-imposed deadline will be ignored anyways. In addition, to prioritize the deadlines of others is to put into practice the higher calling to love thy neighbor as thyself, to imitate the Son of Man in coming to serve and not be served.
- If an item needs to be done As Soon As Possible (ASAP) = A priority.
- Otherwise = C priority.
(require 'org-depend) (require 'cl-lib) (org-clock-persistence-insinuate) (add-hook 'org-clock-in-prepare-hook 'my-org-mode-ask-effort) (defun my-org-mode-ask-effort () "Ask for an effort estimate when clocking in if none exists." (unless (org-entry-get (point) "Effort") (let ((effort (completing-read "Effort: " (org-entry-get-multivalued-property (point) "Effort")))) (unless (equal effort "") (org-set-property "Effort" effort))))) (defun eos/org-clock-in () (interactive) (org-clock-in '(4))) ;; Exclude DONE state tasks from refile targets (defun bh/verify-refile-target () "Exclude todo keywords with a done state from refile targets" (not (member (nth 2 (org-heading-components)) org-done-keywords))) ;; https://orgmode.org/worg/org-contrib/org-depend.html (defun mm/org-insert-trigger () "Automatically insert chain-find-next trigger when entry becomes NEXT" (cond ((equal org-state "NEXT") (unless org-depend-doing-chain-find-next (org-set-property "TRIGGER" "chain-find-next(NEXT,from-current,priority-up,effort-up)"))) ((not (member org-state org-done-keywords)) (org-delete-property "TRIGGER")))) (add-hook 'org-after-todo-state-change-hook 'mm/org-insert-trigger) (progn (defcustom ap/work:clocked-today-ids nil "List of Org heading IDs containing clocktables to read." :type '(repeat string)) (defcustom ap/work:clocked-today-interval 30 "Update the clocktables after this many seconds of idle time." :type 'number) ;; HACK: This version just uses the value as-is, expecting it to be a ;; decimal number with "h" suffix, and it only uses the first value in ;; the ID list. (defun ap/work:clocked-today (&optional messagep) "Show work time clocked today." (interactive (list 'messagep)) (cl-labels ((clocked-for (id) (org-with-point-at (org-id-find id 'marker) (org-narrow-to-subtree) (while (not (org-in-clocktable-p)) (forward-line)) (when (eobp) (error "Can't find clocktable at %S:%S" (current-buffer) id)) (let ((inhibit-message t)) (org-update-dblock)) (while (not (org-at-table-p)) (forward-line)) (if-let ((time (org-table-get 2 3)) ((string-match (rx (group (1+ (or digit ".")) "h")) time))) (match-string 1 time) "0h")))) (let ((string (clocked-for (car ap/work:clocked-today-ids)))) (when messagep (message "Clocked today: %s" string)) string))) (defvar ap/work:clocked-today-lighter "") (defvar ap/work:clocked-today-timer nil) (define-minor-mode ap/work:clocked-today-mode "Show time clocked today in mode line." :global t (let ((lighter '(ap/work:clocked-today-mode ap/work:clocked-today-lighter))) (if ap/work:clocked-today-mode (progn (setf ap/work:clocked-today-timer (run-with-idle-timer ap/work:clocked-today-interval ap/work:clocked-today-interval (lambda () (setf ap/work:clocked-today-lighter (concat "📆" (ap/work:clocked-today) " "))))) (cl-pushnew lighter global-mode-string :test #'equal)) (when (timerp ap/work:clocked-today-timer) (cancel-timer ap/work:clocked-today-timer)) (setf global-mode-string (remove lighter global-mode-string)))))) (spacemacs/set-leader-keys "oa" 'ben/default-custom-agenda) (spacemacs/set-leader-keys "oj" 'spacemacs/org-clock-jump-to-current-clock) (spacemacs/set-leader-keys "oi" 'eos/org-clock-in) (spacemacs/set-leader-keys "oI" 'org-clock-in) (spacemacs/set-leader-keys "oo" 'org-clock-out) (spacemacs/set-leader-keys "or" 'org-resolve-clocks) (spacemacs/set-leader-keys "oc" 'org-capture) ;; Press t to change task todo state (setf org-use-fast-todo-selection t org-treat-S-cursor-todo-selection-as-state-change t ;; Require exit notes for modifying a scheduled for deadline date org-log-reschedule 'time org-log-redeadline 'note org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "PROJ(p)" "APPT(a)" "PROG(i)" "WAIT(w@/!)" "|" "DONE(d)" "CXLD(c@/!)")) org-todo-keyword-faces '(;; Project Defined ("PROJ" :foreground "gold" :weight bold) ;; Todo's Brainstormed ("TODO" :foreground "tomato" :weight bold) ;; Next Action(s) chosen ("NEXT" :foreground "RoyalBlue" :weight bold) ;; Delegated or out of your control ("WAIT" :foreground "magenta" :weight bold) ;; Reducing from potential to actual ("PROG" :foreground "cyan2" :weight bold) ;; Completed task ("DONE" :foreground "SpringGreen3" :weight bold) ;; Formal appointment, in-person/scheduled in advance ;; Of type WAIT, but with a definte deadline ("APPT" :foreground "DarkViolet" :weight bold) ;; Informal (interruption) meeting/verbal/email ;; Informal (interruption) calls/texts ;; ("MEET" :foreground "MediumOrchid" :weight bold) ;; Cancelled task, unable to complete ("CXLD" :foreground "SaddleBrown" :weight bold)) org-enforce-todo-dependencies t org-agenda-dim-blocked-tasks t org-habit-graph-column 80 org-agenda-skip-scheduled-if-deadline-is-shown t ;; 6) Adding New Tasks Quickly with Org Capture ;; Capture templates for: TODO tasks, Notes, appointments, phone calls, meetings, and org-protocol ;; \n is newline in the template. Functions as RET would in insert mode ;; placing a backslash before " in TRIGGER below to have the string not end org-capture-templates '(("n" "Next Action" entry (file "~/project-maria/0inbox.org") "* NEXT [#C] %?%^G\n:PROPERTIES:\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n" :empty-lines 1) ("t" "Todo Task" entry (file "~/project-maria/0inbox.org") "* TODO [#C] %?%^G\n :PROPERTIES:\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n" :empty-lines 1) ("a" "Appointment" entry (file "~/project-maria/0calendar.org") "* APPT %?\nSCHEDULED: %^T\n:PROPERTIES:\n:LOCATION: %^{LOCATION|TBD}\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:" :empty-lines 1) ("j" "Journal Entry" entry (file "~/project-maria/0inbox.org")"* NEXT JOURNAL ENTRY %U\n:PROPERTIES:\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n%?" :empty-lines 1) ("h" "Habit" entry (file "~/project-maria/0inbox.org")"* NEXT %?\nSCHEDULED: %(format-time-string \"%\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:ASSIGNED: %U\n:END:" :empty-lines 1) ("c" "Contacts" entry (file "~/project-maria/0inbox.org") "* %(org-contacts-template-name)\n:PROPERTIES:\n:PHONE: %?\n:EMAIL:\n:ADDRESS:\n:BIRTHDAY:\n:NOTE: Added on: %U\n:END:" :empty-lines 1) ("p" "Project" entry (file "~/project-maria/0projects.org") "* PROJ %? [#C] [/] [%] %^G\n:PROPERTIES:\n:ASSIGNED: %U\n:CATEGORY: %^{CATEGORY|Misc.}\n:END:\n** NEXT [#C]\n:PROPERTIES:\n:TRIGGER: chain-find-next(NEXT,from-current,priority-up,effort-up)\n:EFFORT: %^{0:00|0:10|0:30|1:00|1:30|2:00|2:30|3:00|4:00|5:00|6:00|7:00|8:00}\n:ASSIGNED: %U\n:END:\n" :empty-lines 1)) ;; **** 9) Clocking org-clock-in-switch-to-state "PROG" org-clock-out-remove-zero-time-clocks t org-clock-out-when-done t org-clock-persist t org-clock-in-resume t org-clock-persist-query-resume nil org-clock-auto-clock-resolution 'when-no-clock-is-running org-clock-report-include-clocking-task t org-time-stamp-rounding-minutes '(1 1) org-agenda-clockreport-parameter-plist '(:link t :maxlevel 10 :fileskip0 t :stepskip0 t :compact t :narrow 80) org-log-into-drawer t org-clock-history-length 35 ;; **** 7) Refiling Tasks org-refile-targets '((nil :maxlevel . 9) (org-agenda-files :maxlevel . 9)) org-outline-path-complete-in-steps nil org-refile-use-outline-path 'file org-refile-target-verify-function 'bh/verify-refile-target ;; **** 11) Context Tags with fast selection keys org-tag-alist '(;; Sets geo-spatial and context tags ;; Startgroup and endgroup make tags mutually ;; exclusive (:startgroup) ("0home" . ?h) ("0office" . ?o) ("0errand" . ?e) ;; (:endgroup) ;; Person(s) can be contexts too. ("0father" . ?d) ("0mother" . ?d) ("0brother" . ?d) ("0family" . ?d) ("0workteam1" . ?d) ("0docket" . ?d) ("REF" . ?r) ("FLAGGED" . ??)) org-fast-tag-selection-single-key 'expert org-tags-column 0 ;; For tag searches ignore tasks with scheduled and deadline dates org-agenda-tags-todo-honor-ignore-options t ;; **** 14) Stuck Projects org-stuck-projects '("+TODO=\"PROJ\"" ("NEXT") nil nil) ;; **** 15) Archiving org-archive-default-command 'org-archive-subtree org-archive-location (concat +project-maria-dir+ "archived-tasks/0taskings-" (format-time-string "%Y") ".org::datetree/") org-archive-save-context-info '(time category olpath ltags itags)) (add-hook 'org-agenda-mode-hook (lambda () (define-key org-agenda-mode-map (kbd "s") 'avy-goto-word-or-subword-1))) (defun my/org-agenda-calculate-efforts (limit) "Sum the efforts of scheduled entries up to LIMIT in the agenda buffer." (let (total) (save-excursion (while (< (point) limit) (when (member (org-get-at-bol 'type) '("scheduled" "past-scheduled" "timestamp")) (push (org-entry-get (org-get-at-bol 'org-hd-marker) "EFFORT") total)) (forward-line))) (org-duration-from-minutes (cl-reduce #'+ (mapcar #'org-duration-to-minutes (cl-remove-if-not 'identity total)))))) (defun my/org-agenda-insert-efforts () "Insert the efforts for each day inside the agenda buffer." (save-excursion (let (pos) (while (setq pos (text-property-any (point) (point-max) 'org-agenda-date-header t)) (goto-char pos) (end-of-line) (insert-and-inherit (concat " (" (my/org-agenda-calculate-efforts (next-single-property-change (point) 'day)) ")")) (forward-line))))) (add-hook 'org-agenda-finalize-hook 'my/org-agenda-insert-efforts) (defun ben/default-custom-agenda() "Functionally call custom agenda command bound to KEY" (interactive) (org-agenda nil "d")) (setf org-agenda-block-separator 61 org-agenda-breadcrumbs-separator " | " ;; https://stackoverflow.com/questions/58820073/s-in-org-agenda-prefix-format-doesnt-display-dates-in-the-todo-view org-agenda-prefix-format '((agenda . "%-t %? e%c%s") (todo . "%? e%c%s%(let ((scheduled (org-get-deadline-time (point)))) (if scheduled (format-time-string \" [%Y-%m-%d] \" scheduled) \"\"))") (tags . "%? e%c%s%(let ((scheduled (org-get-deadline-time (point)))) (if scheduled (format-time-string \" [%Y-%m-%d] \" scheduled) \"\"))") (search . "%? e%c%s")) org-agenda-deadline-leaders '("!D!: " "D%3d: " "") org-agenda-scheduled-leaders '("!S!: " "S%3d: " "") org-agenda-time-grid (quote ((daily today remove-match) (0600 0900 1200 1500 1800 2100) "......" "----------------")) org-columns-default-format-for-agenda "%75ITEM(Task) %10Effort(Estim){:} %10CLOCKSUM(ActTime) %5TODO(State)" org-columns-default-format "%75ITEM(Task) %10Effort(Estim){:} %10CLOCKSUM(ActTime) %5TODO(State)" org-global-properties '(quote (("Effort_ALL" . "0:00 0:10 0:30 1:00 1:30 2:00 2:30 3:00 4:00 5:00 6:00 7:00 8:00") ("STYLE_ALL" . "habit"))) org-agenda-columns-add-appointments-to-effort-sum t org-agenda-default-appointment-duration 0 org-agenda-log-mode-items '(closed state clock) org-agenda-start-with-log-mode t org-agenda-start-with-entry-text-mode t org-agenda-add-entry-text-maxlines 5 org-agenda-entry-text-maxlines 5 org-agenda-start-with-clockreport-mode nil org-agenda-custom-commands '( ;; ***** Default Agenda ("d" "Default (Master) Agenda" ((agenda "" ((org-agenda-span 1) (org-deadline-warning-days 7) (org-agenda-overriding-header "Today's Agenda\n"))) (tags "TODO=\"PROG\"" ((org-agenda-sorting-strategy '(priority-down deadline-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nTasks in Progress\n"))) (tags "TODO=\"NEXT\"" ((org-agenda-sorting-strategy '(priority-down deadline-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nAction Items\n") (org-agenda-skip-function '(org-agenda-skip-entry-if 'scheduled)))) ;; Presents only APPT and Routine Events. (agenda "" ((org-agenda-span '33) (org-agenda-start-on-weekday nil) (org-agenda-start-day "+1d") (org-agenda-entry-types '(:timestamp :sexp :scheduled)) (org-agenda-overriding-header "Routine & Appointments\n"))) (tags "+TODO=\"WAIT\"" ((org-agenda-sorting-strategy '(timestamp-down)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nDelegated/Waiting For\n"))) (tags "TODO=\"TODO\"" ((org-agenda-sorting-strategy '(category-keep)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nAll Tasks\n"))) (tags "TODO=\"PROJ\"" ((org-agenda-sorting-strategy '(category-keep)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nAll Projects\n"))) (stuck "" ((org-agenda-overriding-header "\nStuck Projects\n")))) ((org-agenda-tag-filter-preset '("-SDAY")))) ;; ***** Review Agenda ("r" "Review Agenda" ((tags "TODO=\"DONE\"" ((org-agenda-sorting-strategy '(priority-down deadline-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nCompleted Tasks\n"))) (tags "TODO=\"CXLD\"" ((org-agenda-sorting-strategy '(tsia-up)) (org-agenda-todo-keyword-format "%-3s") (org-agenda-overriding-header "\nTerminated Tasks\n"))) (stuck "" ((org-agenda-overriding-header "\nStuck Projects\n"))) (agenda "" ((org-agenda-span '33) (org-agenda-start-on-weekday nil) (org-agenda-start-day "+1d") (org-agenda-entry-types '(:timestamp :sexp :scheduled)) (org-agenda-overriding-header "Routine & Appointments\n")))) ((org-agenda-tag-filter-preset '("-SDAY"))))) org-agenda-window-setup 'current-window)
Organizational Buckets i.e. inbox dumps
Tasks are broken down into kinds. Because humans cannot bi-locate, all tasks needs to have a valid contextual location in which to accomplish them. This is done with tags which are prefixed with "@", 0errand - Tasks that must be completed out and about 0home - 0office 0docket - Instead of having a @John Doe, @Alice, @Bob tagging a task, you can signify such a group with a custom context. Tasks that must be completed in such a meeting setting. @John Doe - Say you have an agenda list of items for the next time you run into John Doe. Tasks that must be completed in John Doe's company
- A Projects list & Project Support Materials - 0projects.org
A comprehensive list. Can include delegated projects.
- Critical for control and focus
- Alleviates subtle tensions
- Projects often evolve.
- Core of the Weekly Review
- Facilitates relationship management
- Calendar actions and information - 0calendar.org
Does a project belong under 0projects or 0calendar? Answer this: Is the time specific appointment a subset of the project or vice versa?
Should an item that has a time context be put in 0calendar.org?
- YES - time specific - Appointments to be tracked Uses a timestamp, synced with google calendar.
- NO - day-specific action - time slot enlarged to entire days Use a scheduled timestamp, org refile to 0projects or 0solo
- NO - day-specific information - items that do not require action from YOU. Useful nonetheless:
Use the WAIT keyword and a scheduled timestamp, refile to 0projects or 0solo.
- Special events with a certain lead time for handling (product launches, fund- raisers, etc.)
- Regular events that you need to prepare for, such as budget reviews, annual conferences, planning events, or meetings (e.g., when should you add next year’s “Annual sales conference” or “Get kids set up for next school year”to your Projects list?)
- Key dates for significant people that you might want to do something about (birthdays, anniversaries, holiday gift giving, etc.)
- Seminars, conferences, speeches, and social and cultural events. It’s OK to decide not to decideas long as you have a decide-not-to-decide system.
- Big life or strategy decisions that require: Additional information needed from internal sources. Ex. you need to sleep on it. Justifiable reason to delay until all factors are visible and understood Create future trigger so you can feel comfortable just "hanging it out" for now.
- Next Actions lists - 0solo.org One off actions that you cannot neatly organize under a project. Ideally, of course, with enough self agency, most tasks should be under your projects list.
- Reference Material - project-jerome-index.org & 0contacts.org
- A Someday/Maybe list - 0someday.org
Refile a task here without changing any TODO keywords or tags. The file tag "-SDAY" excludes such entries from the Agenda.
If on reflection you realize that an optional project doesn’t have a chance of getting your attention for the next few months or more, move it to this list. Whatever ideas/ex-projects/processes on this list can have its own reference materials.
Keep in mind: ex-projects are projects that have lost part of their definition: action-ability. Please refer to the 5 step workflow diagram.
Difference between 0someday items and WAIT keyword items is the intersection between this organizational group and the calendar. Non actionable items that may need an action in the future. Refer to the incubate heading under chapter 6. Falls under calendar rule 3. day specific information. In order to keep with the theme of the calendar as sacred "hardlined" ground, ticklers (HOLD keyword tasks) must have a scheduled date, and exist in 0project or 0solo files.
- Things to get or build for your home
- Hobbies to take up
- Skills to learn
- Creative expressions to explore
- Clothes and accessories to buy
- Toys (hi-tech and otherwise!) to acquire
- Trips to take
- Organizations to join
- Service projects to contribute to
- Things to see and do
- Childrenthings to do with them
- Books to read
- Music to download
- Movies to see
- Gift ideas
- Web sites to explore
- Weekend trips to take
- IdeasMisc. (meaning you don’t know where else to put them!)
3.23.4. Org Attach Config
Attached images will show up in inline by using the , i l RET attachment:
with
no description. Toggle on with , T i
. If you look at the org mode manual, it
will provide detail into how attachments work. What is more pressing is how to
delete attachments after you have deleted their associated headline. The
following is a bash script that does exactly that, emacs - How to delete unused
org-mode attachment files from disc - Stack Over… .
#!/bin/sh ## Location where org-mode stores attachments datadir="$HOME/Dropbox/Documents/Org/data"; orgdir="$HOME/Dropbox/Documents/Org/" echo "The following files appear orphaned:"; files=$(find "$datadir" -type f|perl -ne 'print "$1\n" if /([^\/]*)\/[^\/]*$/'|uniq|while read id; do grep -qiR --include "*.org" "$id" "$orgdir" "*.org_archive" || find "$datadir" -ipath "*$id*" -type f; done) echo "$files" if [ "" == "$files" ]; then echo "Nothing to do!" exit fi echo "Delete? y/[n]" read delete case $delete in y) echo "$files" | while read fn; do rm "$fn"; done ## Delete empty subdirectories as well find $datadir -depth -type d -empty -delete; echo "Done." ;; *) echo "Not deleting anything!" ;; esac
(setf org-attach-id-dir "~/project-jerome/org-attach-data/" ;; https://helpdeskheadesk.net/2022-03-13/ ;; For org attach, change org timestamps to more human readable format. org-id-method 'ts org-attach-id-to-path-function-list '(org-attach-id-ts-folder-format org-attach-id-uuid-folder-format))
3.23.5. Org Babel Config
See examples here: GitHub - dfeich/org-babel-examples: Examples using emacs org mode babel inlin… Control how the results are outputted: Emacs Orgmode Source Code Blocks 2 | jherrlin Video Demonstration of org-babel Various header arguments to modify code upon execution
Key | Effect |
---|---|
, b t | org-babel-tangle Tangle all code blocks in the buffer |
, b v | org-babel-expand-source-block Expand and view code blocks with noweb syntax |
Remember to modify org-src-lang-modes
to enable the appropriate buffer when calling org-edit-special
with cursor inside a jupyter-sage code block.
As it is an alist, we can modify it like so. To really replace an element of an alist (say we wanted js2-mode instead of javascript-mode in my auto-mode-alist
).
(setf (cdr (rassoc 'javascript-mode auto-mode-alist)) 'js2-mode)
But since an alist by definition will shadow matches further down the list, we can instead use
(add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))
The reason why "jupyter-sage"
is set to python
and not sage-shell : sage-mode
is because I tried setting it directly and it does not work (in fact the whole sage-shell-mode went tits-up), and 2. python-mode is close enough.
Noweb should be used for single files, for that is its proper scope. Otherwise it is a one src block >> one file setup which allows us to use org-tangle sync. The reason is that noweb for a scope larger than a file means you have the mental overhead of maintaining 2 project/file structures for no conceivable reason or benefit. Also because org-babel-detangle and org-tanglesync do not work with nested src blocks (aka noweb).
Poly-org allows for cursor sensitive switching of major modes, handy to avoid
calling org-edit-special
all the time. However, you will have to return the
cursor to an org mode section in order to access the org mode major mode keybinding , b t
for org-babel-tangle
. This is why there exists a custom keybinding of org-babel-goto-source-block-head
to SPC a o b
.
;; For when you are lost in a long code block (spacemacs/set-leader-keys "aob" 'org-babel-goto-src-block-head) ;; Used below to rename org edit blocks ;; https://emacs.stackexchange.com/questions/2483/referring-to-the-org-babel-src-block-name-from-within-the-script ;; EDIT please change function so that src blocks with no name get a temporary ;;name. otherwise code highlighting is broken. (defun org-src--construct-edit-buffer-name (org-buffer-name lang) "Construct the buffer name for a source editing buffer." (concat (nth 4 (org-babel-get-src-block-info)) " [" lang "]")) ;; =SPC h d v "org-babel-load-languages" shows that emacs-lisp and ;; shell code is already enabled in org-babel. (org-babel-do-load-languages 'org-babel-load-languages (append org-babel-load-languages '((ledger . t) (calc . t) (js . t) (emacs-lisp . t) (shell . t) (lisp . t) ;; (mathematica . t) (latex . t) ;; (jupyter . t) ;; must be last ))) ;; Sanitize output and deal with paths (setq org-babel-mathematica-command (concat +project-maria-dir+ "mash.pl")) ;; Font-locking ;; (add-to-list 'org-src-lang-modes '("mathematica" . wolfram)) ;; (autoload 'wolfram-mode "wolfram-mode" nil t) ;; (autoload 'run-wolfram "wolfram-mode" nil t) ;; (setq wolfram-program "/home/ben/Wolfram/WolframEngine/12.2/Executables/WolframKernel") ;; (add-to-list 'auto-mode-alist '("\.m$" . wolfram-mode)) ;; (setq wolfram-path "~/.WolframEngine/Applications") ;; e.g. on Linux ~/.Mathematica/Applications ;; For wolfram-mode ;; (setq mathematica-command-line "~/project-maria/mash.pl") ;; (setq org-babel-python-command "/usr/bin/python3") ;; enable proper mode for sagemath code blocks ;; (add-to-list 'org-src-lang-modes '("jupyter-sage" . python)) ;; See library of babel > org babel org heading for more detail (defun org-in-tangle-dir (sub-path) "Expand the SUB-PATH into the directory given by the tangle-dir property if that property exists, else use the `default-directory'." (expand-file-name sub-path (or (org-entry-get (point) "tangle-dir" 'inherit) (default-directory))))
3.23.6. Org Brain Config
- GitHub - Kungsgeten/org-brain: Org-mode wiki + concept-mapping
- <–Personal Knowledge Management
- org-brain has great potential but maintainer is too busy : emacs
org-enable-org-brain-support
must be set to true in your dotspacemacs.
Ex. Brain Jerry's Brain
GitHub - Kungsgeten/org-brain: Org-mode wiki + concept-mapping]] Visit the github page for more information and keybinds
Key | Effect |
---|---|
SPC a o B v | org-brain-visualize |
v | org-brain-visualize from within org-brain buffer |
C-y | paste clipboard and insert as a resource (contextual bookmarks |
- org-brain user modifications - custom code Instead of auto including every single org headline into my brain, I have elected to manually include headlines. This renders the code block below obsolete, but I am keeping it for archival purposes.
(defun org-brain-ensure-ids-in-buffer () "Run `org-brain-get-id' on all headlines in current buffer. Only works if in an `org-mode' buffer inside `org-brain-path'. Suitable for use with `before-save-hook'." (interactive) ;; Checks to see if the open buffer is the bible, if so, do not run function (if (not(string-prefix-p (expand-file-name "~/project-maria/Holy-Bible-Douay-Rheims.org") (expand-file-name (buffer-file-name)))) (and (eq major-mode 'org-mode) (string-prefix-p (expand-file-name org-brain-path) (expand-file-name (buffer-file-name))) (org-map-entries #'org-brain-get-id t 'file))))
Files versus headings / One unified file versus many small files
Contrary to org-roam philosophy, I believe many small files to be less flexible than one unified file. This is not from the perspective of using and programming with database software, but rather primarily an org mode-centric perspective. If that is the case, then headings are the smallest atomic unit or building block to compose our secondary brain.
The one unified file versus many small files debate, is really a centralized versus decentralized debate. I believe in letting my primary org file, milliarium-aureum.org, to grow organically as large as possible before lag sets in. When it does, I will break off sections in ways that make sense. Another fringe benefit of having a single unified file is for org mode radio targets. Just remember to convert any radio targets before exporting a heading from the main file into its own file.
The custom code found list a above, is currently not being used. I have found it to be more flexible to manually call and insert IDs myself. This is why there is a custom binding,
, i I
, to insert an ID. You can also call the unmodified version of the command in PA section above to ensure IDs for all headings in the buffer you are currently editing. In a similar vein, you can use, d c
and, d e
to set a lifespan for an entry you are not sure should remain eternal.
(require 'org-brain) (require 'org-expiry) ;; Add CREATED property when adding a new org-brain headline entry (add-hook 'org-brain-new-entry-hook #'org-expiry-insert-created) (spacemacs/set-leader-keys "o SPC" 'org-brain-visualize-dwim) ;; For evil users, (with-eval-after-load 'evil (evil-set-initial-state 'org-brain-visualize-mode 'emacs)) ;; Automatically add ID properties to all org headlines when saving ;; Disabled because of slowdown, use org-id-get-create instead ;; (add-hook 'before-save-hook #'org-brain-ensure-ids-in-buffer) (defun org-expiry-created-comp (a b) "Compare `org-expiry-created-property-name' properties of A and B." (let ((ta (ignore-errors (org-time-string-to-seconds (org-entry-get (get-text-property 0 'org-marker a) org-expiry-created-property-name)))) (tb (ignore-errors (org-time-string-to-seconds (org-entry-get (get-text-property 0 'org-marker b) org-expiry-created-property-name))))) (cond ((if ta (and tb (< ta tb)) tb) -1) ((if tb (and ta (< tb ta)) ta) +1)))) (defun org-brain-timeline () "List all org-brain headlines in chronological order." (interactive) (let ((org-agenda-files (org-brain-files)) (org-agenda-cmp-user-defined #'org-expiry-created-comp) (org-agenda-sorting-strategy '(user-defined-down))) (org-tags-view nil (format "+%s>\"\"" org-expiry-created-property-name)))) (defun org-brain-cliplink-resource () "Add a URL from the clipboard as an org-brain resource. Suggest the URL title as a description for resource." (interactive) (let ((url (org-cliplink-clipboard-content))) (org-brain-add-resource url (org-cliplink-retrieve-title-synchronously url) t))) (define-key org-brain-visualize-mode-map (kbd "L") #'org-brain-cliplink-resource) ;; Prettify the lines via aa2u package, or ascii art to unicode (defface aa2u-face '((t . nil)) "Face for aa2u box drawing characters") (advice-add #'aa2u-1c :filter-return (lambda (str) (propertize str 'face 'aa2u-face))) (defun aa2u-org-brain-buffer () (let ((inhibit-read-only t)) (make-local-variable 'face-remapping-alist) (add-to-list 'face-remapping-alist '(aa2u-face . org-brain-wires)) (ignore-errors (aa2u (point-min) (point-max))))) (with-eval-after-load 'org-brain (add-hook 'org-brain-after-visualize-hook #'aa2u-org-brain-buffer)) (define-key org-brain-visualize-mode-map (kbd "j") #'evil-scroll-page-down) (define-key org-brain-visualize-mode-map (kbd "k") #'evil-scroll-page-up) (define-key org-brain-visualize-mode-map (kbd "i") #'org-brain-select-map) (define-key org-brain-visualize-mode-map (kbd "I") #'org-brain-select-dwim) (define-key org-brain-visualize-mode-map (kbd "s") #'link-hint-open-link) ;; Org-brain initialization (setf org-brain-path +project-maria-dir+ org-id-track-globally t org-brain-data-file "~/.emacs.d/.cache/.org-brain-data.el" org-id-locations-file "~/.emacs.d/.cache/.org-id-locations" org-brain-visualize-default-choices 'all org-brain-title-max-length 90 org-brain-include-file-entries nil org-brain-file-entries-use-title nil org-brain-headline-entry-name-format-string "%2$s" org-brain-quit-after-goto t org-brain-backlink "<--" org-expiry-inactive-timestamps t)
3.23.7. Org Contacts Config
A flat file of org headings is the simplest and in the unlikely case that I exceed dunbar's number, there is GitHub - girzel/ebdb: An EIEIO port of BBDB, Emacs' contact-management package For further customization options, check out: GitHub - tmalsburg/helm-org-contacts: A helm source address books in org-cont…
An evaluation of other contact management software in Emacs.
;; Require org-contacts to work with mu4e (require 'org-contacts) (setf org-contacts-files (list (concat +project-maria-dir+ "0contacts.org")))
3.23.8. Org Download Config
(setf org-download-method 'attach)
3.23.9. Org Expiry Config
;; Add key bindings for org-expiry package (spacemacs/set-leader-keys-for-major-mode 'org-mode "dc" 'org-expiry-insert-created) (spacemacs/set-leader-keys-for-major-mode 'org-mode "de" 'org-expiry-insert-expiry) ;; Add call to org-expiry-insert-created every time org-id-get-create is run (advice-add 'org-id-get-create :after 'org-expiry-insert-created)
3.23.10. Org Mime Config
(setf org-mime-export-options '(:section-numbers nil ;; otherwise tables will not work :with-broken-links t :with-author nil :with-toc nil :with-latex dvipng))
3.23.11. Org Re Reveal Config
Add audio to presentation? oer / emacs-reveal · GitLab
Example presentation.
# Local IspellDict: en #+Title: 21st Sunday in Ordinary Time #+Author: Blessed Fredereick Ozanam * Welcome :PROPERTIES: :reveal_background: https://s3.amazonaws.com/libapps/accounts/35417/images/Pere_Marquette_preaching.JPG :END: #+begin_quote Reading 1 > come to gather nations of every language; > how can they have faith? through hearing the word > missionaries. #+end_quote * First Reading - Isaiah 66:18-21 :PROPERTIES: :reveal_background: https://images.metmuseum.org/CRDImages/ep/original/DP145412.jpg :END: #+begin_quote *Thus says the LORD: I know their works and their thoughts, and I come to gather nations of every language; they shall come and see my glory. I will set a sign among them; from them I will send fugitives to the nations: to Tarshish, Put and Lud, Mosoch, Tubal and Javan, to the distant coastlands that have never heard of my fame, or seen my glory; and they shall proclaim my glory among the nations. #+end_quote * First Reading - Isaiah 66:18-21 :PROPERTIES: :reveal_background: https://i.etsystatic.com/14907812/r/il/5d0680/2194229035/il_fullxfull.2194229035_q65f.jpg :END: #+begin_quote They shall bring all your brothers and sisters from all the nations as an offering to the LORD, on horses and in chariots, in carts, upon mules and dromedaries, to Jerusalem, my holy mountain, says the LORD, just as the Israelites bring their offering to the house of the LORD in clean vessels. Some of these I will take as priests and Levites, says the LORD. #+end_quote * Responsorial Psalm - Psalm 117:1, 2 *R: Go out to all the world and tell the Good News.* Praise the LORD, all you nations; glorify him, all you peoples! For steadfast is his kindness toward us, and the fidelity of the LORD endures forever. https://www.hearthymn.com/wp-content/uploads/2016/03/Jesus-Christ.jpg * Second Reading - Hebrews 12:5-7, 11-13 :PROPERTIES: :reveal_background: https://uploads7.wikiart.org/images/domenico-ghirlandaio/the-trial-by-fire-st-francis-before-the-sultan-of-egypt-1485.jpg!Large.jpg :END: #+begin_quote Brothers and sisters, You have forgotten the exhortation addressed to you as children: "My son, do not disdain the discipline of the Lord or lose heart when reproved by him; for whom the Lord loves, he disciplines; he scourges every son he acknowledges." Endure your trials as "discipline"; God treats you as sons. For what "son" is there whom his father does not discipline? #+end_quote * Second Reading - Hebrews 12:5-7, 11-13 :PROPERTIES: :reveal_background: https://www.baptistpress.com/wp-content/webpc-passthru.php?src=https://www.baptistpress.com/wp-content/uploads/2022/03/crowns-iStock.jpeg&nocache=1 :END: #+begin_quote At the time, all discipline seems a cause not for joy but for pain, yet later it brings the peaceful fruit of righteousness to those who are trained by it. So strengthen your drooping hands and your weak knees. Make straight paths for your feet, that what is lame may not be disjointed but healed. #+end_quote * The Gospel - Luke 13:22-30 :PROPERTIES: :reveal_background: https://upload.wikimedia.org/wikipedia/commons/b/b2/Der_breite_und_der_schmale_Weg_2008.jpg :END: Jesus passed through towns and villages, teaching as he went and making his way to Jerusalem. Someone asked him, "Lord, will only a few people be saved?" He answered them, "Strive to enter through the narrow gate, for many, I tell you, will attempt to enter but will not be strong enough. After the master of the house has arisen and locked the door, then will you stand outside knocking and saying, 'Lord, open the door for us.' He will say to you in reply, 'I do not know where you are from. * The Gospel - Luke 13:22-30 :PROPERTIES: :reveal_background: https://www.catholicdigest.com/wp-content/uploads/2016/10/BVM-and-Purgatory.jpg :END: And you will say, 'We ate and drank in your company and you taught in our streets.' Then he will say to you, 'I do not know where you are from. Depart from me, all you evildoers!' And there will be wailing and grinding of teeth when you see Abraham, Isaac, and Jacob and all the prophets in the kingdom of God and you yourselves cast out. And people will come from the east and the west and from the north and the south and will recline at table in the kingdom of God. For behold, some are last who will be first, and some are first who will be last." * Homily :PROPERTIES: :reveal_background: https://images.unsplash.com/photo-1616686590634-dc2534bc5062?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8M3x8Y2h1cmNoJTIwc3RhaW5lZCUyMGdsYXNzJTIwd2luZG93fGVufDB8fDB8fA%3D%3D&w=1000&q=80 :END: #+begin_quote Insert homily text here, lorem ipsum lorem ipsum lorem ipsum #+end_quote * Homily :PROPERTIES: :reveal_background: https://christchurchrawdon.files.wordpress.com/2011/03/window6.jpg :END: #+begin_quote Insert homily text here, lorem ipsum lorem ipsum lorem ipsum #+end_quote * Homily :PROPERTIES: :reveal_background: https://www.centralunitedchurch.org/wp-content/uploads/2021/09/sg6.jpg :END: #+begin_quote Insert homily text here, lorem ipsum lorem ipsum lorem ipsum #+end_quote * Prayers of the Faithful :PROPERTIES: :reveal_background: https://wp.cruxnow.com/wp-content/uploads/2021/06/20180330T1222-16045-CNS-NEW-CATHOLICS-EASTER-VIGIL.jpg :END: #+begin_quote R: Loving God, hear our Prayer. #+end_quote * Hail Mary :PROPERTIES: :reveal_background: https://udayton.edu/imri/mary/_resources/img/lit-seasons-and-feasts/page-image-solemnity-of-marys-assumption-rubens.png :END: #+begin_quote Hail, Mary, full of grace, the Lord is with thee. Blessed art thou amongst women and blessed is the fruit of thy womb, Jesus. Holy Mary, Mother of God, pray for us sinners, now and at the hour of our death. Amen. #+end_quote * Prayer to St. Michael the Archangel :PROPERTIES: :reveal_background: https://i.ytimg.com/vi/TIeHqbwNYOw/maxresdefault.jpg :END: #+begin_quote St. Michael the Archangel, defend us in battle, be our protection against the wickedness and snares of the devil. May God rebuke him we humbly pray; and do thou, O Prince of the Heavenly host, by the power of God, cast into hell Satan and all the evil spirits who prowl about the world seeking the ruin of souls. Amen. #+end_quote * Announcements :PROPERTIES: :reveal_background: https://images.unsplash.com/photo-1632230997264-b2bfc65cb8b4?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8c3RhaW5lZCUyMGdsYXNzJTIwd2luZG93fGVufDB8fDB8fA%3D%3D&w=1000&q=80 :END: Insert announcement text here, * Closing :PROPERTIES: :reveal_background: https://catholiclife.diolc.org/wp-content/uploads/2017/11/saints.jpg :END: #+begin_quote Gospel > And people will come from the east and the west and from the north and the south and will recline at table in the kingdom of God. > And what is on the table? > The food that gives eternal life. #+end_quote
(require 'org-re-reveal) (setf org-re-reveal-revealjs-version "4" org-re-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js")
3.23.12. Org Sticky Headers Config
(setq org-sticky-header-full-path 'full)
3.23.13. Ox Publish Config
Note that when editing this config you MUST properly escape " characters and avoid the use of the literal % character unless you are using it as intended i.e. %C
;; Following 2 lines are needed to exclude parent heading from table of contents but still export the content ;; https://emacs.stackexchange.com/questions/30183/orgmode-export-skip-ignore-first-headline-level (require 'ox-extra) (ox-extras-activate '(ignore-headlines)) ;; Allows exporting bibtex citations to html (require 'ox-bibtex) ;; Exclude default CSS from html export and add external stylesheet (setq org-html-head-include-default-style nil) ;; Omit inline css as we use an imported stylesheet (setq org-html-htmlize-output-type 'css) ;; https://www.taingram.org/blog/org-mode-blog.html (setq org-export-global-macros '(("timestamp" . "@@html:<span class=\"timestamp\">[$1]</span>@@"))) (defun my/org-sitemap-date-entry-format (entry style project) "Format ENTRY in org-publish PROJECT Sitemap format ENTRY ENTRY STYLE format that includes date." (let ((filename (org-publish-find-title entry project))) (if (= (length filename) 0) (format "*%s*" entry) (format "{{{timestamp(%s)}}} [[file:%s][%s]]" (format-time-string "%Y-%m-%d" (org-publish-find-date entry project)) entry filename)))) (setf org-publish-project-alist '(("blog" :components ("blog-content" "blog-rss")) ("blog-content" :base-directory "~/project-maria/blog" :html-extension "html" :base-extension "org" :recursive t :publishing-function org-html-publish-to-html :publishing-directory "~/common-lisp/project-isidore/assets/blog" :section-numbers t :table-of-contents t :exclude "rss.org" :with-title nil :auto-sitemap t :sitemap-filename "archive.org" :sitemap-title "Blog Archive" :sitemap-sort-files anti-chronologically :sitemap-style tree :sitemap-format-entry my/org-sitemap-date-entry-format ;; Use HTML5 ;; https://orgmode.org/manual/HTML-doctypes.html#HTML-doctypes :html-doctype "html5" :html-html5-fancy t ;; Link to external custom stylesheet ;; If you need code highlight from highlight.js, include the latter three lines. :html-head " <link rel=\"stylesheet\" type=\"text/css\" href=\"../global.css\"/> <link rel=\"stylesheet\" href=\"//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/styles/base16/solarized-light.min.css\"> <script src=\"//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/highlight.min.js\" defer></script> <script>var hlf=function(){Array.prototype.forEach.call(document.querySelectorAll(\"pre.src\"),function(t){var e;e=t.getAttribute(\"class\"),e=e.replace(/src-(\w+)/,\"src-$1 $1\"),console.log(e),t.setAttribute(\"class\",e),hljs.highlightBlock(t)})};addEventListener(\"DOMContentLoaded\",hlf);</script>" :html-preamble " <div class=\"header header-fixed\"> <div class=\"navbar container\"> <div class=\"logo\"><a href=\"/\">BHW</a></div> <input type=\"checkbox\" id=\"navbar-toggle\" > <label for=\"navbar-toggle\"><i></i></label> <nav class=\"menu\"> <ul> <li><a href=\"/about\">About</a></li> <li><a href=\"/work\">Work</a></li> <li><a href=\"/assets/blog/archive.html\">Blog</a></li> <li><a href=\"/contact\">Contact</a></li> </ul> </nav> </div> </div> <h1 class=\"title\">%t</h1> <p class=\"subtitle\">%s</p> <br/> <p class=\"updated\"><a href=\"/contact#article-history\">Updated:</a> %C</p>" ;; Article Postamble includes ;; Javascript snippet to insert anchor links to Table of Contents ;; HTML Footer :html-postamble "<script> const headers = Array.from( document.querySelectorAll('h2, h3, h4, h5, h6') ); headers.forEach( header => { header.insertAdjacentHTML('afterbegin', '<a href=\"#table-of-contents\">⇱</a>' ); }); </script> <hr/> <footer> <div class=\"copyright-container\"> Comments? Corrections? <a href=\"https://bhw.name/contact\"> Please do reach out.</a><a href=\"https://bhw.name/blog/rss.xml\"> RSS Feed. </a><a href=\"https://bhw.name/subscribe\"> Mailing List. </a><br/> Copyright 2021 Benedict H. Wang. <br/> Blog content is available under <a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/4.0/\"> CC-BY-SA 4.0 </a> unless otherwise noted.<br/> Created with %c on <a href=\"https://www.gnu.org\">GNU</a>/<a href=\"https://www.kernel.org/\">Linux</a><br/> </div> </footer>" ) ("blog-rss" :base-directory "~/project-maria/blog" :base-extension "org" :publishing-directory "~/common-lisp/project-isidore/assets/blog" :publishing-function publish-posts-rss-feed :rss-extension "xml" :html-link-home "http://bhw.name/" :html-link-use-abs-url t :html-link-org-files-as-html t :exclude "archive.org" :auto-sitemap t :sitemap-function posts-rss-feed :sitemap-title "Benedict H. Wang Blog RSS" :sitemap-filename "rss.org" :sitemap-style list :sitemap-sort-files anti-chronologically :sitemap-format-entry format-posts-rss-feed-entry) )) ;; https://alhassy.github.io/AlBasmala#Clickable-Headlines (defun my/ensure-headline-ids (&rest _) "Org trees without a custom ID will have All non-alphanumeric characters are cleverly replaced with ‘-’. If multiple trees end-up with the same id property, issue a message and undo any property insertion thus far. E.g., ↯ We'll go on a ∀∃⇅ adventure ↦ We'll-go-on-a-adventure " (interactive) (let ((ids)) (org-map-entries (lambda () (org-with-point-at (point) (let ((id (org-entry-get nil "CUSTOM_ID"))) (unless id (thread-last (nth 4 (org-heading-components)) (s-replace-regexp "[^[:alnum:]']" "-") (s-replace-regexp "-+" "-") (s-chop-prefix "-") (s-chop-suffix "-") (setq id)) (if (not (member id ids)) (push id ids) (message-box "Oh no, a repeated id!\n\n\t%s" id) (undo) (setq quit-flag t)) (org-entry-put nil "CUSTOM_ID" id)))))))) ;; Whenever html & md export happens, ensure we have headline ids. (advice-add 'org-html-export-to-html :before 'my/ensure-headline-ids) (advice-add 'org-md-export-to-markdown :before 'my/ensure-headline-ids) ;; https://nicolasknoebber.com/posts/blogging-with-emacs-and-org.html (defun format-posts-rss-feed-entry (entry _style project) "Format ENTRY for the posts RSS feed in PROJECT." (org-publish-initialize-cache "blog-rss") (let* ((title (org-publish-find-title entry project)) (link (concat "blog/" (file-name-sans-extension entry) ".html")) (author (org-publish-find-property entry :author project)) (pubdate (format-time-string (car org-time-stamp-formats) (org-publish-find-date entry project)))) (message pubdate) (format "%s :properties: :rss_permalink: %s :author: %s :pubdate: %s :end:\n" title link author pubdate))) (defun posts-rss-feed (title list) "Generate a sitemap of posts that is exported as a RSS feed. TITLE is the title of the RSS feed. LIST is an internal representation for the files to include. PROJECT is the current project." (concat "#+TITLE: " title "\n#+EMAIL: seneschal@bhw.name" "\n\n" (org-list-to-subtree list))) (defun publish-posts-rss-feed (plist filename dir) "Publish PLIST to RSS when FILENAME is rss.org. DIR is the location of the output." (if (equal "rss.org" (file-name-nondirectory filename)) (org-rss-publish-to-rss plist filename dir)))
3.23.14. Org Tanglesync Config
(add-hook 'org-mode 'org-tanglesync-mode) (add-hook 'prog-mode 'org-tanglesync-watch-mode) (add-hook 'text-mode 'org-tanglesync-watch-mode) (setf org-tanglesync-default-diff-action ':diff org-tanglesync-watch-files '("dotfiles.org")) (spacemacs/set-leader-keys-for-major-mode 'org-mode "bS" 'org-tanglesync-process-buffer-interactive)
3.24. Org Noter Config
Key | Description | Where? |
---|---|---|
i | Insert note | Document buffer |
M-i | Insert precise note | Document buffer |
q | Kill session | Document buffer |
M-p | Sync previous page/chapter | Document and notes buffer |
M-. | Sync current page/chapter | Document and notes buffer |
M-n | Sync next page/chapter | Document and notes buffer |
C-M-p | Sync previous notes | Document and notes buffer |
C-M-. | Sync selected notes | Document and notes buffer |
C-M-n | Sync next notes | Document and notes buffer |
Note that syncing feature is to accomodate the feature of org-noter that allow multiple frames of notes to be open on the same file.
(setf org-noter-always-create-frame nil org-noter-hide-other nil org-noter-auto-save-last-location t) (spacemacs/set-leader-keys "aon" 'org-noter)
3.25. Org Recoll Config
;; (load "~/.emacs.d/private/local/org-recoll.el") ;; (setq org-recoll-results-num 50) ;; (spacemacs/set-leader-keys "ss" 'org-recoll-search)
3.26. Org Web Tools Config
;; Fix for wget option flags, as per https://github.com/alphapapa/org-web-tools/issues/35 (setq org-web-tools-archive-wget-options '("--ignore-tags=script,iframe" "--reject=eot,ttf,svg,otf,*.woff*" "--execute" "robots=off" "--adjust-extension" "--span-hosts" "--convert-links" "--page-requisites" "--timestamping" "--no-directories")) (setq org-web-tools-archive-wget-html-only-options '("--execute" "robots=off" "--adjust-extension" "--timestamping" "--no-directories"))
3.27. Pandoc Config
Convert Org Mode files to docx with CMake and Pandoc for mobile accessibility…
See .bashrc
function w2o (word to org)
3.28. Paradox Config
(setf paradox-github-token t)
3.29. PDF Tools Config
PDF Tools uses a C library to convert PDF (which are images) to PNG format to store in Emacs memory. Naturally, a high DPI resolution with low memory could mean performance issues. See https://github.com/politza/pdf-tools/search?p=1&q=memory&type=issues and the new forked repository at https://github.com/vedang/pdf-tools/ for more details.
Installation: for the first time run, please make sure to M-x
pdf-tools-install
pdf-occur notes: lines matching PRCE means Perl Compatible Regular Expressions. See regex list here: PCRE Regular Expression Cheatsheet - Debuggex
Key | Effect |
---|---|
, s s | calls pdf-occur |
g t | goto page # |
;; If bash $top shows high emacs memory usage, try the following. ;; Not sure if they work tbh. (pdf-cache-clear-data) (garbage-collect)
(setf pdf-view-use-scaling t pdf-view-display-size 'fit-width pdf-view-resize-factor 1.1 image-cache-eviction-delay 128 pdf-cache-image-limit 128) ;; Custom function to allow double page scrolling by calling ;; my-pdf-view-double-scroll-horizontal-view (defun my-pdf-view-double-scroll-up-or-next-page (&optional arg) "Scroll page up ARG lines if possible, else go to the next page. When `pdf-view-continuous' is non-nil, scrolling upward at the bottom edge of the page moves to the next page. Otherwise, go to next page only on typing SPC (ARG is nil)." (interactive "P") (if (or pdf-view-continuous (null arg)) (let ((hscroll (window-hscroll)) (cur-page (pdf-view-current-page))) (when (or (= (window-vscroll) (image-scroll-up arg)) ;; Workaround rounding/off-by-one issues. (memq pdf-view-display-size '(fit-height fit-page))) (pdf-view-next-page 2) (when (/= cur-page (pdf-view-current-page)) (image-bob) (image-bol 1)) (set-window-hscroll (selected-window) hscroll))) (image-scroll-up arg))) (defun my-pdf-view-double-scroll-horizontal-view () (interactive) (my-pdf-view-double-scroll-up-or-next-page) (other-window 1) (my-pdf-view-double-scroll-up-or-next-page) (other-window 1)) ;; add spacemacs major mode keybind (spacemacs/set-leader-keys-for-major-mode 'pdf-view-mode "d" 'my-pdf-view-double-scroll-horizontal-view) ;; Allow rotating of sheet music in pdfs (defun pdf-view--rotate (&optional counterclockwise-p page-p) "Rotate PDF 90 degrees. Requires pdftk to work.\n Clockwise rotation is the default; set COUNTERCLOCKWISE-P to non-nil for the other direction. Rotate the whole document by default; set PAGE-P to non-nil to rotate only the current page. \nWARNING: overwrites the original file, so be careful!" ;; error out when pdftk is not installed (if (null (executable-find "pdftk")) (error "Rotation requires pdftk") ;; only rotate in pdf-view-mode (when (eq major-mode 'pdf-view-mode) (let* ((rotate (if counterclockwise-p "left" "right")) (file (format "\"%s\"" (pdf-view-buffer-file-name))) (page (pdf-view-current-page)) (pages (cond ((not page-p) ; whole doc? (format "1-end%s" rotate)) ((= page 1) ; first page? (format "%d%s %d-end" page rotate (1+ page))) ((= page (pdf-info-number-of-pages)) ; last page? (format "1-%d %d%s" (1- page) page rotate)) (t ; interior page? (format "1-%d %d%s %d-end" (1- page) page rotate (1+ page)))))) ;; empty string if it worked (if (string= "" (shell-command-to-string (format (concat "pdftk %s cat %s " "output %s.NEW " "&& mv %s.NEW %s") file pages file file file))) (pdf-view-revert-buffer nil t) (error "Rotation error!")))))) (defun pdf-view-rotate-clockwise (&optional arg) "Rotate PDF page 90 degrees clockwise. With prefix ARG, rotate entire document." (interactive "P") (pdf-view--rotate nil (not arg))) (defun pdf-view-rotate-counterclockwise (&optional arg) "Rotate PDF page 90 degrees counterclockwise. With prefix ARG, rotate entire document." (interactive "P") (pdf-view--rotate :counterclockwise (not arg))) (define-key spacemacs-pdf-view-mode-map (kbd "R") 'pdf-view-rotate-clockwise)
3.30. Plant UML Config
sudo apt install graphviz plantuml
Download Plantuml.jar and place it in the root of your home directory, at ~/plantuml.jar. Control output type with plantuml-output-type
. Org babel file header is required.
,---. ,-----. |Bob| |Alice| `-+-' `--+--' | hello | |-------------->| ,-+-. ,--+--. |Bob| |Alice| `---' `-----'
(setq plantuml-default-exec-mode 'jar plantuml-jar-path "/usr/share/plantuml/plantuml.jar" org-plantuml-jar-path "/usr/share/plantuml/plantuml.jar" plantuml-output-type "txt") (with-eval-after-load "org-mode" (add-to-list 'org-src-lang-modes '("plantuml" . plantuml)))
3.31. Poly Org Config
(use-package poly-org :after org)
3.32. Python Config
On Debian 12, install the Python implementation, the package manager and virtual environment library.
sudo apt install python3 python3-pip python3-venv python3 --version pip3 --version mkdir myproject && cd myproject python3 -m venv env source env/bin/activate
The command in emacs is pyvenv-workon (, v w
) to switch virtual environments.
Install common python tooling globally,
# Install LSP server + upgrade to JSON RPC 2.0, import sorter, code formatting, # code refactoring sudo apt install python3-pylsp python3-pylsp-jsonrpc python3-pylsp-isort python3-pylsp-black python3-rope
(setf python-format-on-save t python-indent-offset 4)
3.33. Shell Config
Key | Effect |
---|---|
M-! | Shell-command. Prefix with C-u (SPC-u for spacemacs) to insert output at point |
M-S-\ | Shell-command-on-region. Pipe region into shell command |
M-: | Eval s-exp |
;; Forces bash shell into interactive mode, leadings to sourcing of ;; ~/.bashrc and interactive aliases and functions ;; (setq shell-command-switch "-ic") ;; Default value was "-c" (setq shell-command-switch "-c")
3.34. Yasnippet Config
;; https://github.com/joaotavora/yasnippet/issues/998#issuecomment-496449546 (defun my-yas-try-expanding-auto-snippets () (when (and (boundp 'yas-minor-mode) yas-minor-mode) (let ((yas-buffer-local-condition ''(require-snippet-condition . auto))) (yas-expand)))) (add-hook 'post-command-hook #'my-yas-try-expanding-auto-snippets)
Belongs to the auto-completion layer in spacemacs Jack of Some on youtube has a fantastic tutorial on yasnippet
Key | Effect |
---|---|
M-/ | expand snippet using hippie expand |
3.35. Youtube Sub Extractor Config
(require 'youtube-sub-extractor)
4. Spacemacs Reference Manual
A personal keybinding file is a useful for software like (spac)emacs. There is a vast expanse of possible commands, shortcuts and various Emacs/vim/evil layer interactions. Some may find the sheer breadth of cutomizability suffocating, but it is in conjuction with the emacs theme of the tool serving you. Recording useful bindings makes learning spacemacs a more managable task. View content under Bare Minimum header. Then skip to Org-mode header and view that. “Tell me and I will forget, show me and I may remember; involve me and I will understand.” Finally, author recommends user creating a personal org file for the same purpose. The rest of the file are keybinds/notes tailored specifically to the author, which you many find useful anyways. Hope this has helped.
4.1. Information for Completely New Beginners
For beginners and my future (forgetful) self: The only file you should touch to customize Spacemacs is ~/.spacemacs (or ~/.spacemacs.d/init.el if you prefer having a directory). You shouldn't touch anything within ~/.emacs.d. This rule holds true unless you are installing local packages, sending a pull request etc. If you know what you are doing, you don't need this guide anymore. You shouldn't have any ~/.emacs file either. The ~/.spacemacs file is structured with the following functions:
There are major-mode and minor-mode. These are not related to the fact they apply to only one or all buffers. Instead, each buffer has one, and only one, major-mode (like python-mode, ruby-mode, etc…). Each buffer can have several minor-mode (like linum-mode). Some minor-mode are global in the sense they will affect all buffers, like global-centered-cursor-mode.
Emacs lisp variables can be global or buffer-local. Changing a global variable will affect all buffers. Changing a buffer-local variable with (setq … will affect only the current buffer. It is possible to change the default value of a buffer-local variable with (setq-default …. This will change the value for all newly created buffers.
buffer-local variables have default values, but they may be overridden by hooks when entering some given mode. The modify such values for some kind of buffers a function should be added to the hook, for instance:
(setq-default fill-column 80) (add-hook 'mail-mode-hook (lambda () (setq fill-column 72))) (add-hook 'python-mode-hook (lambda () (setq fill-column 79)))
Spacemacs indeed provides some toggle functions for some functionalities. They are called (spacemacs/toggle-…) and adding -on or -off at the end enable or disable them.
«I want to be able to answer the questions: "Oh, I want to customize that behavior, where do I need to code? What are the methods I should call? What are the methods I should NOT call? What variable can I change/create? What is actually executed when I put my code here?…etc"»:
Spacemacs, like Emacs or vim, is a powerful tool. Like every powerful tool, it requires some time to get used to it, to be comfortable with. If you want to start piloting a plane, you'll not intuitively know what button to press to do this or that. If you want to achieve something, you have to go through a really long manual, or get an instructor. It's the same for Spacemacs. There is a documentation, a quick-start and a migrating from vim documents. They are quite long, but it's because the range of possibilities are as-long as the documents. The other way is to get help from some "instructor", i.e. Spacemacs regular contributors. I would recommend you to come to the gitter room which is quite active and hopefully helpful.
4.2. Spacemacs Navigation & Searching
Search is divided into two categories: File name search, and File content search. Efficient navigation relies on a proper understanding of searching and its scopes.
fd
pressed together will act as ESC, see evil-escape package *currently disabled for author, see dotspacemacs excluded.C-g
will also act as ESC in situations wherefd
orESC
fail you.- SUPER IMPORTANT Use remapkey.exe (on windows) to swap the following:
- Swap ESC and Caps Lock
- Swap both left ctrl with left alt & right ctrl with right alt
- Swap the windows key with left alt
SPC SPC
acts asM-x
4.2.1. Searching - File Content
- Scope: Computer (All Files) using fd-find. Note org-recoll as an option to search all file contents, such as all PDF's in Project Jerome.
Scope: Project (projectile.el defines this as any directory you have defined as the "root directory" by placing a .projectile file in said directory) Thanks to: the silver searcher (ag) as it allows as to fuzzy search.
-G*.cljs -w time - search for the word "time" in all .cljs files
-tclojure time - search for "time" in all .{clj,cljs,cljc} files
-uno\ due\ tre - search for the string "uno duo tre"
-C5 foo - search for "foo" but show 5 lines of context before and after the match.
-(?:^|[^\w-])time(?:[^\w-]|$) - search for lisp-word "time", i.e. search for the full word "time" while considering "-" to be a word characer
- Search for
Key Effect SPC / Also performs search project, same as SPC s p SPC * Performs SPC / command with symbol under cursor SPC s C-s Helm-swoop within open buffers SPC p t Opens up treemacs sidebar in project view , g g With cursor in function, search that function SPC s SPC Custom function calling rg-dir for project-maria Scope: File/Buffer Thanks to: Helm-occur
Key Effect SPC s c Clears the red underlining of search matched text ? Helm-occur with symbol under cursor - Jumps within visible file/buffer or visible buffer search (buffer navigation)
My scheme for navigating the visible buffer:
- For short hops within a line or a couple of lines in a buffer I
- Jumps within visible file/buffer or visible buffer search (buffer navigation)
My scheme for navigating the visible buffer:
/t/F/T. ct)
etc are goldies. Make sure to use evil-snipe package for improved
fFTt
search behaviour, namely highlighting and repeated search with fFTt
instead of ;
(This freed-up home row key can be rebound to?). Secondly,
evil-snipe allows you to set evil-snipe-aliases
so that the previous ct)
can
be typed ct]
and will include ct)
, ct]
, and ct}
. Check the 3.11.1 commentary on spacemacs. Remember s
and p
stand for sentence and
paragraph respectively when used in context with a vim operator. Ex. d a s
translates to "delete around a sentence".
- For medium hops across all visible frames, windows and buffers, I
use
avy-goto-word-or-subword-1
on s, since s in vim is basically useless (see r and c). These are fully compatible with vim commands. So e.g. I used s <two char sequence>
all the time for quickly deleting blocks of text. - Hoping past what I can see, but still within the file, helm-swoop simply
outclasses /. I almost never use /, so rebind it to
helm-swoop
in your evil config.
avy-goto-char-timer > type more than one letter. timer can be shortened or lengthened.
Key | Effect |
---|---|
SPC j j | Avy-timer > Jump to specific letter |
SPC j w | Avy-word > Jump to specific word |
SPC j b | Go to previous jump location |
g ; | Go to last edit |
ctrl-o | jump back |
4.2.2. Searching - File Name
We only need one command for this: helm-for-files
. Use C-h f
to find
out docstrings, but basically it runs through our buffer list (what is a
buffer?), then our recentf list, then our bookmarks, our file caches, then
files in current dir before resorting to helm-fd.
See Unix locate
(implemented as mlocate, plocate etc) and Unix find
(implemented as GNU find and fd)
This command will allow you to find files ANYWHERE. As long as you know the pathname, of course. A primer on fd.
4.2.3. Searching - Directory
Key | Effect |
---|---|
SPC f d | Call helm-find-files with a prefix |
SPC f b | Access bookmarks list |
4.2.4. Searching - World Wide Web
Google alternatives:
Wikipedia https://hn.algolia.com/ Appending reddit to search term https://search.marginalia.nu/ Duck Duck go, Bing etc.
Web Scraping
4.2.5. Searching - Handling Directories with Dired
Key | Effect |
---|---|
( | Toggles simple view |
0w | (dired-copy-filename-as-kill &optional ARG |
S | Toggle sort by A-Z and last edited |
Explanation of w command: Copy names of marked (or next ARG) files into the kill ring. The names are separated by a space. With a zero prefix arg, use the absolute file name of each marked file.
4.2.6. Navigation - Project Manipulation
What is a project? Spacemacs uses projectile.el (pre-installed) to manage projects.
- For those with coding backgrounds, any directory with a git repo will automatically be considered a project.
- Absent a .git folder, a .projectile file will mark it as a project to projectile.
Key | Effect |
---|---|
SPC SPC then type * | *=projectile-add-known-project |
SPC p p | Switch Projects |
4.2.7. Search and Replace
How do I search and replace a section of the buffer?
Turn on and use line numbers, SPC t n a
.
:5,12s/foo/bar/g
How do I yank all matching lines into one buffer?
:g/^{pattern}/yank A
This runs the global command to yank any line that matches ^{pattern} and put it in register a. Because a is uppercase, instead of just setting the register to the value, it will append to it. Since the global command run the command against all matching lines, as a result you will get all lines appended to each other.
What this means is that you probably want to reset the register to an empty string before starting: :let @a="".
And naturally, you can use the same with any named register. How can I execute vim commands on matching patterns?
:g/{pattern}/normal nd$
Explanation: On each line, where pattern matches, execute the following normal mode commands nd$. With the cursor at the start of the line, 'n' jumps to the pattern, and 'd$' deletes to the end of the line.
How to execute a vim commands on every single line?
:%norm fED
This tells vim to press fED on each line as if you had typed it in normal mode. fE will move the cursor forward to the first E, and D deletes everything until the end of the line.
How to capture all subsequent text on a line after a pattern match
\(.*\)
captures all subsequent text on the line.
Incrementally replace a given string pic1, pic1, pic1 > pic1, pic2, pic3 etc.
C-v
and highlight 1- M-x cua-rectangle-mark-mode
M-n and set appropriate values
See the following if the above does not work EmacsWiki: Numbers In Registers.
How do I remove all blank lines from a buffer?
This is a frequent question so I figured I’d mention the solution here:
You want to remove all empty (blank) lines from a buffer. How do you do it? Well, it’s super easy.
Mark what you want to change (or use C-x h to mark the whole buffer) and run this:
M-x flush-lines RET ^$ RET
And you’re done. So what does that mean? Well, M-x flush-lines will flush (remove) lines that match a regular expression, and ^$ contain the meta-characters ^ for beginning of string and $ for end of string. Ergo, if the two meta-characters are next to eachother, it must be a blank line.
We can also generalize it further and remove lines that may have whitespace (only!) characters:
M-x flush-lines RET ^\s-*$ RET
In this case \s- is the syntax class (type C-h s to see your buffer’s syntax table) for whitespace characters. The * meta-character, in case you are not a regexp person, means zero or more of the preceding character.
Source: https://emacs.stackexchange.com/questions/48526/how-do-i-delete-all-blank-lines-in-a-buffer
How do I match any candidate within a range of characters
[0-9] or [A-Z] or [a-z]
How to I reuse the matched pattern?
\0 or \1
https://unix.stackexchange.com/questions/35206/replace-using-vim-reuse-part-of-the-search-pattern
How do I insert a newline?
\n
:%s/Ver. [0-9]../\0\n/g
How do I remove page break or form feed characters?
First be sure to in fundamental-mode
to properly see the ^L or ^M chars. In
EmacsLisp, the form-feed character is written `?\f’, and `\f’ represents it in
strings. (`\f’ is also used in C.) M-: (replace-string "\f" "")
How do I match a pattern only at the beginning of a line?
Use the ^ character.
Regular Expressions
The pattern that matches substrings in parentheses having no other ( and ) characters in between (like (xyz 123) in Text (abc(xyz 123)) is
\([^()]*\) %s/<chapter[^<>]*>//g Details:
\( - an opening round bracket (note that in POSIX BRE, ( should be used, see sed example below) [^()]* - zero or more (due to the * Kleene star quantifier) characters other than those defined in the negated character class/POSIX bracket expression, that is, any chars other than ( and ) \) - a closing round bracket (no escaping in POSIX BRE allowed)
4.2.8. Navigation - Buffer & Window Manipulation
- Buffers = instances of files, SPC b. All buffers have ONE major mode. Can have multiple minor modes.
- Windows = Display area that a buffer is shown, SPC w
- Frame = what is conventionally understood as a window. Has the minimize, maximize and close in top right/left.
Key | Effect |
---|---|
SPC # | Switch to Window number, hjkl directional keys work too. |
SPC tab | Switch between previous buffer, current buffer in window |
SPC b b | Access recent files, open buffers and bookmarks in one place |
SPC f b | Access just bookmarks > Useful for bookmarking directories |
SPC w / | Split window vertically |
SPC w - | Split window horizontally |
SPC t g | Enable Golden Ratios |
C-f | Page down |
C-b | Page up |
Major / Minor Mode
Key | Effect |
---|---|
SPC m | Major mode leader. Access to all bindings specific to major mode |
, | Major mode leader. Access to all bindings specific to major mode |
Minor mode can be reached with SPC t. See spacemacs documentation.
4.2.9. Navigation - Marks and Registers
Key | Effect |
---|---|
C-SPC | Set-mark-command = different from evil-set-marker (m) which is for buffer scope |
SPC r m | helm-all-mark-rings = access earlier marks set by the previous command |
Above is the emacs way, utilizing registers. For vim(evil)-style marking (primarily used within a buffer-wide scope)
Key | Effect |
---|---|
m a | drop a mark named a, m b to drop a mark named b etc. |
' a | goto line mark named a |
` a | goto exact pointer mark named a |
The above marks and registers offer a greater degree of manual control. If
you would like something similar to a back button in a web browser, please
M-x helm-for-files
"evil-jumps.el" under the evil package.
Convenient functions also from the evil package.
Key | Effect |
---|---|
g ; | goto-last-change |
g i | evil-insert-resume |
4.3. Text Manipulation
4.3.1. Global Shortcuts (From SPC Leader Key in All Buffers)
Key | Effect |
---|---|
SPC i j | evil-insert-line-below |
SPC i k | evil-insert-line-above |
SPC ; i | evil-comments, more options to gcc |
SPC c y | Comments a line and makes a copy below it |
SPC t l | toggle-truncating |
SPC t L | turn on visual line navigation |
SPC t I | toggle aggressive indenting |
SPC C-v s | Identical to C-x r t in above heading |
SPC r y | Shows helm kill ring (copy&paste history) |
SPC a u | Shows undo tree. q to quit |
SPC S s | auto-corrects word under cursor |
SPC e | Runs error checking |
C-o | Normal state for next command |
SPC x TAB | To use hjkl to indent-rigidly a block |
Surround Region
Evil-surround package
Key | Effect |
---|---|
SPC v | initiate expand-region mode |
v | expand the region by one semantic unit |
V | contract the region by one semantic unit |
r | reset the region to initial selection |
4.3.2. Vim Style Shortcuts
Must reads to understand Vi's Modal Editing
Vim Operations
Shift Modifier It seems to be a convention that normal commands operate after the cursor and pressing shift causes the command to operate before the cursor. For example p pastes (puts) after the cursor but P pastes before. Similarly, o opens a line after but O opens before. Note that this also extends to search: / is a forward search, but ? searches backwards. ? is what you get when you press shift + '/'.
Key | Effect |
---|---|
u | Undo |
C-r | Redo |
p | Paste under cursor line |
x | Deletes character under cursor |
0 | Moves to the beginning of the line |
$ | Moves to the end of the line |
w | moves to the beginning of the word |
e | moves to the end of the next word |
o | Enters newline below and insert mode |
O | Enters newline above and insert mode |
d f * | deletes all text up to *. Useful with "." |
d i * | deletes all text up to * |
dd | deletes entire line |
A | Enters insert mode at end of line |
D | Deletes until end of line |
R | Replaces until you exit |
Y | Yanks until end of line |
y | Yanks selection > first use visual mode |
yy | Yanks the line under cursor > no need for visual mode |
C | Changes until end of line |
c * | * can be l=letter or w=word, c2w would change next 2 words |
v | Visual char mode |
V | Visual line mode |
C-v | Visual block mode |
gcc | Comment out a line |
gc | In visual mode for selections |
f * | can be combined with d, c, or y to search the current line for * |
F * | searches the line backwards. Press ; with both to repeat search |
J | joins line (cursor can be anywhere) USEFUL for PDF paste to txt |
. | repeats last editing command |
% | Type % to find a matching ),], or } |
gu | Vim lowercase operator |
gU | Vim uppercase operator |
" a | Reference register a (register + operator + motion) |
" b | Reference register b (" b d e) deletes word and puts into register b |
m <char> | Mark cursor location with given char |
' <char> | Go the line with the specified mark |
` <char> | Go exactly to the specified mark |
S-R | Replaces highlighted region |
t | Same as f, but stops before the char |
t | t as a text operator can stand for tags |
% | go to matching bracket |
^ | go to first non-whitespace character in the line |
g_ | go to last non-blank character in the line. |
Find and replace whole words in vim You can use \< to match the beginning of a word and \> to match the end:
%s/\<word\>/newword/g
How to include forward slash in vi search & replace? Here are two ways:
escape the / which is the default substitute separator: :s/usrbin/\/usr\/bin use another substitute separator, e.g., using the hash # character: :s#usrbin#/usr/bin. Note that there are characters that you can't use as a separator: ", \, |
Vim keyboard macros
15.8.17.1 Vim keyboard macros
Spacemacs supports the VIM interface for creating macros in normal state using q to start a macro and @ to play a macro.
To record a keyboard macro:
Press q (there's no visual indicator, but it's waiting for a letter key to be pressed). Press a letter key to start recording to that letter register. (the minibuffer shows: Defining kbd macro…) Perform the actions that will be recorded. Press q to stop recording the macro. (the minibuffer shows: Keyboard macro defined).
To execute a recorded macro: (A macro can be played back multiple times, by typing a number before starting the macro)
Press @ (the minibuffer shows: @-, and it waits for a letter register key
to be pressed). Press a letter key for a register where a previous macro
has been recorded. The macro can be repeated by pressing the repeat last
editing command key: . (period). Macro can also be called via 99@a
to
repeat macro stored in register a 99 times.
4.3.3. Emacs Style Shortcuts
Emacs 12.5 Documentation on Rectangles has useful information
Key | Effect |
---|---|
C-x h | mark-whole-buffer |
C-x r t | Replace rectangle contents with string on each line (string-rectangle) |
M-x "undo" | In addition to SPC a u for the tree, this command can be used for a specific region |
C-Backspace | Calls backward-kill-sexp which kill previous symbolic expression |
delete-whitespace-rectangle | Mark region, then call this command. |
C-M-\ | Indent-region |
C-q C-l | Insert linebreak |
Emacs Macro
The Emacs way to define macros is available behind the prefix: SPC K
To start recording a keyboard macro:
Press SPC K k (uppercase then lowercase) to start recording a macro. Perform the actions that should be recorded. Press SPC K K (uppercase twice) to stop recording the macro.
To execute the last recorded macro press: SPC K K The macro can be executed again by pressing K one or more times. The single character replay works until another key than K is pressed.
4.3.4. Evil Multiple Cursors
grm - evil-mc-make-all-cursors gru - evil-mc-undo-all-cursors grs - evil-mc-pause-cursors grr - evil-mc-resume-cursors grf - evil-mc-make-and-goto-first-cursor grl - evil-mc-make-and-goto-last-cursor grh - evil-mc-make-cursor-here grj - evil-mc-make-cursor-move-next-line grk - evil-mc-make-cursor-move-prev-line M-n - evil-mc-make-and-goto-next-cursor grN - evil-mc-skip-and-goto-next-cursor M-p - evil-mc-make-and-goto-prev-cursor grP - evil-mc-skip-and-goto-prev-cursor C-n - evil-mc-make-and-goto-next-match grn - evil-mc-skip-and-goto-next-match C-t - evil-mc-skip-and-goto-next-match C-p - evil-mc-make-and-goto-prev-match grp - evil-mc-skip-and-goto-prev-match
4.3.5. Spell Checking
In addition to the layer README, know that your personal Dictionary is located at: ~/.aspell.en.pws
Key | Effect |
---|---|
C-; | flyspell-auto-correct-previous-word, repeat for next suggestion |
Note, flyspell-auto-correct-previous-word only corrects what's visible on the screen (Thank God).
4.4. Layouts and Workspaces
Refer to official spacemacs documentation on the same wording.
4.5. Help & Errors & Troubleshooting
4.5.1. General Help & Documentation
When Emacs freezes for some unknown reason, end the process with
pkill -9 emacs27
When updating org, or any large and complex packages, if you run into bugs it is
good to delete all .elc files. This is because any changes to macros require the
recompilation of elisp files. Delete all .elc files under ~/.emacs.d and then
run M-x spacemacs/recompile-elpa
.
cd ~/.emacs.d && find . -name *.elc -print0 | xargs -0 rm
Install Emacs from source
I wrote the initial tutorial for Windows 10, for Emacs was also my introduction into the world of UNIX and Lisp. That, combined with the desire to remind my future forgetful self was the reason for the surface-level depth and hand holding steps. Now if you count yourself comfortable in such an environment, I can think of a few good reasons to install Emacs from source at this point in time.
- When Emacs 29 is configured with the flag
--with-native-compilation
Emacs Lisp bytecode is translated to C and then machine code, yielding performance benefits. - WSLg uses Wayland and Emacs 29.0.50 has the pure GTK feature instead of relying on the older X window system. This leads to a smoother user experience on multiple, high DPI monitors.
- Debian does not build emacs with the flag
--with-xwidgets
for security reasons. With this feature enabled, Emacs is able to embed a Webkit browser widget inside a buffer. Compared to Emacs EWW which has HTML and limited CSS support, xwidget-webkit offers an experience closer to a conventional web browser. - Emacs 29 introduces tree-sitter support, a powerful parsing library that enhances its understanding of source code. With this integration, Emacs gains features like precise syntax highlighting, accurate indentation and easier extensibility.
Currently Debian bookworm packages Emacs 28.2. And for the record, I find such attention to stability perfectly reasonable. I am not familiar with the typical C build process, so Mr. Batsov's advice helped. Onto the build process,
sudo apt update # Install build dependencies ./configure will tell you if a build dependency is missing. sudo apt install git build-essential libgtk-3-dev libgnutls28-dev \ libtiff5-dev libgif-dev libjpeg-dev libpng-dev libxpm-dev \ libncurses-dev texinfo autoconf libxml2-dev libwebp-dev \ librsvg2-dev libsqlite3-dev liblcms2-dev libgpm-dev libotf-dev \ libacl1-dev libjansson4 libjansson-dev libgccjit-12 libgccjit-12-dev \ gcc-12 g++-12 libtree-sitter-dev export CC=/usr/bin/gcc-12 CXX=/usr/bin/gcc-12 sudo git clone git://git.sv.gnu.org/emacs.git /usr/local/src/emacs cd /usr/local/src/emacs sudo ./autogen.sh # See ./configure --help for more options. "C-h v" # 'system-configuration-options' to see what your Emacs is built with. sudo ./configure --with-mailutils --with-wide-int --with-pgtk \ --with-native-compilation=aot --with-json --with-tree-sitter # gconf is deprecated in favour of gsettings. # I have 4 threads. sudo make -j4 # Default install in /usr/local/ and emacs-29.0.50 binary under # /usr/local/bin. sudo make install # If you keep your Emacs source folder around, it will know how to uninstall # or to git pull from master and rebuild. sudo make uninstall # sudo git clean -dfX in case of rebuild.
4.5.2. Specific Troubleshooting and Known Issues
Copy paste from WSL2 to Windows is broken?
Paste something from the kill ring via
SPC r y
. Or restart your computer.- Whichkey Lag Due to issue described here: justbur/emacs-which-key#226 Lots of time spent inside which-key–maybe-replace
How to use the universal argument in spacemacs, as C-u is evil-scroll-up?
SPC u
also seeevil-want-C-u-scroll
variable.- If you run into graphical issues with VcXsrv or X2Go try starting emacs in
emas -nw
mode first, to generate .elc (compiled emacs lisp) files.
- Should the numbering of windows be off after resuming from sleep, such that
when creating a new frame window one
SPC 1
cannot be selected:SPC F D
should delete the "hidden" frame.
4.5.3. Performance
Use the Emacs profiler SPC h P s
to track performance issues.
If poorly written Emacs lisp packages aren't a problem, then look at garbage collection.
Afterwards, use SPC a k
to browse installed packages and uninstall any
extraneous packages by adding them to the excluded packages list.
Lastly look at the enabled global minor modes and disable any that are unneeded.
Spacemacs Specific
Key | Effect |
---|---|
SPC h | Read hydra menu at bottom |
SPC h d m | Describe-Mode Command, query unknown command |
SPC h d k | Describe Keybinding |
SPC h d a | Describe Emacs Command |
C-h i | M-x "info" for information :) |
SPC h d v | Describe a variable |
SPC h d f | Describe a function |
Do M-x customize-group RET org RET and begin exploring the Org customization groups. You can click on the Org Agenda group (or customize-group the org-agenda customization group directly). You would eventually come upon that option there, and then you could click the expander arrow and read the full docstring for it.
Using M-x apropos RET org agenda RET (or other apropos commands, like apropos-user-option, customize-apropos-options, etc). Scrolling through the list, you'd eventually come upon it and could follow the links to more info.
Using Helm, I generally have helm-mode enabled, and then I can C-h v, type org agenda, and quickly browse a list of relevant variables. Pressing C-j on one of them displays the help for that variable without exiting Helm, then pressing RET on one of them goes to that variable's help page, and you could click the link to customize it.
Finally, it's probably mentioned in the Org manual in the Agenda section. It's pretty thorough too. It can feel overwhelming if you don't know what you're looking for.