emacs: optimize lazy loading

This commit is contained in:
Pavel Korytov 2024-07-09 23:48:23 +03:00
parent 23496bfacc
commit 10429c4ad6
2 changed files with 177 additions and 430 deletions

View file

@ -30,12 +30,6 @@
(setq my/nested-emacs (and (getenv "IS_EMACS") t))
(setenv "IS_EMACS" "true")
(defmacro with-eval-after-load-norem (file &rest body)
(declare (indent 1) (debug (form def-body)))
`(unless my/remote-server
(with-eval-after-load ,file
,@body)))
(setq my/emacs-started nil)
(add-hook 'emacs-startup-hook
@ -111,6 +105,9 @@
(setq confirm-kill-emacs 'y-or-n-p)
(setq initial-major-mode 'fundamental-mode)
(setq initial-scratch-message "Hello there <3\n\n")
(use-package general
:straight t
:config
@ -329,11 +326,18 @@ then it takes a second \\[keyboard-quit] to abort the minibuffer."
"u" 'winner-undo
"U" 'winner-redo)
(defun my/lisp-interaction-buffer ()
(interactive)
(let ((buf (get-buffer-create "*lisp-interaction*")))
(with-current-buffer buf
(lisp-interaction-mode))
(switch-to-buffer buf)))
(my-leader-def
:infix "b"
"" '(:which-key "buffers")
"s" '((lambda () (interactive) (switch-to-buffer (persp-scratch-buffer)))
:which-key "*scratch*")
"s" '(my/lisp-interaction-buffer
:which-key "*lisp-interaction*")
"m" '((lambda () (interactive) (persp-switch-to-buffer "*Messages*"))
:which-key "*Messages*")
"l" 'next-buffer
@ -356,7 +360,7 @@ then it takes a second \\[keyboard-quit] to abort the minibuffer."
(require 'hideshow)
(general-define-key
:keymaps '(hs-minor-mode-map outline-minor-mode-map)
:keymaps '(hs-minor-mode-map outline-minor-mode-map outline-mode-map)
:states '(normal motion)
"ze" 'hs-hide-level
"TAB" 'evil-toggle-fold)
@ -1030,12 +1034,13 @@ Obeys `widen-automatically', which see."
(use-package olivetti
:straight t
:if (display-graphic-p)
:commands (olivetti-mode)
:config
(setq-default olivetti-body-width 86))
(use-package keycast
:straight t
:config
:init
(define-minor-mode keycast-mode
"Keycast mode"
:global t
@ -1044,10 +1049,12 @@ Obeys `widen-automatically', which see."
(add-to-list 'global-mode-string '("" keycast-mode-line " "))
(add-hook 'pre-command-hook 'keycast--update t) )
(remove-hook 'pre-command-hook 'keycast--update)
(setq global-mode-string (delete '("" keycast-mode-line " ") global-mode-string)))))
(setq global-mode-string (delete '("" keycast-mode-line " ") global-mode-string))))
:commands (keycast--update))
(use-package doom-themes
:straight t
;; Not deferring becuase I want `doom-themes-visual-bell-config'
:config
(setq doom-themes-enable-bold t
doom-themes-enable-italic t)
@ -1227,7 +1234,7 @@ Obeys `widen-automatically', which see."
(tab-bar-tab :background (my/color-value 'bg)
:foreground (my/color-value 'yellow)
:underline (my/color-value 'yellow))
(tab-bar :background nil :foreground nil)
(tab-bar :background 'unspecified :foreground 'unspecified)
(magit-section-secondary-heading :foreground (my/color-value 'blue)
:weight 'bold))
@ -1245,7 +1252,8 @@ Obeys `widen-automatically', which see."
(my/regenerate-desktop)))
(if my/is-termux
(my/switch-theme 'modus-operandi-tinted)
(progn
(my/switch-theme 'modus-operandi-tinted))
(my/switch-theme 'ef-duo-light))
(with-eval-after-load 'transient
@ -2572,6 +2580,7 @@ Returns (<buffer> . <workspace-index>) or nil."
;; (setq livedown-browser "qutebrowser"))
(use-package adoc-mode
:mode (rx (| ".asciidoc") eos)
:straight t)
(use-package plantuml-mode
@ -2596,6 +2605,8 @@ Returns (<buffer> . <workspace-index>) or nil."
(use-package subed
:straight (:host github :repo "rndusr/subed" :files ("subed/*.el")
:build (:not native-compile))
;; (cons (rx (| "srt" "vtt" "ass") eos) #'subed-mode)
:mode ("\\(?:ass\\|\\(?:sr\\|vt\\)t\\)\\'" . subed-mode)
:config
(general-define-key
:keymaps '(subed-mode-map subed-vtt-mode-map)
@ -2655,6 +2666,7 @@ Returns (<buffer> . <workspace-index>) or nil."
:straight (:host github :repo "SqrtMinusOne/reverso.el")
:init
(my-leader-def "ar" #'reverso)
:commands (reverso)
:config
(setq reverso-languages '(russian english german))
(reverso-history-mode))
@ -2739,6 +2751,7 @@ Returns (<buffer> . <workspace-index>) or nil."
(add-hook 'clips-mode 'lispy-mode))
(use-package ein
:commands (ein:run)
:straight t)
(setq my/pipenv-python-alist '())
@ -2883,6 +2896,7 @@ Returns (<buffer> . <workspace-index>) or nil."
(use-package json-mode
:straight t
:mode "\\.json\\'"
:config
(add-hook 'json-mode-hook #'smartparens-mode)
(add-hook 'json-mode-hook #'hs-minor-mode)
@ -2918,11 +2932,13 @@ Returns (<buffer> . <workspace-index>) or nil."
(use-package jenkinsfile-mode
:straight t
:mode "Jenkinsfile\\'"
:config
(add-hook 'jenkinsfile-mode-hook #'smartparens-mode)
(my/set-smartparens-indent 'jenkinsfile-mode))
(use-package crontab-mode
:mode "/crontab\\(\\.X*[[:alnum:]]+\\)?\\'"
:straight t)
(use-package nginx-mode
@ -2931,6 +2947,7 @@ Returns (<buffer> . <workspace-index>) or nil."
(my/set-smartparens-indent 'nginx-mode))
(use-package hcl-mode
:mode "\\.hcl\\'"
:straight t)
(add-hook 'sh-mode-hook #'smartparens-mode)
@ -2961,9 +2978,11 @@ Returns (<buffer> . <workspace-index>) or nil."
"rr" #'sqlformat-buffer)
(use-package sparql-mode
:mode "\\.sparql\\'"
:straight t)
(use-package graphql-mode
:mode (rx (| "gql" "grapql") eos)
:straight t)
(defun my/doc-view-setup ()
@ -2997,6 +3016,7 @@ Returns (<buffer> . <workspace-index>) or nil."
(add-hook 'gnuplot-mode-hook #'smartparens-mode))
(use-package x509-mode
:commands (x509-dwim)
:straight (:host github :repo "jobbflykt/x509-mode"
:build (:not native-compile)))
@ -3080,7 +3100,7 @@ Returns (<buffer> . <workspace-index>) or nil."
(lambda ()
(rainbow-delimiters-mode -1))))
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(require 'org-crypt)
(org-crypt-use-before-save-magic)
(setq org-tags-exclude-from-inheritance '("crypt"))
@ -3103,7 +3123,7 @@ Returns (<buffer> . <workspace-index>) or nil."
keys
(funcall fun prompt keys)))
(with-eval-after-load-norem 'epa
(with-eval-after-load 'epa
(advice-add #'epa--select-keys :around #'my/epa--select-keys-around))
(unless my/remote-server
@ -3151,7 +3171,7 @@ Returns (<buffer> . <workspace-index>) or nil."
(with-eval-after-load 'org
(org-link-set-parameters "rel" :follow #'browse-url :export #'my/export-rel-url))
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(general-define-key
:keymaps 'org-mode-map
"C-c d" #'org-decrypt-entry
@ -3190,7 +3210,7 @@ Returns (<buffer> . <workspace-index>) or nil."
(kill-new url)
(message (concat "Copied URL: " url))))
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(general-nmap :keymaps 'org-mode-map
"C-x C-l" 'my/org-link-copy))
@ -3258,11 +3278,11 @@ With ARG, repeats or can move backward if negative."
(sp-local-pair 'org-mode "$" "$")
(sp--remove-local-pair "'"))
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(setq my/org-latex-scale 1.75)
(setq org-format-latex-options (plist-put org-format-latex-options :scale my/org-latex-scale)))
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(setq my/latex-preview-header "\\documentclass{article}
\\usepackage[usenames]{color}
\\usepackage{graphicx}
@ -3375,6 +3395,7 @@ With ARG, repeats or can move backward if negative."
(use-package restclient
:if (not my/remote-server)
:straight t
:mode ("\\.http\\'" . restclient-mode)
:config
(general-define-key
:keymaps 'restclient-mode-map
@ -3393,7 +3414,7 @@ With ARG, repeats or can move backward if negative."
:if (not my/remote-server)
:straight t)
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(org-babel-do-load-languages
'org-babel-load-languages
`((emacs-lisp . t)
@ -3680,9 +3701,11 @@ With ARG, repeats or can move backward if negative."
(use-package phscroll
:straight (:host github :repo "misohena/phscroll")
:commands (org-phscroll-mode)
:config
(with-eval-after-load 'org
(require 'org-phscroll)))
(require 'org-phscroll)
(org-phscroll-deactivate)))
(defun my/update-org-agenda ()
(interactive)
@ -3717,7 +3740,7 @@ With ARG, repeats or can move backward if negative."
(run-hooks 'my/org-refile-hooks))))
(setq org-roam-directory (concat org-directory "/roam"))
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(require 'seq)
(my/update-org-agenda))
@ -3766,7 +3789,7 @@ With ARG, repeats or can move backward if negative."
(setq org-clock-persist 'clock)
(org-clock-persistence-insinuate))
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(add-to-list
'org-global-properties
'("Effort_ALL" . "0 0:05 0:10 0:15 0:30 0:45 1:00 1:30 2:00 4:00 8:00")))
@ -3908,90 +3931,6 @@ With ARG, repeats or can move backward if negative."
"v" #'org-ql-view
"q" #'org-ql-search))
(with-eval-after-load 'org-ql
(org-ql-defpred property (property &optional value &key inherit multi)
"Return non-nil if current entry has PROPERTY, and optionally VALUE.
If INHERIT is nil, only match entries with PROPERTY set on the
entry; if t, also match entries with inheritance. If INHERIT is
not specified, use the Boolean value of
`org-use-property-inheritance', which see (i.e. it is only
interpreted as nil or non-nil). If MULTI is non-nil, also check for
multi-value properties."
:normalizers ((`(,predicate-names)
;; HACK: This clause protects against the case in
;; which the arguments are nil, which would cause an
;; error in `rx-to-string' in other clauses. This
;; can happen with `org-ql-completing-read',
;; e.g. when the input is "property:" while the user
;; is typing.
;; FIXME: Instead of this being moot, make this
;; predicate test for whether an entry has local
;; properties when no arguments are given.
(list 'property ""))
(`(,predicate-names ,property ,value . ,plist)
;; Convert keyword property arguments to strings. Non-sexp
;; queries result in keyword property arguments (because to do
;; otherwise would require ugly special-casing in the parsing).
(when (keywordp property)
(setf property (substring (symbol-name property) 1)))
(list 'property property value
:inherit (if (plist-member plist :inherit)
(plist-get plist :inherit)
org-use-property-inheritance)
:multi (when (plist-member plist :multi)
(plist-get plist :multi)))))
;; MAYBE: Should case folding be disabled for properties? What about values?
;; MAYBE: Support (property) without args.
;; NOTE: When inheritance is enabled, the preamble can't be used,
;; which will make the search slower.
:preambles ((`(,predicate-names ,property ,value ,(map :multi) . ,(map :inherit))
;; We do NOT return nil, because the predicate still needs to be tested,
;; because the regexp could match a string not inside a property drawer.
(list :regexp (unless inherit
(rx-to-string `(seq bol (0+ space) ":" ,property
,@(when multi '((? "+"))) ":"
(1+ space) ,value (0+ space) eol)))
:query query))
(`(,predicate-names ,property ,(map :multi) . ,(map :inherit))
;; We do NOT return nil, because the predicate still needs to be tested,
;; because the regexp could match a string not inside a property drawer.
;; NOTE: The preamble only matches if there appears to be a value.
;; A line like ":ID: " without any other text does not match.
(list :regexp (unless inherit
(rx-to-string `(seq bol (0+ space) ":" ,property
,@(when multi '((? "+")))
":" (1+ space)
(minimal-match (1+ not-newline)) eol)))
:query query)))
:body
(pcase property
('nil (user-error "Property matcher requires a PROPERTY argument"))
(_ (pcase value
('nil
;; Check that PROPERTY exists
(org-ql--value-at
(point) (lambda ()
(org-entry-get (point) property))))
(_
;; Check that PROPERTY has VALUE.
;; TODO: Since --value-at doesn't account for inheritance,
;; we should generalize --tags-at to also work for property
;; inheritance and use it here, which should be much faster.
(if multi
(when-let (values (org-ql--value-at
(point) (lambda ()
;; The default separator is space
(let ((org-property-separators `((,property . "\n"))))
(org-entry-get (point) property inherit)))))
(seq-some (lambda (v)
(string-equal value v))
(split-string values "\n")))
(string-equal value (org-ql--value-at
(point) (lambda ()
(org-entry-get (point) property inherit)))))))))))
(cl-defun my/org-ql-view-recent-items
(&key num-days (type 'ts)
(files (org-agenda-files))
@ -4132,77 +4071,6 @@ and lots of comments which are too long for my Emacs config."
(with-eval-after-load 'org-ql
(advice-add #'org-ql-view--format-element :override #'my/org-ql-view--format-element-override))
(defun my/org-meeting--prompt ()
(let* ((meetings (org-ql-query
:select #'element-with-markers
:from (org-agenda-files)
:where '(and (todo) (tags "mt") (ts-active :from today to 31))
:order-by 'scheduled))
(data (mapcar
(lambda (meeting)
(let ((raw-value (org-element-property :raw-value meeting))
(scheduled (org-format-timestamp
(org-element-property :scheduled meeting)
(cdr org-time-stamp-formats))))
(cons (format "%-30s %s" raw-value
(propertize scheduled 'face 'org-agenda-date))
meeting)))
meetings))
(ivy-prescient-sort-commands nil))
(cdr
(assoc
(completing-read "Meeting: " data nil t)
data))))
(defun my/org-meeting--format-link (meeting)
(format "[[file:%s::*%s][%s]]"
(buffer-file-name
(marker-buffer
(org-element-property :org-marker meeting)))
(org-element-property :raw-value meeting)
(org-element-property :raw-value meeting)))
(defun my/org-meeting-link (&optional arg)
(interactive "p")
(save-excursion
(org-back-to-heading t)
(let* ((meeting (my/org-meeting--prompt))
(link (my/org-meeting--format-link meeting))
(element (org-element-at-point-no-context)))
(if (or (not arg) (not (org-element-property :MEETING element)))
(org-set-property "MEETING" link)
(let ((range (org-get-property-block
(org-element-property :begin element)))
(case-fold-search nil))
(goto-char (cdr range))
(beginning-of-line)
(insert-and-inherit ":MEETING+: " link "\n")
(org-indent-line))))))
(defun my/org-ql-meeting-tasks (meeting)
(interactive (list (my/org-meeting--prompt)))
(org-ql-search (org-agenda-files)
`(property "MEETING" ,(my/org-meeting--format-link meeting)
:multi t)
:sort '(date priority todo)
:buffer (format "*Meeting Tasks: %s*" (org-element-property :raw-value meeting))
:super-groups '((:auto-outline-path t))))
(defun my/org-ql-meeting-tasks-agenda ()
(interactive)
(let ((meeting (save-window-excursion
(org-agenda-switch-to)
(org-back-to-heading)
(org-ql--add-markers
(org-element-at-point)))))
(my/org-ql-meeting-tasks meeting)))
(with-eval-after-load 'org-agenda
(general-define-key
:keymaps 'org-agenda-mode-map
:states '(normal motion)
"gm" #'my/org-ql-meeting-tasks-agenda))
(use-package org-habit-stats
:straight (:host github :repo "ml729/org-habit-stats")
:after (org)
@ -5010,6 +4878,7 @@ TODO Write something, maybe? "))))
(use-package calfw
:straight t
:defer t
:config
(add-hook 'cfw:calendar-mode-hook #'my/calfw-setup-buffer))
@ -5115,7 +4984,7 @@ TODO Write something, maybe? "))))
("\\subsubsection{%s}" . "\\subsubsection*{%s}")))))
;; Make sure to eval the function when org-latex-classes list already exists
(with-eval-after-load-norem 'ox-latex
(with-eval-after-load 'ox-latex
(my/setup-org-latex))
(with-eval-after-load 'ox
@ -5307,7 +5176,6 @@ TODO Write something, maybe? "))))
(use-package dired-recent
:straight t
:after dired
:commands (dired-recent-open)
:config
(dired-recent-mode)
(general-define-key
@ -5318,14 +5186,15 @@ TODO Write something, maybe? "))))
(use-package all-the-icons-dired
:straight t
:after (dired)
:if (display-graphic-p)
:hook (dired-mode . (lambda ()
(unless (string-match-p "/gnu/store" default-directory)
(all-the-icons-dired-mode))))
:config)
(all-the-icons-dired-mode)))))
(use-package dired-open
:straight t
:after (dired)
:commands (dired-open-xdg))
(use-package dired-du
@ -5440,10 +5309,13 @@ TODO Write something, maybe? "))))
(list (telega-msg-for-interactive)
(prefix-numeric-value current-prefix-arg)))
(if (eq arg 4)
(let ((default-directory
(with-current-buffer (my/get-good-buffer 'dired-mode "Dired buffer: ")
(dired-current-directory))))
(progn
(setq telega-msg-save-dir
(with-current-buffer (my/get-good-buffer 'dired-mode "Dired buffer: ")
(dired-current-directory)))
(telega-msg-save msg))
(setq default-directory (expand-file-name "~"))
(setq telega-msg-save-dir nil)
(telega-msg-save msg)))
(defun my/dired-attach-to-notmuch (files notmuch-buffer)
@ -5987,6 +5859,7 @@ TODO Write something, maybe? "))))
("terminfo/65" "terminfo/65/*")
("integration" "integration/*")
(:exclude ".dir-locals.el" "*-tests.el")))
:commands (eat eat-shell-mode)
:config
(setq eat-shell "/bin/bash"))
@ -6731,6 +6604,7 @@ ENTRY is an instance of `elfeed-entry'."
:straight t
:init
(my-leader-def "au" #'gnus)
:commands (gnus)
:config
(my/persp-add-rule
gnus-summary-mode 0 "gnus"
@ -7782,6 +7656,11 @@ base toot."
:straight t
:if (not my/remote-server)
:functions (my-google-translate-at-point google-translate--search-tkk)
:commands (google-translate-at-point
google-translate-at-point-reverse
google-translate-query-translate
google-translate-query-translate-reverse
google-translate-smooth-translate)
:custom
(google-translate-backend-method 'curl)
:config
@ -7878,6 +7757,7 @@ base toot."
(use-package sx
:straight t
:commands (sx-search sx-tab-frontpage)
:config
(general-define-key
:states '(normal)
@ -7963,6 +7843,7 @@ base toot."
:straight t
:init
(setq ellama-language "English")
:defer t
:config
(require 'llm-ollama)
;; I've looked for this option for 1.5 hours
@ -7982,7 +7863,7 @@ base toot."
:embedding-model "llama3:instruct")))))
(with-eval-after-load 'ellama
(transient-define-prefix my/ellama ()
(transient-define-prefix my/ellama-transient ()
"Ellama actions."
["General"
:class transient-row
@ -8021,8 +7902,15 @@ base toot."
("sp" "Provider" ellama-provider-select)
("ss" "Session" ellama-session-switch)
("sr" "Rename ression" ellama-session-rename)
("sd" "Delete session" ellama-session-remove)])
(my-leader-def "aie" #'my/ellama))
("sd" "Delete session" ellama-session-remove)]))
(defun my/ellama ()
(interactive)
(require 'ellama)
(call-interactively #'my/ellama-transient))
(my-leader-def "aie" #'my/ellama)
(defun my/diff-strings (str1 str2)
(let ((file1 (make-temp-file "diff1"))
@ -8085,37 +7973,6 @@ base toot."
(interactive (list (my/ellama--text) (derived-mode-p 'org-mode)))
(my/ellama-text-with-diff text is-org-mode my/ellama-improve-concise-prompt))
(with-eval-after-load 'ellama
(cl-defstruct (llm-ollama-gradient (:include llm-ollama)) num-ctx)
(cl-defmethod llm-provider-chat-request ((provider llm-ollama-gradient) prompt _)
(let (request-alist messages options)
(setq messages
(mapcar (lambda (interaction)
`(("role" . ,(symbol-name (llm-chat-prompt-interaction-role interaction)))
("content" . ,(llm-chat-prompt-interaction-content interaction))))
(llm-chat-prompt-interactions prompt)))
(when (llm-chat-prompt-context prompt)
(push `(("role" . "system")
("content" . ,(llm-provider-utils-get-system-prompt prompt llm-ollama-example-prelude)))
messages))
(push `("messages" . ,messages) request-alist)
(push `("model" . ,(llm-ollama-chat-model provider)) request-alist)
(when (llm-chat-prompt-temperature prompt)
(push `("temperature" . ,(llm-chat-prompt-temperature prompt)) options))
(when (llm-chat-prompt-max-tokens prompt)
(push `("num_predict" . ,(llm-chat-prompt-max-tokens prompt)) options))
(when (llm-ollama-gradient-num-ctx provider)
(push `("num_ctx" . ,(llm-ollama-gradient-num-ctx provider)) options))
(when options (push `("options" . ,options) request-alist))
request-alist))
(push `("llama3-gradient" . ,(make-llm-ollama-gradient
:chat-model "llama3-gradient"
:embedding-model "llama3-gradient"
:num-ctx 48000))
ellama-providers))
(with-eval-after-load 'gptel
(cl-defmethod gptel--request-data :around ((_backend gptel-ollama) prompts)
(let ((request-alist (cl-call-next-method)))
@ -8126,6 +7983,7 @@ base toot."
request-alist)))
(use-package ini
:mode "\\.ini\\'"
:straight (:host github :repo "daniel-ness/ini.el"))
(defvar my/index-root (concat (getenv "HOME") "/"))
@ -8500,6 +8358,7 @@ prefix."
TREE is a form a defined by `my/index--tree-get'. The return value is
a list of commands as defined by `my/index--commands-display'."
(require 'ini)
(let* ((map-tree (my/index--wakatime-get-map-tree tree))
(map-tree-encoding (ini-encode `(("projectmap" . ,map-tree))))
(map-tree-saved (with-temp-buffer
@ -8905,6 +8764,7 @@ to `dired' if used interactively."
"M-o" #'casual-main-menu))
(use-package chess
:commands (chess-pgn-mode)
:straight t)
(setq my/chess-python "/home/pavel/.guix-extra-profiles/dev/dev/bin/python3")
@ -8992,6 +8852,7 @@ to `dired' if used interactively."
(use-package zone
:ensure nil
:commands (zone)
:config
(setq original-zone-programs (copy-sequence zone-programs)))

308
Emacs.org
View file

@ -67,6 +67,7 @@ I decided not to keep configs for features that I do not use anymore because thi
| org-roam-protocol | 2f0c20eb01b8899d00d129cc7ca5c6b263c69c65 |
| eshell-info-banner | 4ccc0bbc412b68e1401533264d801d86b1fc8cc7 |
| aweshell | 4ccc0bbc412b68e1401533264d801d86b1fc8cc7 |
| link tasks to meetings | 23496bfacc31ffedf2092da04e4e602b71373425 |
* Initial setup
Setting up the environment, performance tuning and a few basic settings.
@ -150,14 +151,6 @@ To launch Emacs with this config, run
emacs -q -l ~/.emacs.d/init-minimal.el
#+end_src
A convinience macro:
#+begin_src emacs-lisp
(defmacro with-eval-after-load-norem (file &rest body)
(declare (indent 1) (debug (form def-body)))
`(unless my/remote-server
(with-eval-after-load ,file
,@body)))
#+end_src
** Performance
*** Measure startup speed
A small function to print out the loading time and number of GCs during the loading. Can be useful as a point of data for optimizing Emacs startup time.
@ -174,7 +167,7 @@ A small function to print out the loading time and number of GCs during the load
(setq my/emacs-started t)))
#+end_src
Set the following to =t= to print debug information during the startup. This will include the order in which the packages are loaded and the loading time of individual packages.
Set the following to =t= to print debug information during the startup. This will include package loading order and time.
#+begin_src emacs-lisp
(setq use-package-verbose nil)
#+end_src
@ -189,7 +182,7 @@ Just setting ~gc-cons-treshold~ to a larger value.
*** Run garbage collection when Emacs is unfocused
Run GC when Emacs loses focus. +Time will tell if that's a good idea.+
Some time has passed, and I still don't know if there is any quantifiable advantage to this, but it doesn't hurt.
I still don't know if there is any quantifiable advantage to this, but it doesn't hurt.
#+begin_src emacs-lisp
(add-hook 'emacs-startup-hook
@ -291,6 +284,15 @@ This adds a confirmation to avoid accidental Emacs closing.
#+begin_src emacs-lisp
(setq confirm-kill-emacs 'y-or-n-p)
#+end_src
** Scratch buffer
I have a problem with =emacs-lisp-mode= as =initial-major-mode= because in my config it loads =lispy=, which loads =org-mode=.
So until I've made a better loading screen, this will do.
#+begin_src emacs-lisp
(setq initial-major-mode 'fundamental-mode)
(setq initial-scratch-message "Hello there <3\n\n")
#+end_src
* General settings
** Keybindings
*** general.el
@ -549,6 +551,7 @@ Using the =SPC= key as a leader key, like in Doom Emacs or Spacemacs.
(my-leader-def
"a" '(:which-key "apps"))
#+end_src
**** Universal argument
Change the universal argument to =M-u=. I use =C-u= to scroll up, as I'm used to from vim.
@ -608,12 +611,23 @@ It doesn't play too well with perspective.el, that is it has a single history li
"U" 'winner-redo)
#+end_src
**** Buffer management
The following is necessary since my scratch buffer isn't lisp-interaction.
#+begin_src emacs-lisp
(defun my/lisp-interaction-buffer ()
(interactive)
(let ((buf (get-buffer-create "*lisp-interaction*")))
(with-current-buffer buf
(lisp-interaction-mode))
(switch-to-buffer buf)))
#+end_src
#+begin_src emacs-lisp
(my-leader-def
:infix "b"
"" '(:which-key "buffers")
"s" '((lambda () (interactive) (switch-to-buffer (persp-scratch-buffer)))
:which-key "*scratch*")
"s" '(my/lisp-interaction-buffer
:which-key "*lisp-interaction*")
"m" '((lambda () (interactive) (persp-switch-to-buffer "*Messages*"))
:which-key "*Messages*")
"l" 'next-buffer
@ -651,7 +665,7 @@ Evil does a pretty good job of abstracting all these packages with a set of vim-
#+begin_src emacs-lisp
(require 'hideshow)
(general-define-key
:keymaps '(hs-minor-mode-map outline-minor-mode-map)
:keymaps '(hs-minor-mode-map outline-minor-mode-map outline-mode-map)
:states '(normal motion)
"ze" 'hs-hide-level
"TAB" 'evil-toggle-fold)
@ -1716,6 +1730,7 @@ Title format, which used to look something like =emacs:project@hostname=. Now it
(use-package olivetti
:straight t
:if (display-graphic-p)
:commands (olivetti-mode)
:config
(setq-default olivetti-body-width 86))
#+end_src
@ -1725,7 +1740,7 @@ Showing the last pressed key. Occasionally useful.
#+begin_src emacs-lisp
(use-package keycast
:straight t
:config
:init
(define-minor-mode keycast-mode
"Keycast mode"
:global t
@ -1734,7 +1749,8 @@ Showing the last pressed key. Occasionally useful.
(add-to-list 'global-mode-string '("" keycast-mode-line " "))
(add-hook 'pre-command-hook 'keycast--update t) )
(remove-hook 'pre-command-hook 'keycast--update)
(setq global-mode-string (delete '("" keycast-mode-line " ") global-mode-string)))))
(setq global-mode-string (delete '("" keycast-mode-line " ") global-mode-string))))
:commands (keycast--update))
#+end_src
** Themes and colors
*** Theme packages
@ -1742,6 +1758,7 @@ My colorschemes of choice.
#+begin_src emacs-lisp
(use-package doom-themes
:straight t
;; Not deferring becuase I want `doom-themes-visual-bell-config'
:config
(setq doom-themes-enable-bold t
doom-themes-enable-italic t)
@ -1970,7 +1987,7 @@ Defining colors for =tab-bar.el=:
(tab-bar-tab :background (my/color-value 'bg)
:foreground (my/color-value 'yellow)
:underline (my/color-value 'yellow))
(tab-bar :background nil :foreground nil)
(tab-bar :background 'unspecified :foreground 'unspecified)
(magit-section-secondary-heading :foreground (my/color-value 'blue)
:weight 'bold))
#+end_src
@ -1994,7 +2011,8 @@ The built-in =load-theme= does not deactivate the previous theme, so here's a fu
#+begin_src emacs-lisp
(if my/is-termux
(my/switch-theme 'modus-operandi-tinted)
(progn
(my/switch-theme 'modus-operandi-tinted))
(my/switch-theme 'ef-duo-light))
#+end_src
**** Extending current theme
@ -3502,6 +3520,7 @@ Section snippets. The code turned out to be more complicated than just writing t
*** Ascii Doc
#+begin_src emacs-lisp
(use-package adoc-mode
:mode (rx (| ".asciidoc") eos)
:straight t)
#+end_src
*** PlantUML
@ -3536,6 +3555,8 @@ A major mode to work with subtitles.
(use-package subed
:straight (:host github :repo "rndusr/subed" :files ("subed/*.el")
:build (:not native-compile))
;; (cons (rx (| "srt" "vtt" "ass") eos) #'subed-mode)
:mode ("\\(?:ass\\|\\(?:sr\\|vt\\)t\\)\\'" . subed-mode)
:config
(general-define-key
:keymaps '(subed-mode-map subed-vtt-mode-map)
@ -3622,6 +3643,7 @@ References:
:straight (:host github :repo "SqrtMinusOne/reverso.el")
:init
(my-leader-def "ar" #'reverso)
:commands (reverso)
:config
(setq reverso-languages '(russian english german))
(reverso-history-mode))
@ -3749,6 +3771,7 @@ An honorary Lisp.
#+begin_src emacs-lisp
(use-package ein
:commands (ein:run)
:straight t)
#+end_src
*** pyright
@ -3994,6 +4017,7 @@ A function to start up [[https://www.tensorflow.org/tensorboard][TensorBoard]].
#+begin_src emacs-lisp
(use-package json-mode
:straight t
:mode "\\.json\\'"
:config
(add-hook 'json-mode-hook #'smartparens-mode)
(add-hook 'json-mode-hook #'hs-minor-mode)
@ -4044,6 +4068,7 @@ A package to quickly create =.gitignore= files.
#+begin_src emacs-lisp
(use-package jenkinsfile-mode
:straight t
:mode "Jenkinsfile\\'"
:config
(add-hook 'jenkinsfile-mode-hook #'smartparens-mode)
(my/set-smartparens-indent 'jenkinsfile-mode))
@ -4051,6 +4076,7 @@ A package to quickly create =.gitignore= files.
*** crontab
#+begin_src emacs-lisp
(use-package crontab-mode
:mode "/crontab\\(\\.X*[[:alnum:]]+\\)?\\'"
:straight t)
#+end_src
*** nginx
@ -4063,6 +4089,7 @@ A package to quickly create =.gitignore= files.
*** HCL
#+begin_src emacs-lisp
(use-package hcl-mode
:mode "\\.hcl\\'"
:straight t)
#+end_src
** Shell
@ -4109,11 +4136,13 @@ So far I didn't find a nice SQL client for Emacs, but I occasionally run SQL que
*** SPARQL
#+begin_src emacs-lisp
(use-package sparql-mode
:mode "\\.sparql\\'"
:straight t)
#+end_src
*** GraphQL
#+begin_src emacs-lisp
(use-package graphql-mode
:mode (rx (| "gql" "grapql") eos)
:straight t)
#+end_src
** Documents
@ -4160,6 +4189,7 @@ Emacs integration for [[http://gnuplot.info/][gnuplot]].
** x509
#+begin_src emacs-lisp
(use-package x509-mode
:commands (x509-dwim)
:straight (:host github :repo "jobbflykt/x509-mode"
:build (:not native-compile)))
#+end_src
@ -4281,7 +4311,7 @@ Use the built-in org mode (=:type built-in=).
Setting up =org-crypt= to encrypt parts of file.
#+begin_src emacs-lisp :noweb-ref
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(require 'org-crypt)
(org-crypt-use-before-save-magic)
(setq org-tags-exclude-from-inheritance '("crypt"))
@ -4311,7 +4341,7 @@ Another way to encrypt Org files is to save them with the extension =.org.gpg=.
keys
(funcall fun prompt keys)))
(with-eval-after-load-norem 'epa
(with-eval-after-load 'epa
(advice-add #'epa--select-keys :around #'my/epa--select-keys-around))
(unless my/remote-server
@ -4388,7 +4418,7 @@ I've moved this block above because the =my-leader-def= expression in the next b
*** General keybindings
#+begin_src emacs-lisp
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(general-define-key
:keymaps 'org-mode-map
"C-c d" #'org-decrypt-entry
@ -4429,7 +4459,7 @@ I've moved this block above because the =my-leader-def= expression in the next b
(kill-new url)
(message (concat "Copied URL: " url))))
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(general-nmap :keymaps 'org-mode-map
"C-x C-l" 'my/org-link-copy))
#+end_src
@ -4517,14 +4547,14 @@ Call the function before opening an org file or reopen a buffer after calling th
Scale latex fragments preview.
#+begin_src emacs-lisp
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(setq my/org-latex-scale 1.75)
(setq org-format-latex-options (plist-put org-format-latex-options :scale my/org-latex-scale)))
#+end_src
Also, LaTeX fragments preview tends to break whenever the are custom =#+LATEX_HEADER= entries. To circumvent this, I add a custom header and modify the ~org-preview-latex-process-alist~ variable
#+begin_src emacs-lisp
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(setq my/latex-preview-header "\\documentclass{article}
\\usepackage[usenames]{color}
\\usepackage{graphicx}
@ -4698,6 +4728,7 @@ References:
(use-package restclient
:if (not my/remote-server)
:straight t
:mode ("\\.http\\'" . restclient-mode)
:config
(general-define-key
:keymaps 'restclient-mode-map
@ -4719,7 +4750,7 @@ References:
*** Org Babel Setup
Enable languages
#+begin_src emacs-lisp
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(org-babel-do-load-languages
'org-babel-load-languages
`((emacs-lisp . t)
@ -5127,9 +5158,11 @@ I use Org to manage some small tables which I want to process further. So here i
#+begin_src emacs-lisp
(use-package phscroll
:straight (:host github :repo "misohena/phscroll")
:commands (org-phscroll-mode)
:config
(with-eval-after-load 'org
(require 'org-phscroll)))
(require 'org-phscroll)
(org-phscroll-deactivate)))
#+end_src
** Productivity & Knowledge management
@ -5188,7 +5221,7 @@ Also, my project structure is somewhat chaotic, so I have an =.el= file in the o
(run-hooks 'my/org-refile-hooks))))
(setq org-roam-directory (concat org-directory "/roam"))
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(require 'seq)
(my/update-org-agenda))
#+end_src
@ -5266,7 +5299,7 @@ The following enables org-clock persistence between Emacs sessions.
Effort estimation. Not using this as of now.
#+begin_src emacs-lisp
(with-eval-after-load-norem 'org
(with-eval-after-load 'org
(add-to-list
'org-global-properties
'("Effort_ALL" . "0 0:05 0:10 0:15 0:30 0:45 1:00 1:30 2:00 4:00 8:00")))
@ -5446,97 +5479,6 @@ It doesn't look great with org-bars mode, so...
"q" #'org-ql-search))
#+end_src
***** Add :multi argument to the property predicate
I use the property predicate to find tasks linked to meetings, and I want to link some tasks to multiple meetings. So I modified the property predicate to support that.
I can't contribute that back to =org-ql= because it requires copyright assignment, so here it is.
#+begin_src emacs-lisp
(with-eval-after-load 'org-ql
(org-ql-defpred property (property &optional value &key inherit multi)
"Return non-nil if current entry has PROPERTY, and optionally VALUE.
If INHERIT is nil, only match entries with PROPERTY set on the
entry; if t, also match entries with inheritance. If INHERIT is
not specified, use the Boolean value of
`org-use-property-inheritance', which see (i.e. it is only
interpreted as nil or non-nil). If MULTI is non-nil, also check for
multi-value properties."
:normalizers ((`(,predicate-names)
;; HACK: This clause protects against the case in
;; which the arguments are nil, which would cause an
;; error in `rx-to-string' in other clauses. This
;; can happen with `org-ql-completing-read',
;; e.g. when the input is "property:" while the user
;; is typing.
;; FIXME: Instead of this being moot, make this
;; predicate test for whether an entry has local
;; properties when no arguments are given.
(list 'property ""))
(`(,predicate-names ,property ,value . ,plist)
;; Convert keyword property arguments to strings. Non-sexp
;; queries result in keyword property arguments (because to do
;; otherwise would require ugly special-casing in the parsing).
(when (keywordp property)
(setf property (substring (symbol-name property) 1)))
(list 'property property value
:inherit (if (plist-member plist :inherit)
(plist-get plist :inherit)
org-use-property-inheritance)
:multi (when (plist-member plist :multi)
(plist-get plist :multi)))))
;; MAYBE: Should case folding be disabled for properties? What about values?
;; MAYBE: Support (property) without args.
;; NOTE: When inheritance is enabled, the preamble can't be used,
;; which will make the search slower.
:preambles ((`(,predicate-names ,property ,value ,(map :multi) . ,(map :inherit))
;; We do NOT return nil, because the predicate still needs to be tested,
;; because the regexp could match a string not inside a property drawer.
(list :regexp (unless inherit
(rx-to-string `(seq bol (0+ space) ":" ,property
,@(when multi '((? "+"))) ":"
(1+ space) ,value (0+ space) eol)))
:query query))
(`(,predicate-names ,property ,(map :multi) . ,(map :inherit))
;; We do NOT return nil, because the predicate still needs to be tested,
;; because the regexp could match a string not inside a property drawer.
;; NOTE: The preamble only matches if there appears to be a value.
;; A line like ":ID: " without any other text does not match.
(list :regexp (unless inherit
(rx-to-string `(seq bol (0+ space) ":" ,property
,@(when multi '((? "+")))
":" (1+ space)
(minimal-match (1+ not-newline)) eol)))
:query query)))
:body
(pcase property
('nil (user-error "Property matcher requires a PROPERTY argument"))
(_ (pcase value
('nil
;; Check that PROPERTY exists
(org-ql--value-at
(point) (lambda ()
(org-entry-get (point) property))))
(_
;; Check that PROPERTY has VALUE.
;; TODO: Since --value-at doesn't account for inheritance,
;; we should generalize --tags-at to also work for property
;; inheritance and use it here, which should be much faster.
(if multi
(when-let (values (org-ql--value-at
(point) (lambda ()
;; The default separator is space
(let ((org-property-separators `((,property . "\n"))))
(org-entry-get (point) property inherit)))))
(seq-some (lambda (v)
(string-equal value v))
(split-string values "\n")))
(string-equal value (org-ql--value-at
(point) (lambda ()
(org-entry-get (point) property inherit)))))))))))
#+end_src
***** Recent items
I just want to change the default grouping in =org-ql-view-recent-items=...
#+begin_src emacs-lisp
@ -5695,83 +5637,6 @@ and lots of comments which are too long for my Emacs config."
(advice-add #'org-ql-view--format-element :override #'my/org-ql-view--format-element-override))
#+end_src
**** Link tasks to meetings
The workflow here is basically link some tasks to meeting(s) and create a report from tasks linked to a particular meetings. The report also shows the time spent per task thanks to the last modification to =org-ql=.
This is essentially to avoid having to scramble my mind for hints of what I'm supposed to tell I was doing at each meeting.
#+begin_src emacs-lisp
(defun my/org-meeting--prompt ()
(let* ((meetings (org-ql-query
:select #'element-with-markers
:from (org-agenda-files)
:where '(and (todo) (tags "mt") (ts-active :from today to 31))
:order-by 'scheduled))
(data (mapcar
(lambda (meeting)
(let ((raw-value (org-element-property :raw-value meeting))
(scheduled (org-format-timestamp
(org-element-property :scheduled meeting)
(cdr org-time-stamp-formats))))
(cons (format "%-30s %s" raw-value
(propertize scheduled 'face 'org-agenda-date))
meeting)))
meetings))
(ivy-prescient-sort-commands nil))
(cdr
(assoc
(completing-read "Meeting: " data nil t)
data))))
(defun my/org-meeting--format-link (meeting)
(format "[[file:%s::*%s][%s]]"
(buffer-file-name
(marker-buffer
(org-element-property :org-marker meeting)))
(org-element-property :raw-value meeting)
(org-element-property :raw-value meeting)))
(defun my/org-meeting-link (&optional arg)
(interactive "p")
(save-excursion
(org-back-to-heading t)
(let* ((meeting (my/org-meeting--prompt))
(link (my/org-meeting--format-link meeting))
(element (org-element-at-point-no-context)))
(if (or (not arg) (not (org-element-property :MEETING element)))
(org-set-property "MEETING" link)
(let ((range (org-get-property-block
(org-element-property :begin element)))
(case-fold-search nil))
(goto-char (cdr range))
(beginning-of-line)
(insert-and-inherit ":MEETING+: " link "\n")
(org-indent-line))))))
(defun my/org-ql-meeting-tasks (meeting)
(interactive (list (my/org-meeting--prompt)))
(org-ql-search (org-agenda-files)
`(property "MEETING" ,(my/org-meeting--format-link meeting)
:multi t)
:sort '(date priority todo)
:buffer (format "*Meeting Tasks: %s*" (org-element-property :raw-value meeting))
:super-groups '((:auto-outline-path t))))
(defun my/org-ql-meeting-tasks-agenda ()
(interactive)
(let ((meeting (save-window-excursion
(org-agenda-switch-to)
(org-back-to-heading)
(org-ql--add-markers
(org-element-at-point)))))
(my/org-ql-meeting-tasks meeting)))
(with-eval-after-load 'org-agenda
(general-define-key
:keymaps 'org-agenda-mode-map
:states '(normal motion)
"gm" #'my/org-ql-meeting-tasks-agenda))
#+end_src
**** Tracking habits
Let's see how this goes.
@ -6887,6 +6752,7 @@ An example contact entry can look like this:
(use-package calfw
:straight t
:defer t
:config
(add-hook 'cfw:calendar-mode-hook #'my/calfw-setup-buffer))
@ -7013,7 +6879,7 @@ Add a custom LaTeX template without default packages. Packages are indented to b
("\\subsubsection{%s}" . "\\subsubsection*{%s}")))))
;; Make sure to eval the function when org-latex-classes list already exists
(with-eval-after-load-norem 'ox-latex
(with-eval-after-load 'ox-latex
(my/setup-org-latex))
#+end_src
@ -7363,7 +7229,6 @@ I used to use [[https://www.emacswiki.org/emacs/DiredPlus][dired+]], which provi
(use-package dired-recent
:straight t
:after dired
:commands (dired-recent-open)
:config
(dired-recent-mode)
(general-define-key
@ -7382,17 +7247,18 @@ Display icons for files.
#+begin_src emacs-lisp
(use-package all-the-icons-dired
:straight t
:after (dired)
:if (display-graphic-p)
:hook (dired-mode . (lambda ()
(unless (string-match-p "/gnu/store" default-directory)
(all-the-icons-dired-mode))))
:config)
(all-the-icons-dired-mode)))))
#+end_src
Provides stuff like =dired-open-xdg=
#+begin_src emacs-lisp
(use-package dired-open
:straight t
:after (dired)
:commands (dired-open-xdg))
#+end_src
@ -7552,10 +7418,13 @@ Save a telega file to a dired buffer.
(list (telega-msg-for-interactive)
(prefix-numeric-value current-prefix-arg)))
(if (eq arg 4)
(let ((default-directory
(with-current-buffer (my/get-good-buffer 'dired-mode "Dired buffer: ")
(dired-current-directory))))
(progn
(setq telega-msg-save-dir
(with-current-buffer (my/get-good-buffer 'dired-mode "Dired buffer: ")
(dired-current-directory)))
(telega-msg-save msg))
(setq default-directory (expand-file-name "~"))
(setq telega-msg-save-dir nil)
(telega-msg-save msg)))
#+end_src
@ -8325,6 +8194,7 @@ Still, I'll probably switch to =eat= if =eshell= doesn't work for me.
("terminfo/65" "terminfo/65/*")
("integration" "integration/*")
(:exclude ".dir-locals.el" "*-tests.el")))
:commands (eat eat-shell-mode)
:config
(setq eat-shell "/bin/bash"))
#+end_src
@ -9344,6 +9214,7 @@ I'll try to use it for NTTP for now. Will see if I can do more with it.
:straight t
:init
(my-leader-def "au" #'gnus)
:commands (gnus)
:config
(my/persp-add-rule
gnus-summary-mode 0 "gnus"
@ -10706,6 +10577,11 @@ References:
:straight t
:if (not my/remote-server)
:functions (my-google-translate-at-point google-translate--search-tkk)
:commands (google-translate-at-point
google-translate-at-point-reverse
google-translate-query-translate
google-translate-query-translate-reverse
google-translate-smooth-translate)
:custom
(google-translate-backend-method 'curl)
:config
@ -10824,6 +10700,7 @@ There is a package called =devdocs= that does more or less the same, but I like
#+begin_src emacs-lisp
(use-package sx
:straight t
:commands (sx-search sx-tab-frontpage)
:config
(general-define-key
:states '(normal)
@ -10923,6 +10800,7 @@ I don't have access to any proprietary APIs, but LLaMA 3 8b with [[https://ollam
:straight t
:init
(setq ellama-language "English")
:defer t
:config
(require 'llm-ollama)
;; I've looked for this option for 1.5 hours
@ -10945,7 +10823,7 @@ I don't have access to any proprietary APIs, but LLaMA 3 8b with [[https://ollam
The keybindings are a bit crazy to use even with =which-key=, so here goes transient.el.
#+begin_src emacs-lisp
(with-eval-after-load 'ellama
(transient-define-prefix my/ellama ()
(transient-define-prefix my/ellama-transient ()
"Ellama actions."
["General"
:class transient-row
@ -10984,8 +10862,15 @@ The keybindings are a bit crazy to use even with =which-key=, so here goes trans
("sp" "Provider" ellama-provider-select)
("ss" "Session" ellama-session-switch)
("sr" "Rename ression" ellama-session-rename)
("sd" "Delete session" ellama-session-remove)])
(my-leader-def "aie" #'my/ellama))
("sd" "Delete session" ellama-session-remove)]))
(defun my/ellama ()
(interactive)
(require 'ellama)
(call-interactively #'my/ellama-transient))
(my-leader-def "aie" #'my/ellama)
#+end_src
**** Change natural text & diff against the results
@ -11073,10 +10958,10 @@ Also, a prompt to make a text more concise.
- =ellama-code-complete= is pretty good to write migrations
*** Model settings
**** llama3-gradient
[[https://ollama.com/library/llama3-gradient][llama3-gradient]] is a version of LLaMA 3 with an extended context size. It requires setting the =num_ctx= parameter to work correctly.
[[https://ollama.com/library/llama3-gradient][llama3-gradient]] is a version of LLaMA 3 with an extended context size. It requires setting the =num_ctx= parameter to work correctly. For ellama, the following works.
For ellama, the following works:
#+begin_src emacs-lisp
It's problematic to load this so I'm commenting this out for now.
#+begin_src emacs-lisp :tangle no
(with-eval-after-load 'ellama
(cl-defstruct (llm-ollama-gradient (:include llm-ollama)) num-ctx)
@ -11211,6 +11096,7 @@ Another interesting tool is [[https://rclone.org/][rclone]], which provides a si
We'll a package called [[https://github.com/daniel-ness/ini.el][ini.el]] to parse INI files.
#+begin_src emacs-lisp
(use-package ini
:mode "\\.ini\\'"
:straight (:host github :repo "daniel-ness/ini.el"))
#+end_src
@ -11711,6 +11597,7 @@ And insert that in =wakatime.cfg= if necessary.
TREE is a form a defined by `my/index--tree-get'. The return value is
a list of commands as defined by `my/index--commands-display'."
(require 'ini)
(let* ((map-tree (my/index--wakatime-get-map-tree tree))
(map-tree-encoding (ini-encode `(("projectmap" . ,map-tree))))
(map-tree-saved (with-temp-buffer
@ -11726,9 +11613,6 @@ a list of commands as defined by `my/index--commands-display'."
insert-command)))))
#+end_src
#+RESULTS:
: my/index--wakatime-commands
**** Symlinks
The last part here is creating symbolic links.
@ -12258,6 +12142,7 @@ chess.el is a package by John Wiegley.
#+begin_src emacs-lisp
(use-package chess
:commands (chess-pgn-mode)
:straight t)
#+end_src
@ -12415,6 +12300,7 @@ Watch out if you are using EXWM.
#+begin_src emacs-lisp
(use-package zone
:ensure nil
:commands (zone)
:config
(setq original-zone-programs (copy-sequence zone-programs)))