vanilla-emacs
vanilla-emacs copied to clipboard
#+TITLE: Luca's literate Emacs config #+STARTUP: show3levels #+OPTIONS: auto-id:t #+OPTIONS: broken-links:t #+OPTIONS: tags:nil #+HTML_HEAD: #+HTML_HEAD: #+PROPERTY: header-args:emacs-lisp :comments link
- Introduction :PROPERTIES: :CUSTOM_ID: h:49282F28-9E13-48D2-A565-1605B1CC57B8 :END: ** This file :PROPERTIES: :CUSTOM_ID: h:D9ED3ADB-810A-4A1C-A1D3-5397874AFAC7 :END: This file (~readme.org~) is my literate emacs configuration. Every time I save the file, the code blocks get tangled. By default, they get tangled (in sequence) to ~./init.el~. Some blocks override this default (e.g. see the section [[*early-init.el][early-init.el]]).
This file also is exported to HTML, it can be viewed [[https://luca.cambiaghi.me/vanilla-emacs/readme.html][here]]. See [[*org-html-themify][this section]] for my configuration. You can access my blog at the same [[https://luca.cambiaghi.me][website]].
** Why vanilla? :PROPERTIES: :CUSTOM_ID: h:40A8BDAE-F8E3-4DB3-AC8C-7E5067B7EE4D :END: I used [[https://github.com/hlissner/doom-emacs][DOOM emacs]] for an year and I was an happy user. One day I woke up with the wish to understand Emacs a little more.
After about a week (12/01/2021) I had restored my configuration and in the process I understood better concepts such as:
- hooks
- minor and major modes
- advices
It is still a long journey but I am glad I started it. ** Why literate? :PROPERTIES: :CUSTOM_ID: h:B5231F9E-07D2-4738-97FD-78EC648B3F3D :END: Having your configuration in ~org-mode~ has some benefits and some drawbacks. It adds a layer of abstraction between me and my ~init.el~ file, is it worth it?
The main drawback is that it can happen that the ~org-mode~ file has a mistake and tangles an incorrect ~init.el~ file. In that case you can't use your nice bindings but you are thrown in barebones emacs and you have to =C-x C-f= your way to the ~init.el~ and run ~check-parens~.
You can also run ~org-babel-tangle-jump-to-org~ from the tangled file if you add: #+begin_src org ,#+PROPERTY: header-args:emacs-lisp :comments link #+end_src
Another drawback is that a big configuration can be slow to tangle and tangling on save can block ~emacs~. See [[#h:16B948EA-5375-44DE-ACD7-3664D4A9CE5F][this section]] for a solution to this drawback.
Let's consider some of the benefits:
- I can export this file to HTML ([[https://luca.cambiaghi.me/vanilla-emacs/readme.html][here]])
- People can read this file on Github ([[https://github.com/lccambiaghi/vanilla-emacs][here]])
- I can comfortably document my configuration (and not from within comments), include links, ~sh~ code blocks, etc.
- I can organize my configuration blocks in sections, easily disable some headings with ~COMMENT~ ** Modules :PROPERTIES: :CUSTOM_ID: h:C522D670-C206-44F7-96CE-17D01E578287 :END: I tangle this file with the function ~lc/tangle-config~, you can read source code in [[#h:16B948EA-5375-44DE-ACD7-3664D4A9CE5F][this]] section. Every time I save this ~.org~ file, it is tangled to multiple ~.el~ files.
I achieve that by means of this file's "local variables", which I put at the end of the ~.org~ file: #+begin_src org
Local Variables:
eval: (add-hook 'after-save-hook (lambda ()(progn (lc/org-add-ids-to-headlines-in-file) (lc/tangle-config))) nil t)
End:
#+end_src
To design modules, I look at blocks in my config that I would like to toggle on and off. For example if I am on an iPad I may want to not load anything related to Python or ~vterm~.
I assign org properties to each heading. These are determine which ~.el~ file they will be britten to. For example the header of the section concerning ~lsp-mode~ has the following properties: #+begin_src org :PROPERTIES: :CUSTOM_ID: h:6BC08822-D2B3-4BE9-9EBE-C42F89F0E688 :header-args: :emacs-lisp :tangle ./lisp/init-prog-lsp.el :END: #+end_src
All subheadings under it will "inherit" those properties and will be tangled to the same file. We also need to write some ~emacs-lisp~ at the end of the tanged file to "provide" those modules. [[#h:E80DEB4B-6AC9-415D-AF36-0044479D1B5A][Here]] an example of one of these "footer" headers.
I then have a lean ~init.el~ (written in [[#h:7B22A4F3-49A1-4848-A185-B4EEA060EECE][this]] section) which I use to control which modules I want to use in my session. On my main computer I typically want to enable all of them.
** How can I fork it? :PROPERTIES: :CUSTOM_ID: h:A4F99DF1-6997-41C6-92B2-2226913F0C21 :END: I guess one could fork this repo and use this ~org~ file as template. You can duplicate this file, give it another name and tangle that file to your ~init.el~.
I would start with a "small" configuration, just with the "core" functionalities. For example the [[#h:EC68944C-F745-45D8-9905-420E0813DBAF][Startup]], the [[#h:376622D2-A6B7-4050-97C6-413B0D77B89C][Package manager]] and [[#h:403F77CB-A591-4431-B568-CD802876F770][general]] sections would be a good starting point.
Then, you can start importing "sections" you are curious about, for example [[#h:06E0EA9F-7CF4-4B99-8A4A-2C63A4F8A6B6][Completion framework]] . You could also ~COMMENT~ all headings and uncomment only those which are interesting to you. You could find the ~org-toggle-comment~ command useful, after selecting all headings in the file.
** Structure of this configuration :PROPERTIES: :CUSTOM_ID: h:CEDB99C8-27AD-4118-8C8D-29A5882E47AE :END:
- In the second section some optimization of startup time, mostly stolen from smart people.
- In the third section we bootstrap ~straight~ and ~use-package~, our package managers
- In the fourth section we configure ~emacs~ with sane defaults and extend some its core features (e.g. ~help-mode~)
- In the fifth section we set up ~general~, which we use to manage our keybindings and lazy loading of packages. Afterwards we configure ~evil~, for modal editing.
- In the sixth section the invaluable ~org-mode~ with several extensions
- The remaining sections declare my personal configuration of UI and core packages, leveraging the great tools described in this list. ** Notable sections :PROPERTIES: :CUSTOM_ID: h:5752563C-7D7B-4AC2-866D-F0887C7B80AE :END: I am particularly proud of some sections in this configuration, because of one or more of these reasons:
- They improve my productivity considerably
- They are non-standard solutions (or at least hard to find online)
- They are particularly fine-tuned to my workflow
Here they are, without any ranking:
- [[*general][general]]
- [[#h:DC4B461C-91FC-4543-8C9C-FDF28121DCBA][eval operator]]
- [[*evil-indent-plus][evil-indent-plus]]
- [[*evil-iedit-state][evil-iedit-state]]
- [[#h:B26642F5-695F-4475-92B5-2EB9B1C1A96A][evil-mc]]
- [[*org mode][org mode]]
- [[*ob-jupyter][ob-jupyter]]
- [[*org-tree-slide][org-tree-slide]]
- [[*evil-org-mode][evil-org-mode]]
- [[#h:AC175A47-E576-4AA6-A9C7-709129F4C56F][use org-id in links]]
- [[*org-html-themify][org-html-themify]]
- [[#h:DE534B1B-9DF0-4966-A21C-B65B76B6A64E][org-jupyter-mode]]
- [[#h:5F1EC880-5646-4E50-A460-C2F23BD864FC][Modus themes]]
- [[*dashboard][dashboard]]
- [[*popup management][popup management]]
- [[*projectile][projectile]]
- [[#h:DADD41F3-F805-4E89-9EDB-B21350A81A19][hydra-smerge]]
- [[*envrc][envrc]]
- [[*yasnippet][yasnippet]]
- [[*dired][dired]]
- [[*web browser][web browser]]
- [[#h:28CB5546-FBE4-481D-B620-623006DC0FDA][lsp mode]]
- [[*dap-mode][dap-mode]]
- [[*pytest][pytest]]
- [[*jupyter][jupyter]]
- [[*evil-lisp state][evil-lisp state]]
- [[#h:884FB8DF-D672-496E-9068-1FD15F0250E5][Adjust window size (transient)]]
- early-init.el and init.el :PROPERTIES: :CUSTOM_ID: h:EC68944C-F745-45D8-9905-420E0813DBAF :END: ** early-init.el :PROPERTIES: :CUSTOM_ID: h:7DBC58C1-3944-437C-87F9-95C9202BD34E :END: Taken from DOOM's early init #+BEGIN_SRC emacs-lisp :tangle early-init.el ;;; early-init.el --- Early Init File -- lexical-binding: t; no-byte-compile: t -- ;; NOTE: early-init.el is now generated from readme.org. Please edit that file instead
;; Defer garbage collection further back in the startup process (setq gc-cons-threshold most-positive-fixnum gc-cons-percentage 0.6)
;; In Emacs 27+, package initialization occurs before user-init-file' is ;; loaded, but after
early-init-file'. Doom handles package initialization, so
;; we must prevent Emacs from doing it early!
(setq package-enable-at-startup nil)
;; Do not allow loading from the package cache (same reason).
(setq package-quickstart nil)
;; Prevent the glimpse of un-styled Emacs by disabling these UI elements early. (push '(menu-bar-lines . 0) default-frame-alist) (push '(tool-bar-lines . 0) default-frame-alist) (push '(vertical-scroll-bars) default-frame-alist)
;; Resizing the Emacs frame can be a terribly expensive part of changing the ;; font. By inhibiting this, we easily halve startup times with fonts that are ;; larger than the system default. (setq frame-inhibit-implied-resize t)
;; Disable GUI elements (menu-bar-mode -1) (tool-bar-mode -1) (scroll-bar-mode -1) (setq inhibit-splash-screen t) (setq use-file-dialog nil)
;; Prevent unwanted runtime builds in gccemacs (native-comp); packages are ;; compiled ahead-of-time when they are installed and site files are compiled ;; when gccemacs is installed. (setq comp-deferred-compilation nil)
;;; early-init.el ends here #+END_SRC
** init.el: startup optimization :PROPERTIES: :CUSTOM_ID: h:E6162DC2-7E1C-4843-8448-FF104A444B40 :END: Taken from DOOM's init #+BEGIN_SRC emacs-lisp :tangle init.el ;;; init.el --- Personal configuration file -- lexical-binding: t; no-byte-compile: t; -- ;; NOTE: init.el is now generated from readme.org. Please edit that file instead
;; file-name-handler-alist' is consulted on every
require', load' and various ;; path/io functions. You get a minor speed up by nooping this. However, this ;; may cause problems on builds of Emacs where its site lisp files aren't ;; byte-compiled and we're forced to load the *.el.gz files (e.g. on Alpine) (unless (daemonp) (defvar doom--initial-file-name-handler-alist file-name-handler-alist) (setq file-name-handler-alist nil) ;; Restore
file-name-handler-alist' later, because it is needed for handling
;; encrypted or compressed files, among other things.
(defun doom-reset-file-handler-alist-h ()
;; Re-add rather than setq', because changes to
file-name-handler-alist'
;; since startup ought to be preserved.
(dolist (handler file-name-handler-alist)
(add-to-list 'doom--initial-file-name-handler-alist handler))
(setq file-name-handler-alist doom--initial-file-name-handler-alist))
(add-hook 'emacs-startup-hook #'doom-reset-file-handler-alist-h)
(add-hook 'after-init-hook '(lambda ()
;; restore after startup
(setq gc-cons-threshold 16777216
gc-cons-percentage 0.1)))
)
;; Ensure Doom is running out of this file's directory
(setq user-emacs-directory (file-truename (file-name-directory load-file-name)))
#+END_SRC
** init.el: load modules :PROPERTIES: :CUSTOM_ID: h:7B22A4F3-49A1-4848-A185-B4EEA060EECE :END: #+begin_src emacs-lisp :tangle init.el ;; (add-to-list 'load-path "~/.emacs.d/lisp/") (add-to-list 'load-path (expand-file-name "lisp" user-emacs-directory))
(let ((file-name-handler-alist nil) (gc-cons-threshold 100000000)) (require 'init-core) (require 'init-ui-extra) (require 'init-org-roam) (require 'init-org-export) (require 'init-prog-vterm) (require 'init-prog-nix) (require 'init-prog-lsp) (require 'init-prog-python) (require 'init-prog-jupyter) (require 'init-prog-elisp) (require 'init-prog-markdown) (require 'init-prog-stan) ;; (require 'init-prog-r) ;; (require 'init-prog-clojure) (require 'init-prog-tree-sitter) (require 'init-extra-focus) (require 'init-extra-web) ;; (require 'init-extra-rss) ;; (require 'init-extra) )
;;; init.el ends here #+end_src
- Package manager :PROPERTIES: :CUSTOM_ID: h:376622D2-A6B7-4050-97C6-413B0D77B89C :header-args: :emacs-lisp :tangle ./lisp/init-core.el :END: ** bootstrap straight and straight-use-package :PROPERTIES: :CUSTOM_ID: h:686F7A63-013E-48ED-AC56-DF39BD398E20 :END: Some rules/conventions:
- Prefer ~:init~ to ~:custom~. Prefer multiple ~setq~ expressions to one.
- Default to ~:defer t~, use ~:demand~ to force loading
- When packages do not require installation e.g. ~dired~, we need ~:straight (:type built-in)~
- If you specify ~:commands~, they will be autoloaded and the package will be loaded when the commands are first executed
- If you use ~:general~ and bind commands to keys it will automatically load the package on first invokation
NOTE: if you change a package recipe from ~melpa~ to ~github~ in a ~use-package~ block but that package is used as a dependency is used in a previous ~use-package~ block with a ~melpa~ recipe, you will get a warning. Just make sure to declare the "base" package with the ~github~ recipe first.
#+BEGIN_SRC emacs-lisp (setq straight-use-package-by-default t) (setq straight-vc-git-default-clone-depth 1) (setq straight-recipes-gnu-elpa-use-mirror t) ;; (setq straight-check-for-modifications '(check-on-save find-when-checking)) (setq straight-check-for-modifications nil) (setq use-package-always-defer t) (defvar bootstrap-version) (let* ((straight-repo-dir (expand-file-name "straight/repos" user-emacs-directory)) (bootstrap-file (concat straight-repo-dir "/straight.el/bootstrap.el")) (bootstrap-version 5)) (unless (file-exists-p bootstrap-file) (shell-command (concat "mkdir -p " straight-repo-dir " && " "git -C " straight-repo-dir " clone " "https://github.com/raxod502/straight.el.git && " "git -C " straight-repo-dir " checkout 2d407bc"))) (load bootstrap-file nil 'nomessage)) (straight-use-package 'use-package) ;; This is a variable that has been renamed but straight still refers when ;; doing :sraight (:no-native-compile t) (setq comp-deferred-compilation-black-list nil) #+END_SRC
** straight lockfile :PROPERTIES: :CUSTOM_ID: h:D0E05B42-6CEF-45A0-ACF9-E5F14F6DFE76 :END: We can run ~M-x straight-freeze-versions~ to write the file ~straight/versions/default.el~. The content of the file can then be kept in a code block, under version control. The code block can then be tangle again to ~straight/versions/default.el~. We can then restore package versions using ~M-x straight-thaw-versions~.
#+begin_src emacs-lisp :tangle no (("Emacs-wgrep" . "f9687c28bbc2e84f87a479b6ce04407bb97cfb23") ("ace-window" . "0577c426a9833ab107bab46c60d1885c611b2fb9") ("all-the-icons-completion" . "9e7d456b0934ecb568b6f05a8445e3f4ce32261f") ("all-the-icons-dired" . "147ed0dfd1034a686795a08dc63e2c293128597e") ("all-the-icons.el" . "65c496d3d1d1298345beb9845840067bffb2ffd8") ("annalist.el" . "134fa3f0fb91a636a1c005c483516d4b64905a6d") ("avy" . "ba5f035be33693d1a136a5cbeedb24327f551a92") ("blacken" . "563c744f545552cb92e8e84d5be4e2cdbabc93ca") ("bui.el" . "f3a137628e112a91910fd33c0cff0948fa58d470") ("centered-cursor-mode.el" . "4093821cc9759ca5a3c6e527d4cc915fc3a5ad74") ("cfrs" . "f3a21f237b2a54e6b9f8a420a9da42b4f0a63121") ("code-cells.el" . "8660bdeedee360e5eb632f1eb1356eb09d7dfbee") ("consult" . "47c4f405efdf4692c6b7e1dd2098573db9aeae6c") ("corfu" . "c8e6607c90a89ff19062cd37afc17e8bbb86aba3") ("csv-mode" . "43f6106f0d4e21a18b5b7d7708d641d50fbdfa0b") ("dap-mode" . "f918c0580bd17105cbe50aa701a2375abca5a6ab") ("darkroom" . "27b928a6e91c3207742180f7e209bae754c9c1fe") ("dash.el" . "da167c51e9fd167a48d06c7c0ee8e3ac7abd9718") ("devdocs.el" . "4257e59dafbffb2616d240f84c5c25770ee28cac") ("diff-hl" . "4a08b02afec1fc6b1e84de46cc34f75f6c9c3bcc") ("dired-hacks" . "7c0ef09d57a80068a11edc74c3568e5ead5cc15a") ("dired-hide-dotfiles" . "6a379f23f64045f5950d229254ce6f32dbbf5364") ("docker-tramp.el" . "930d7b46c180d8a13240a028c1b40af84f2a3219") ("doom-modeline" . "edf18b93cceb5cf00e1006d0034663ef4d9fdc11") ("el-get" . "9353309744e4f8a7c9b1adf22ec99536fb2146b0") ("eldoc" . "eab3f2590621c6559cb92a5edc519fc7e51ef850") ("elisp-refs" . "8f84280997d8b233d66fb9958a34b46078c58b03") ("elisp-tree-sitter" . "5e1091658d625984c6c5756e3550c4d2eebd73a1") ("emacs-async" . "c78bab7506a70a735d2c3deab13fa87bf44a83d3") ("emacs-bind-map" . "510a24138d8de3b8df0783f1ac493a551fc9bd74") ("emacs-dashboard" . "1d3fce6e8e8605f770f2b23184b055029128c477") ("emacs-hide-mode-line" . "bc5d293576c5e08c29e694078b96a5ed85631942") ("emacs-jupyter" . "0a7055d7b12cf98723110415b08ee91869fa7d94") ("emacs-libvterm" . "a940dd2ee8a82684860e320c0f6d5e15d31d916f") ("emacs-python-pytest" . "ea53891a219659d9339220d5db50a8c525f199af") ("emacs-undo-fu" . "e81c8da4416b15cac9d5ac7574e11471417a65ca") ("emacs-web-server" . "22ce66ea43e0eadb9ec1d691a35d9695fc29cee6") ("emacs-websocket" . "82b370602fa0158670b1c6c769f223159affce9b") ("emacs-which-key" . "1217db8c6356659e67b35dedd9f5f260c06f6e99") ("emacs-winum" . "c5455e866e8a5f7eab6a7263e2057aff5f1118b9") ("emacs-zmq" . "38dc6c4119aee57666caf8f97c8a3d7f678823e0") ("emacsmirror-mirror" . "75b9477acee5ab4bf6f404d6d6700d0524cdb4e3") ("emacsql" . "374726060d74df0e2bcb9d0355ff41e2c400ed30") ("embark" . "b80d96ce0ab79e73829322e46c6d7493eb2b8c34") ("envrc" . "57d78f0138d9c676dff182e713249ad055ccf85d") ("epl" . "78ab7a85c08222cd15582a298a364774e3282ce6") ("eros" . "dd8910279226259e100dab798b073a52f9b4233a") ("evil" . "3e41a823334abbba9cf16e482855699054d9dfe0") ("evil-cleverparens" . "8c45879d49bfa6d4e414b6c1df700a4a51cbb869") ("evil-collection" . "e55718869252a8cd46e61e350bb514194a37f2f8") ("evil-goggles" . "8f20a16e74016f37ad76dc4f2230d9b00c6df3c2") ("evil-iedit-state" . "93e4cbfcee802adbb9dd0ebd5836fea4fa932849") ("evil-indent-plus" . "b4dacbfdb57f474f798bfbf5026d434d549eb65c") ("evil-lisp-state" . "3c65fecd9917a41eaf6460f22187e2323821f3ce") ("evil-mc" . "63fd2fe0c213a4cc31c464d246f92931c4cb720f") ("evil-nerd-commenter" . "42ba1a473b4f1df061baddd2f8b812a2f35e366e") ("evil-org-mode" . "a9706da260c45b98601bcd72b1d2c0a24a017700") ("evil-snipe" . "a79177df406a79b4ffa25743c752f21363bba1cc") ("evil-surround" . "282a975bda83310d20a2c536ac3cf95d2bf188a5") ("exec-path-from-shell" . "3a8d97c096c2c5714b667130fd8a80d5622ee067") ("f.el" . "50af874cd19042f17c8686813d52569b1025c76a") ("flycheck" . "278d0810f05eb03600d835c2bdd67d6b55a58034") ("gcmh" . "0089f9c3a6d4e9a310d0791cf6fa8f35642ecfd9") ("general.el" . "9651024e7f40a8ac5c3f31f8675d3ebe2b667344") ("git-timemachine" . "ca09684e94767cc0b2339b77b778b4de4f9d104f") ("gnu-elpa-mirror" . "bc03f8141c285538418daeff450f67d90ead2403") ("goto-chg" . "278cd3e6d5107693aa2bb33189ca503f22f227d0") ("helpful" . "67cdd1030b3022d3dc4da2297f55349da57cde01") ("highlight-indent-guides" . "cf352c85cd15dd18aa096ba9d9ab9b7ab493e8f6") ("hl-todo" . "c0f0555a6b9f3818f29e6394db0b45d6d5675edf") ("ht.el" . "c4c1be487d6ecb353d07881526db05d7fc90ea87") ("hydra" . "9e9e00cb240ea1903ffd36a54956b3902c379d29") ("iedit" . "27c61866b1b9b8d77629ac702e5f48e67dfe0d3b") ("imenu-list" . "76f2335ee6f2f066d87fe4e4729219d70c9bc70d") ("inheritenv" . "7e4c8b0d0a43b6f1c6c4d6dbd2f3bf5ce7f20067") ("isearch-mb" . "e70ba8f594afef989006493dd71bd693a29e9f42") ("kind-icon" . "6e0e0c5c2f846685861ef6c157044b1a55572359") ("let-alist" . "592553db5929b54db40af0df90c5add0aaca045b") ("lsp-mode" . "95a5270ff783af063392286e8f45cf338c5a9765") ("lsp-pyright" . "fa6698a6e33880feb16d264172aa665d14cb8a6f") ("lsp-treemacs" . "72d367757a89453a712f6ba1df9b6e789ece2bbd") ("lsp-ui" . "96b1ecbfbf87a775f05b5f0b55253376a3bd61e7") ("magit" . "b1702991eec2c068d282fc2f1bd665726a14e10d") ("marginalia" . "e63d27e6fb24ed16339de9d813c555d40aa1e4ca") ("markdown-mode" . "521658eb32e456681592443e04ae507c3a59ed07") ("melpa" . "1a054aba2409fb8ae12a634952f3d1336a14eb70") ("modus-themes" . "03f7046dff86c5342af778ad3f9850af7e950aed") ("nix-mode" . "20ee8d88900b169831d6b0783bd82d2625e940c7") ("no-littering" . "13414b7a294fa6f35bbeb535cdcab6b256e39da7") ("ob-async" . "9aac486073f5c356ada20e716571be33a350a982") ("olivetti" . "a31ac05a161a91fe5c157930b62a6c07037982ee") ("orderless" . "f2c78c4a6059c5f892e48a3887d4368a547515ff") ("org" . "6304afcaa40a29291bc0705f8527e0ab75f7b807") ("org-appear" . "ffbd742267ff81ba8433177fac5d7fe22b6d68a9") ("org-fragtog" . "680606189d5d28039e6f9301b55ec80517a24005") ("org-reverse-datetree" . "c42078f8601b7f600135f66e75246a53c5f9975f") ("org-roam" . "d71675fb479d11da3ae597bb13bc1c96256ff0b0") ("org-superstar-mode" . "03be6c0a3081c46a59b108deb8479ee24a6d86c0") ("org-tree-slide" . "3faa042393ebfe5699a3bffce775f039d7416ceb") ("paredit" . "8330a41e8188fe18d3fa805bb9aa529f015318e8") ("persistent-scratch" . "4e159967801b75d07303221c4e5a2b89039c6a11") ("persp-projectile" . "4e374d7650c7e041df5af5ac280a44d4a4ec705a") ("perspective-el" . "d3afc52ed098b713b6607943bd1ee0ef899db267") ("pfuture" . "bde5b06795e3e35bfb2bba4c34b538d506a0856e") ("pkg-info" . "76ba7415480687d05a4353b27fea2ae02b8d9d61") ("posframe" . "c91d4d53fa479ceb604071008ce0a901770eff57") ("projectile" . "20df208385ce7b80207602c9931e31094eca85fb") ("python-mode" . "29c6815c585c200eda2541b678e499d06c3e14d2") ("rainbow-delimiters" . "a32b39bdfe6c61c322c37226d66e1b6d4f107ed0") ("restart-emacs" . "1607da2bc657fe05ae01f7fdf26f716eafead02c") ("s.el" . "08661efb075d1c6b4fa812184c1e5e90c08795a9") ("shrink-path.el" . "c14882c8599aec79a6e8ef2d06454254bb3e1e41") ("smartparens" . "37f77bf2e2199be9fe27e981317b02cfd0e8c70e") ("spinner" . "34905eae12a236753fa88abc831eff1e41e8576e") ("straight.el" . "af5437f2afd00936c883124d6d3098721c2d306c") ("svg-lib" . "5ff87b7f9a85e728360a63d8e4ae7aaa7eccf7d3") ("toml-mode.el" . "f6c61817b00f9c4a3cab1bae9c309e0fc45cdd06") ("transient" . "270eff1c7cc910dfe9882e97df608627028eaa40") ("transpose-frame" . "12e523d70ff78cc8868097b56120848befab5dbc") ("tree-sitter-langs" . "f4effc81fcac3592bce7072619a0e17043412cf4") ("treemacs" . "b18a05b1f62074a40e6011d83cd4c92cbee040dd") ("use-package" . "a7422fb8ab1baee19adb2717b5b47b9c3812a84c") ("vertico" . "742c57635eadf74743f0d70b9125c4d2a95e22df") ("vterm-toggle" . "2a6861ef6af91dad4be082139214a30116b50acf") ("with-editor" . "e8569e027ff5c9bef8d9ff0734e3293e1c0574a2") ("xwwp" . "f67e070a6e1b233e60274deb717274b000923231") ("yaml-mode" . "535273d5a1eb76999d20afbcf4d9f056d8ffd2da") ("yasnippet" . "5cbdbf0d2015540c59ed8ee0fcf4788effdf75b6")) #+end_src
** Enable use-package statistics :PROPERTIES: :CUSTOM_ID: h:F75CE115-0722-49E4-9BD8-8A57BADAD080 :END: If you'd like to see how many packages you've loaded, what stage of initialization they've reached, and how much aggregate time they've spent (roughly), you can enable ~use-package-compute-statistics~ after loading use-package but before any use-package forms, and then run the command M-x ~use-package-report~ to see the results. The buffer displayed is a tabulated list. You can use =S= in a column to sort the rows based on it.
#+BEGIN_SRC emacs-lisp (setq use-package-compute-statistics t) #+END_SRC
From the report:
- dashboard 3.18 (org)
- evil-collection 2.48 (evil)
- projectile 1.67
- devdocs 1.17
- Emacs :PROPERTIES: :CUSTOM_ID: h:BB41A3C4-8047-40D7-B99D-1BFDAC930D25 :header-args: :emacs-lisp :tangle ./lisp/init-core.el :END: ** Sane defaults :PROPERTIES: :CUSTOM_ID: h:94661C0F-79D0-4CD4-AA3F-CADB0E79398C :END: Inspired by https://github.com/natecox/dotfiles/blob/master/emacs/emacs.d/nathancox.org
To debug a LISP function use ~debug-on-entry~. You step /in/ with =d= and /over/ with =e=
#+BEGIN_SRC emacs-lisp (use-package emacs :init (setq inhibit-startup-screen t initial-scratch-message nil sentence-end-double-space nil ring-bell-function 'ignore frame-resize-pixelwise t)
(setq user-full-name "Luca Cambiaghi" user-mail-address "[email protected]")
(setq read-process-output-max (* 1024 1024)) ;; 1mb
;; always allow 'y' instead of 'yes'. (defalias 'yes-or-no-p 'y-or-n-p)
;; default to utf-8 for all the things (set-charset-priority 'unicode) (setq locale-coding-system 'utf-8 coding-system-for-read 'utf-8 coding-system-for-write 'utf-8) (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (set-selection-coding-system 'utf-8) (prefer-coding-system 'utf-8) (setq default-process-coding-system '(utf-8-unix . utf-8-unix))
;; write over selected text on input... like all modern editors do (delete-selection-mode t)
;; enable recent files mode. (recentf-mode t) (setq recentf-exclude `(,(expand-file-name "straight/build/" user-emacs-directory) ,(expand-file-name "eln-cache/" user-emacs-directory) ,(expand-file-name "etc/" user-emacs-directory) ,(expand-file-name "var/" user-emacs-directory)))
;; don't want ESC as a modifier
(global-set-key (kbd "
;; Don't persist a custom file, this bites me more than it helps (setq custom-file (make-temp-file "")) ; use a temp file as a placeholder (setq custom-safe-themes t) ; mark all themes as safe, since we can't persist now (setq enable-local-variables :all) ; fix =defvar= warnings
;; stop emacs from littering the file system with backup files (setq make-backup-files nil auto-save-default nil create-lockfiles nil)
;; follow symlinks (setq vc-follow-symlinks t)
;; don't show any extra window chrome (when (window-system) (tool-bar-mode -1) (toggle-scroll-bar -1))
;; enable winner mode globally for undo/redo window layout changes (winner-mode t)
(show-paren-mode t)
;; less noise when compiling elisp (setq byte-compile-warnings '(not free-vars unresolved noruntime lexical make-local)) (setq native-comp-async-report-warnings-errors nil) (setq load-prefer-newer t)
;; clean up the mode line (display-time-mode -1) (setq column-number-mode t)
;; use common convention for indentation by default (setq-default indent-tabs-mode t) (setq-default tab-width 2)
;; Enable indentation+completion using the TAB key. ;; Completion is often bound to M-TAB. (setq tab-always-indent 'complete) ) #+END_SRC
** custom variables :PROPERTIES: :CUSTOM_ID: h:AC160303-DF53-4597-9BAA-3AE1E7E13431 :END: #+begin_src emacs-lisp (use-package emacs :init (setq lc/is-ipad ( ;; < > (length (shell-command-to-string "uname -a | grep iPad")) 0))
(setq lc/is-windows (eq system-type 'windows-nt))
(defcustom lc/default-font-family "fira code" "Default font family" :type 'string :group 'lc)
(defcustom lc/variable-pitch-font-family "Sans Serif" ;; "cantarell" ;; "Variable pitch font family" :type 'string :group 'lc)
(defcustom lc/laptop-font-size (if lc/is-windows 100 150) "Font size used for laptop" :type 'int :group 'lc)
(defcustom lc/monitor-font-size
150
"Font size used for laptop"
:type 'int
:group 'lc)
(defcustom lc/theme nil "Current theme (light or dark)" :type 'symbol :options '(light dark) :group 'lc)
;; (setq lc/is-low-power (string= (system-name) "pntk"))
;; (setq lc/is-slow-ssh (string= (getenv "IS_TRAMP") "true"))
) #+end_src
** Font :PROPERTIES: :CUSTOM_ID: h:3CDD0539-5A95-468C-85F0-71B391D7115D :END: #+begin_src emacs-lisp (use-package emacs :hook (after-init . lc/set-font-size) :init (defun lc/get-font-size () "font size is calculated according to the size of the primary screen" (let* (;; (command "xrandr | awk '/primary/{print sqrt( ($(nf-2)/10)^2 + ($nf/10)^2 )/2.54}'") (command "osascript -e 'tell application "finder" to get bounds of window of desktop' | cut -d',' -f3") (screen-width (string-to-number (shell-command-to-string command)))) ;;< (if (> screen-width 2560) lc/monitor-font-size lc/laptop-font-size))) (defun lc/set-font-size () (interactive) ;; Main typeface (set-face-attribute 'default nil :family lc/default-font-family :height (lc/get-font-size)) ;; Set the fixed pitch face (monospace) (set-face-attribute 'fixed-pitch nil :family lc/default-font-family) ;; Set the variable pitch face (set-face-attribute 'variable-pitch nil :family lc/variable-pitch-font-family) ;; modeline (set-face-attribute 'mode-line nil :family lc/default-font-family :height (lc/get-font-size)) (set-face-attribute 'mode-line-inactive nil :family lc/default-font-family :height (lc/get-font-size)) ) ) #+end_src
** COMMENT Adjust font size :PROPERTIES: :CUSTOM_ID: h:D9DB7FA2-18C6-46A9-9567-1FEFADD523AC :END: #+begin_src emacs-lisp (use-package emacs :init (defun lc/adjust-font-size (height) "Adjust font size by given height. If height is '0', reset font size. This function also handles icons and modeline font sizes." (interactive "nHeight ('0' to reset): ") (let ((new-height (if (zerop height) (lc/get-font-size) (+ height (face-attribute 'default :height))))) (set-face-attribute 'default nil :height new-height) (set-face-attribute 'fixed-pitch nil :height new-height) (set-face-attribute 'variable-pitch nil :height new-height) (set-face-attribute 'mode-line nil :height new-height) (set-face-attribute 'mode-line-inactive nil :height new-height) (message "Font size: %s" new-height)))
(defun lc/increase-font-size ()
"Increase font size by 0.5 (5 in height)."
(interactive)
(lc/adjust-font-size 5))
(defun lc/decrease-font-size ()
"Decrease font size by 0.5 (5 in height)."
(interactive)
(lc/adjust-font-size (- 5)))
(defun lc/reset-font-size ()
"Reset font size according to the `lc/default-font-size'."
(interactive)
(lc/adjust-font-size 0))
)
#+end_src
** Zoom :PROPERTIES: :CUSTOM_ID: h:f73c5fb4-246e-423c-8cfd-0482dcb1f699 :END: #+begin_src emacs-lisp (use-package emacs :init (global-set-key (kbd "C-=") 'text-scale-increase) (global-set-key (kbd "C--") 'text-scale-decrease) ) #+end_src
** macOS :PROPERTIES: :CUSTOM_ID: h:7BA73F60-D31F-4A96-9DEE-02A4FC1BEE8B :END: #+BEGIN_SRC emacs-lisp (use-package emacs :init (defun lc/is-macos () (and (eq system-type 'darwin) (= 0 (length (shell-command-to-string "uname -a | grep iPad"))))) (when (lc/is-macos) (setq mac-command-modifier 'super) ; command as super (setq mac-option-modifier 'meta) ; alt as meta (setq mac-control-modifier 'control) ) ;; when on emacs-mac (when (fboundp 'mac-auto-operator-composition-mode) (mac-auto-operator-composition-mode) ;; enables font ligatures (global-set-key [(s c)] 'kill-ring-save) (global-set-key [(s v)] 'yank) (global-set-key [(s x)] 'kill-region) (global-set-key [(s q)] 'kill-emacs) ) ) #+END_SRC
** Garbage collector magic hack :PROPERTIES: :CUSTOM_ID: h:A17DC2B8-4E73-4F43-BD6E-07ADAEC9A3A7 :END: Used by DOOM to manage garbage collection #+BEGIN_SRC emacs-lisp (use-package gcmh :demand :config (gcmh-mode 1)) #+END_SRC
** helpful :PROPERTIES: :CUSTOM_ID: h:273CA7B2-AE07-4571-AB4A-92523B11DB41 :END: #+BEGIN_SRC emacs-lisp (use-package helpful :after evil :init (setq evil-lookup-func #'helpful-at-point) :bind ([remap describe-function] . helpful-callable) ([remap describe-command] . helpful-command) ([remap describe-variable] . helpful-variable) ([remap describe-key] . helpful-key)) #+END_SRC
** eldoc :PROPERTIES: :CUSTOM_ID: h:FC10A86D-86E6-45C2-8759-ADE233B0D80C :END: #+begin_src emacs-lisp (use-package eldoc :hook (emacs-lisp-mode cider-mode)) #+end_src
** exec path from shell :PROPERTIES: :CUSTOM_ID: h:B1611A44-8567-4370-80B4-9D904434E274 :END: #+begin_src emacs-lisp (use-package exec-path-from-shell ;; :if (memq window-system '(mac ns)) :if (lc/is-macos) :hook (emacs-startup . (lambda () (setq exec-path-from-shell-arguments '("-l")) ; removed the -i for faster startup (exec-path-from-shell-initialize))) ;; :config ;; (exec-path-from-shell-copy-envs ;; '("GOPATH" "GO111MODULE" "GOPROXY" ;; "NPMBIN" "LC_ALL" "LANG" "LC_TYPE" ;; "SSH_AGENT_PID" "SSH_AUTH_SOCK" "SHELL" ;; "JAVA_HOME")) ) #+end_src
** no littering :PROPERTIES: :CUSTOM_ID: h:2DB2921D-434E-4321-A15E-4B3329ABC946 :END: #+begin_src emacs-lisp (use-package no-littering :demand :config (with-eval-after-load 'recentf (add-to-list 'recentf-exclude no-littering-var-directory) (add-to-list 'recentf-exclude no-littering-etc-directory)) ) #+end_src
** server mode :PROPERTIES: :CUSTOM_ID: h:5F50A0A6-0C8E-4804-BBF5-A8D9B1372F12 :END: #+begin_src emacs-lisp (use-package emacs :init (unless (and (fboundp 'server-running-p) (server-running-p)) (server-start))) #+end_src
** Auto-pair parenthesis :PROPERTIES: :CUSTOM_ID: h:BE3F251D-5F39-4337-B27C-CFB81EE9A504 :END: #+begin_src emacs-lisp (use-package emacs :hook ((org-jupyter-mode . (lambda () (lc/add-local-electric-pairs '()))) (org-mode . (lambda () (lc/add-local-electric-pairs '(;(?= . ?=) (?~ . ?~)))))) :init ;; auto-close parentheses (electric-pair-mode +1) (setq electric-pair-preserve-balance nil) ;; don't skip newline when auto-pairing parenthesis (setq electric-pair-skip-whitespace-chars '(9 32)) ;; mode-specific local-electric pairs (defconst lc/default-electric-pairs electric-pair-pairs) (defun lc/add-local-electric-pairs (pairs) "Example usage: (add-hook 'jupyter-org-interaction-mode '(lambda () (set-local-electric-pairs '()))) " (setq-local electric-pair-pairs (append lc/default-electric-pairs pairs)) (setq-local electric-pair-text-pairs electric-pair-pairs))
;; disable auto pairing for < >
(add-function :before-until electric-pair-inhibit-predicate
(lambda (c) (eq c ?< ;; >
)))
)
#+end_src
You can use below block to print the value of ~electric-pair-pairs~ #+begin_src emacs-lisp :tangle no (mapcar (lambda (elm) (char-to-string (car elm))) electric-pair-pairs) #+end_src
** Rename file :PROPERTIES: :CUSTOM_ID: h:6A783697-911E-433D-B8ED-CC70F5F217FA :END: #+begin_src emacs-lisp (use-package emacs :init (defun lc/rename-current-file () "Rename the current visiting file and switch buffer focus to it." (interactive) (let ((new-filename (lc/expand-filename-prompt (format "Rename %s to: " (file-name-nondirectory (buffer-file-name)))))) (if (null (file-writable-p new-filename)) (user-error "New file not writable: %s" new-filename)) (rename-file (buffer-file-name) new-filename 1) (find-alternate-file new-filename) (message "Renamed to and now visiting: %s" (abbreviate-file-name new-filename)))) (defun lc/expand-filename-prompt (prompt) "Return expanded filename prompt." (expand-file-name (read-file-name prompt))) )
#+end_src
** xref :PROPERTIES: :CUSTOM_ID: h:AC4FAE7D-5AF3-4D5A-810F-55AB4C7D1C1B :END: #+begin_src emacs-lisp (use-package xref :straight (:type built-in) :init (setq xref-prompt-for-identifier nil) ;; always find references of symbol at point ;; configured in consult ;; (setq xref-show-definitions-function #'xref-show-definitions-completing-read) ;; (setq xref-show-xrefs-function #'xref-show-definitions-buffer) ; for grep and the like ;; (setq xref-file-name-display 'project-relative) ;; (setq xref-search-program 'grep) ) #+end_src
** Don't close windows on escape :PROPERTIES: :CUSTOM_ID: h:8BB05594-D909-4E99-960B-5624F915E664 :END: Sometimes =ESC= kills my window layout. This advice prevents that from happening. #+begin_src emacs-lisp (use-package emacs :init (defadvice keyboard-escape-quit (around keyboard-escape-quit-dont-close-windows activate) (let ((buffer-quit-function (lambda () ()))) ad-do-it)) )
#+end_src
- Keybindings :PROPERTIES: :CUSTOM_ID: h:A992628D-9095-4392-9C96-2633E8DDDE08 :header-args: :emacs-lisp :tangle ./lisp/init-core.el :END: ** general :PROPERTIES: :CUSTOM_ID: h:403F77CB-A591-4431-B568-CD802876F770 :END: In this block we load ~general~ and define bindings for generic commands e.g. ~find-file~. The commands provided by packages should be binded in the ~use-package~ block, thanks to the ~:general~ keyword. NOTE: We need to load ~general~ before ~evil~, otherwise the ~:general~ keyword in the ~use-package~ blocks won't work.
#+BEGIN_SRC emacs-lisp (use-package general :demand t :config (general-evil-setup)
(general-create-definer lc/leader-keys :states '(normal insert visual emacs) :keymaps 'override :prefix "SPC" :global-prefix "C-SPC")
(general-create-definer lc/local-leader-keys :states '(normal visual) :keymaps 'override :prefix "," :global-prefix "SPC m")
(general-nmap :states 'normal "gD" '(xref-find-references :wk "references") )
(lc/leader-keys
"SPC" '(execute-extended-command :which-key "execute command")
"`" '((lambda () (interactive) (switch-to-buffer (other-buffer (current-buffer) 1))) :which-key "prev buffer")
"
";" '(eval-expression :which-key "eval sexp")
"b" '(:ignore t :which-key "buffer")
"br" 'revert-buffer
;; "bs" '((lambda () (interactive)
;; (pop-to-buffer "*scratch*"))
;; :wk "scratch")
"bd" 'kill-current-buffer
"c" '(:ignore t :which-key "code")
"f" '(:ignore t :which-key "file")
"fD" '((lambda () (interactive) (delete-file (buffer-file-name))) :wk "delete")
"ff" 'find-file
"fs" 'save-buffer
"fR" '(lc/rename-current-file :wk "rename")
"g" '(:ignore t :which-key "git")
;; keybindings defined in magit
"h" '(:ignore t :which-key "describe")
"he" 'view-echo-area-messages
"hf" 'describe-function
"hF" 'describe-face
"hl" 'view-lossage
"hL" 'find-library
"hm" 'describe-mode
"hk" 'describe-key
"hK" 'describe-keymap
"hp" 'describe-package
"hv" 'describe-variable
"k" '(:ignore t :which-key "kubernetes")
;; keybindings defined in kubernetes.el
"o" '(:ignore t :which-key "org")
;; keybindings defined in org-mode
;; "p" '(:ignore t :which-key "project")
;; keybindings defined in projectile
"s" '(:ignore t :which-key "search")
;; keybindings defined in consult
"t" '(:ignore t :which-key "toggle")
"t d" '(toggle-debug-on-error :which-key "debug on error")
"t l" '(display-line-numbers-mode :wk "line numbers")
"t w" '((lambda () (interactive) (toggle-truncate-lines)) :wk "word wrap")
;; "t +" '(lc/increase-font-size :wk "+ font")
;; "t -" '(lc/decrease-font-size :wk "- font")
;; "t +" 'text-scale-increase
;; "t -" 'text-scale-decrease
;; "t 0" '(lc/reset-font-size :wk "reset font")
"u" '(universal-argument :wk "universal")
"w" '(:ignore t :which-key "window")
"wl" 'windmove-right
"wh" 'windmove-left
"wk" 'windmove-up
"wj" 'windmove-down
"wr" 'winner-redo
"wd" 'delete-window
"w=" 'balance-windows-area
"wD" 'kill-buffer-and-window
"wu" 'winner-undo
"wr" 'winner-redo
"wm" '(delete-other-windows :wk "maximize")
"x" '(:ignore t :which-key "browser")
;; keybindings defined in xwwp
)
(lc/local-leader-keys :states 'normal "d" '(:ignore t :which-key "debug") "e" '(:ignore t :which-key "eval") "t" '(:ignore t :which-key "test"))) #+END_SRC
** evil :PROPERTIES: :CUSTOM_ID: h:D32C2E37-37BE-4033-B9A5-270D47570991 :END: *** evil mode :PROPERTIES: :CUSTOM_ID: h:331844DD-1F0E-4348-84F5-F53350749226 :END: Best VIM reference: https://countvajhula.com/2021/01/21/vim-tip-of-the-day-a-series/
Search tricks:
- =*= / # to go to next/prev occurence of symbol under point
- =/= starts a search, use =n= / =N= to go to next/prev
- Use the =gn= noun to, for example, change next match with =cgn=
Some interesting vim nouns:
- =_= :: first character in the line (synonym to =^=)
- =g_= :: last character on the line (synonym to =$=)
Marks:
- =ma= :: mark a position in buffer and save it to register ~a~
- ='a= :: go to mark ~a~
- =mA= :: mark position and filename [
- =]'= :: go to next mark
- =''= :: go back to previous mark (kept track automatically)
- =g;= :: go to previous change location
- =gi= :: go back to insert mode where you left off
- =C-o= :: jump (out) to previous position (useful after =gd=)
- =C-i= :: jump (in) to previous position
Macros:
- =qq= :: record macro ~q~
- =@q= :: execute macro ~q~
Registers:
- ="ayio= :: save object in register ~a~ "
- ="ap= :: paste object in register ~a~ "
- Macros are saved in registers so you can simply ="qp= and paste your macro!! "
NOTE: I inserted the above quotes because the single double quotes were breaking my VIM object detection in the rest of the file
#+BEGIN_SRC emacs-lisp (use-package evil :demand :general (lc/leader-keys "wv" 'evil-window-vsplit "ws" 'evil-window-split) :init (setq evil-want-integration t) (setq evil-want-keybinding nil) (setq evil-want-C-u-scroll t) (setq evil-want-C-i-jump t) (setq evil-want-Y-yank-to-eol t) ;; (setq evil-respect-visual-line-mode t) (setq evil-undo-system 'undo-fu) (setq evil-search-module 'evil-search) ;; enables gn ;; move to window when splitting (setq evil-split-window-below t) (setq evil-vsplit-window-right t) ;; (setq-local evil-scroll-count 0) (setq evil-auto-indent nil) ;; emacs bindings in insert mode ;; (setq evil-disable-insert-state-bindings t) :config (evil-mode 1) (define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state) (define-key evil-motion-state-map "_" 'evil-end-of-line) (define-key evil-motion-state-map "0" 'evil-beginning-of-line) (evil-set-initial-state 'messages-buffer-mode 'normal) (evil-set-initial-state 'dashboard-mode 'normal) ;; don't move cursor after == (defun lc/evil-dont-move-cursor (orig-fn &rest args) (save-excursion (apply orig-fn args))) (advice-add 'evil-indent :around #'lc/evil-dont-move-cursor) ;; disable TAB in normal mode to jump forward ;; (with-eval-after-load 'evil-maps ;; (define-key evil-motion-state-map (kbd "TAB") nil)) ) #+END_SRC
*** evil-collection :PROPERTIES: :CUSTOM_ID: h:04B5B86D-5E51-41A8-ACE5-D07EBCDBA4E7 :END: #+BEGIN_SRC emacs-lisp (use-package evil-collection :after evil :demand :init (setq evil-collection-magit-use-z-for-folds nil) :config (evil-collection-init)) #+END_SRC
*** eval operator :PROPERTIES: :CUSTOM_ID: h:DC4B461C-91FC-4543-8C9C-FDF28121DCBA :END: This section provides a custom eval operator, accessible with =gr=. This gives you super powers when coupled with custom text objects (provided by [[*evil-indent-plus][evil-indent-plus]] and [[*evil-cleverparens][evil-cleverparens]] )
For example:
- =grab= evals the form at point
- =grad= evals the top-level form (e.g. use-package blocks or functions)
- =grak= evals the function in ~python~
- =grr= evals the line
#+begin_src emacs-lisp (use-package evil :config (defcustom evil-extra-operator-eval-modes-alist '((emacs-lisp-mode eros-eval-region) ;; (scheme-mode geiser-eval-region) (clojure-mode cider-eval-region) (jupyter-repl-interaction-mode jupyter-eval-line-or-region) ;; when executing in src block ;; (python-mode python-shell-send-region) ;; when executing in org-src-edit mode ) "Alist used to determine evil-operator-eval's behaviour. Each element of this alist should be of this form: (MAJOR-MODE EVAL-FUNC [ARGS...]) MAJOR-MODE denotes the major mode of buffer. EVAL-FUNC should be a function with at least 2 arguments: the region beginning and the region end. ARGS will be passed to EVAL-FUNC as its rest arguments" :type '(alist :key-type symbol) :group 'evil-extra-operator)
(evil-define-operator evil-operator-eval (beg end)
"Evil operator for evaluating code."
:move-point nil
(interactive "
(define-key evil-motion-state-map "gr" 'evil-operator-eval)
)
#+end_src
*** evil-goggles :PROPERTIES: :CUSTOM_ID: h:DF40753F-AE4C-4A22-90B1-7468A5C86485 :END: #+BEGIN_SRC emacs-lisp (use-package evil-goggles :after evil :demand :init (setq evil-goggles-duration 0.05) :config (push '(evil-operator-eval :face evil-goggles-yank-face :switch evil-goggles-enable-yank :advice evil-goggles--generic-async-advice) evil-goggles--commands) (evil-goggles-mode) (evil-goggles-use-diff-faces) ) #+END_SRC
*** evil-snipe :PROPERTIES: :CUSTOM_ID: h:142C0F28-5AE4-4034-B61C-3CE4D1E6B2BB :END: #+BEGIN_SRC emacs-lisp (use-package evil-snipe :after evil :demand :config (evil-snipe-mode +1) (evil-snipe-override-mode +1)) #+END_SRC
*** evil-nerd-commenter :PROPERTIES: :CUSTOM_ID: h:1FF5CDDF-D69C-46D3-A5CD-97C058F5E8BA :END: #+BEGIN_SRC emacs-lisp (use-package evil-nerd-commenter :general (general-nvmap "gc" 'evilnc-comment-operator "gC" 'evilnc-copy-and-comment-operator) ) #+END_SRC
*** evil-surround :PROPERTIES: :CUSTOM_ID: h:0F159B03-E7CB-4AC7-8871-BED1534559E6 :END: (
- Use =S)= to surround something without spaces e.g. ~(sexp)~
- Use =S(= to surround something with spaces e.g. ~( sexp )~ )
#+BEGIN_SRC emacs-lisp (use-package evil-surround :general (:states 'operator "s" 'evil-surround-edit "S" 'evil-Surround-edit) (:states 'visual "S" 'evil-surround-region "gS" 'evil-Surround-region)) #+END_SRC
*** evil-indent-plus :PROPERTIES: :CUSTOM_ID: h:F5CFE676-28DE-4B1F-BDDF-3DA431FAB728 :END: To select a function in ~python~:
- Stand on a line in the body of the function (root, not an if)
- Select with =vik=
#+begin_src emacs-lisp (use-package evil-indent-plus :after evil :demand :config (define-key evil-inner-text-objects-map "i" 'evil-indent-plus-i-indent) (define-key evil-outer-text-objects-map "i" 'evil-indent-plus-a-indent) (define-key evil-inner-text-objects-map "k" 'evil-indent-plus-i-indent-up) (define-key evil-outer-text-objects-map "k" 'evil-indent-plus-a-indent-up) (define-key evil-inner-text-objects-map "j" 'evil-indent-plus-i-indent-up-down) (define-key evil-outer-text-objects-map "j" 'evil-indent-plus-a-indent-up-down) ) #+end_src
*** evil cleverparens: outer form text object :PROPERTIES: :CUSTOM_ID: h:02F42E4A-7DB4-4150-AA74-22CB3FE7636C :END: NOTE:
- Mark the outer form with =v a f=
#+begin_src emacs-lisp (use-package evil-cleverparens :after evil :hook (emacs-lisp-mode . lc/init-cleverparens) :init (defun lc/init-cleverparens () (require 'evil-cleverparens-util) (evil-define-text-object evil-cp-a-defun (count &optional beg end type) "An outer text object for a top level sexp (defun)." (if (evil-cp--inside-form-p) (let ((bounds (evil-cp--top-level-bounds))) (evil-range (car bounds) (cdr bounds) 'inclusive :expanded t)) (error "Not inside a sexp.")))
(evil-define-text-object evil-cp-inner-defun (count &optional beg end type)
"An inner text object for a top level sexp (defun)."
(if (evil-cp--inside-form-p)
(let ((bounds (evil-cp--top-level-bounds)))
(evil-range (1+ (car bounds)) (1- (cdr bounds)) 'inclusive :expanded t))
(error "Not inside a sexp.")))
(define-key evil-outer-text-objects-map "f" #'evil-cp-a-defun)
(define-key evil-inner-text-objects-map "f" #'evil-cp-inner-defun)
)
) #+end_src
*** evil-iedit-state :PROPERTIES: :CUSTOM_ID: h:4055D055-3521-41DE-8BC5-0196F89BB3F8 :END: Keybindings:
- =TAB= :: toggle occurrence
- =n= / =N= :: next/prev occurrence
- =F= :: restrict scope to function
- =J= / =K= :: extend scope of match down/up
- =V= :: toggle visibility of matches
#+begin_src emacs-lisp (use-package evil-iedit-state :straight (evil-iedit-state :type git :host github :repo "kassick/evil-iedit-state" :branch "master") :general (lc/leader-keys "s e" '(evil-iedit-state/iedit-mode :wk "iedit") "s q" '(evil-iedit-state/quit-iedit-mode :wk "iedit quit"))) #+end_src
*** evil-mc: multi cursor :PROPERTIES: :CUSTOM_ID: h:B26642F5-695F-4475-92B5-2EB9B1C1A96A :END: #+begin_src emacs-lisp (use-package evil-mc :after evil :general (general-nmap "M-n" #'evil-mc-make-and-goto-next-match ) (general-vmap ;; "gm" '(:keymap evil-mc-cursors-map) "A" #'evil-mc-make-cursor-in-visual-selection-end "I" #'evil-mc-make-cursor-in-visual-selection-beg) (general-nmap "gm" '(:keymap evil-mc-cursors-map) "Q" #'evil-mc-undo-all-cursors ;; "M-p" #'evil-mc-make-and-goto-prev-cursor ) :config (global-evil-mc-mode 1) ) #+end_src
*** Fix scroll error when centaur tabs is active :PROPERTIES: :CUSTOM_ID: h:FD4609AC-AD2E-44EA-81FC-0154D84C9701 :END: Taken from this PR: https://github.com/emacs-evil/evil/pull/1323/files
#+begin_src emacs-lisp (use-package evil :init (defun lc/evil-posn-x-y (position) (let ((xy (posn-x-y position))) (when header-line-format (setcdr xy (+ (cdr xy) (or (and (fboundp 'window-header-line-height) (window-header-line-height)) evil-cached-header-line-height (setq evil-cached-header-line-height (evil-header-line-height)))))) (when (fboundp 'window-tab-line-height) (setcdr xy (+ (cdr xy) (window-tab-line-height)))) xy)) :config (advice-add 'evil-posn-x-y :override #'lc/evil-posn-x-y) ) #+end_src
** which-key :PROPERTIES: :CUSTOM_ID: h:4F5BF801-2E48-44B3-8822-240BC6D08732 :END: #+BEGIN_SRC emacs-lisp (use-package which-key :demand :general (lc/leader-keys "?" 'which-key-show-top-level ) :init (setq which-key-separator " ") (setq which-key-prefix-prefix "+") (setq which-key-show-early-on-C-h t) ;; make sure which-key doesn't show normally but refreshes quickly after it is ;; triggered. (setq which-key-idle-delay 10000) (setq which-key-idle-secondary-delay 0.05) :config (which-key-mode)) #+END_SRC
- Org :PROPERTIES: :CUSTOM_ID: h:B1DBE90D-B6C9-4BD4-B15B-185FE238D236 :header-args: :emacs-lisp :tangle ./lisp/init-core.el :END: ** org mode :PROPERTIES: :CUSTOM_ID: h:934C85A9-D8DB-455F-A19C-570300047FD5 :END: Interesting bits:
- If you use + in lists it will show up as below:
- subitem
- you can cycle to next TODO state with ~org-shiftright~
- You can access custom agenda views with ~org-agenda~, mapped to =SPC o A=
- Yo insert a src block use =, i= and then type initials e.g. ~jp~ for ~jupyter-python~
#+BEGIN_SRC emacs-lisp (use-package org ;; :straight org-plus-contrib ;; :straight (:type built-in) :hook ((org-mode . prettify-symbols-mode) (org-mode . visual-line-mode) (org-mode . variable-pitch-mode)) :general (lc/leader-keys "f t" '(org-babel-tangle :wk "tangle") "o C" '(org-capture :wk "capture") "o l" '(org-todo-list :wk "todo list")
"o c" '((lambda () (interactive)
(persp-switch "main")
(find-file (concat user-emacs-directory "readme.org")))
:wk "open config")
)
(lc/local-leader-keys :keymaps 'org-mode-map "a" '(org-archive-subtree :wk "archive subtree") "E" '(org-export-dispatch :wk "export") "i" '(org-insert-structure-template :wk "insert src") "l" '(:ignore true :wk "link") "l l" '(org-insert-link :wk "insert link") "l s" '(org-store-link :wk "store link") "L" '((lambda () (interactive) (org-latex-preview)) :wk "latex preview") ;; "L" '((lambda () (interactive) (org--latex-preview-region (point-min) (point-max))) :wk "latex") "r" '(org-refile :wk "refile") "n" '(org-toggle-narrow-to-subtree :wk "narrow subtree") "p" '(org-priority :wk "priority") "q" '(org-set-tags-command :wk "tag") "s" '(org-sort :wk "sort") "t" '(:ignore true :wk "todo") "t t" '(org-todo :wk "heading todo") "t s" '(org-schedule :wk "schedule") "t d" '(org-deadline :wk "deadline") "x" '(org-toggle-checkbox :wk "toggle checkbox") ) (org-mode-map :states 'insert "TAB" 'lc/org-indent-or-complete "S-TAB" nil) (org-mode-map :states 'normal "z i" '(org-toggle-inline-images :wk "inline images")) :init ;; general settings (when (file-directory-p "~/org") (setq org-directory "~/org" +org-export-directory "~/org/export" org-default-notes-file "~/org/personal/todo.org" org-id-locations-file "~/org/.orgids" )) (setq ;; org-export-in-background t org-src-preserve-indentation t ;; do not put two spaces on the left org-startup-indented t ;; org-startup-with-inline-images t org-hide-emphasis-markers t org-catch-invisible-edits 'smart) (setq org-image-actual-width nil) (setq org-indent-indentation-per-level 1) (setq org-list-demote-modify-bullet '(("-" . "+") ("+" . "*"))) ;; disable modules for faster startup (setq org-modules '(ol-docview org-habit)) (setq org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "PROG(p)" "|" "HOLD(h)" "DONE(d)"))) (setq-default prettify-symbols-alist '(("#+BEGIN_SRC" . "»") ("#+END_SRC" . "«") ("#+begin_src" . "»") ("#+end_src" . "«") ("lambda" . "λ") ("->" . "→") ("->>" . "↠"))) (setq prettify-symbols-unprettify-at-point 'right-edge) (defun lc/org-indent-or-complete () "Complete if point is at end of a word, otherwise indent line." (interactive) (if (looking-at "\>") (dabbrev-expand nil) (org-cycle) )) (setq warning-suppress-types (append warning-suppress-types '((org-element-cache)))) :config ;; (efs/org-font-setup) (add-to-list 'org-structure-template-alist '("sh" . "src shell")) (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) (add-to-list 'org-structure-template-alist '("py" . "src python")) (add-to-list 'org-structure-template-alist '("clj" . "src clojure")) (add-to-list 'org-structure-template-alist '("jp" . "src jupyter-python")) (add-to-list 'org-structure-template-alist '("jr" . "src jupyter-R")) ;; fontification (add-to-list 'org-src-lang-modes '("jupyter-python" . python)) (add-to-list 'org-src-lang-modes '("jupyter-R" . R)) ;; latex ;; (setq org-latex-compiler "xelatex") ;; see https://www.reddit.com/r/emacs/comments/l45528/questions_about_mving_from_standard_latex_to_org/gkp4f96/?utm_source=reddit&utm_medium=web2x&context=3 ;; (setq org-latex-pdf-process '("TEXINPUTS=:$HOME/git/AltaCV//: tectonic %f")) (setq org-latex-pdf-process '("tectonic %f")) (setq org-export-backends '(html)) ;; (add-to-list 'org-export-backends 'beamer) (plist-put org-format-latex-options :scale 1.2) ) #+END_SRC
** org code blocks in monospace font :PROPERTIES: :CUSTOM_ID: h:57AD5032-5D49-436D-883D-BA44315D7B65 :END: #+begin_src emacs-lisp (use-package org :config (defun my-adjoin-to-list-or-symbol (element list-or-symbol) (let ((list (if (not (listp list-or-symbol)) (list list-or-symbol) list-or-symbol))) (require 'cl-lib) (cl-adjoin element list)))
(eval-after-load "org" '(mapc (lambda (face) (set-face-attribute face nil :inherit (my-adjoin-to-list-or-symbol 'fixed-pitch (face-attribute face :inherit)))) (list 'org-code 'org-block ;; 'org-table 'org-block-background ))) )
#+end_src
** org agenda :PROPERTIES: :CUSTOM_ID: h:345DD7DC-12A2-444B-923E-A61B11AB2D26 :END: #+begin_src emacs-lisp (use-package org :general (lc/leader-keys "o a" '(org-agenda-list :wk "agenda") "o A" '(org-agenda :wk "agenda") "o C" '(org-capture :wk "capture") "o l" '(org-todo-list :wk "todo list") "o c" '((lambda () (interactive) (find-file (concat user-emacs-directory "readme.org"))) :wk "open config") "o n" '((lambda () (interactive) (org-agenda nil "n")) :wk "next") "o i" '((lambda () (interactive) (find-file (concat org-roam-directory "/personal/inbox.org"))) :wk "open todos")) :init (setq org-agenda-files '())
;; if roam work folder exists, add to agenda files (when (file-directory-p "~/roam/work") (setq org-agenda-files (append org-agenda-files '("~/roam/work/todo.org"))))
(when (file-directory-p "~/roam/personal")
(setq org-agenda-files
(append org-agenda-files
'("~/roam/personal/20210721120340-birthdays.org" "~/roam/personal/inbox.org"))))
(setq org-agenda-custom-commands '(("d" "Dashboard" ((agenda "" ((org-deadline-warning-days 7))) (todo "NEXT" ((org-agenda-overriding-header "Next Tasks"))) (tags-todo "agenda/ACTIVE" ((org-agenda-overriding-header "Active Projects"))))) ("n" "Next Tasks" ((todo "NEXT" ((org-agenda-overriding-header "Next Tasks"))))) ("w" "Work Tasks" tags-todo "+work"))) ) #+end_src
** COMMENT Hack to get org-version to work :PROPERTIES: :CUSTOM_ID: h:78D6F7DF-905E-4016-BF91-4E9E38580633 :END: #+begin_src emacs-lisp (use-package org :config ;; temporary hack until straight.el supports building org properly (defun org-git-version () "The Git version of org-mode. Inserted by installing org-mode or when a release is made." ;; (require 'git) ;; (let ((git-repo (expand-file-name ;; "straight/repos/org/" user-emacs-directory))) ;; (string-trim ;; (git-run "describe" ;; "--match=release*" ;; "--abbrev=6" ;; "HEAD"))) "9.2.4")
(defun org-release () "The release version of org-mode. Inserted by installing org-mode or when a release is made." ;; (require 'git) ;; (let ((git-repo (expand-file-name ;; "straight/repos/org/" user-emacs-directory))) ;; (string-trim ;; (string-remove-prefix ;; "release_" ;; (git-run "describe" ;; "--match=release*" ;; "--abbrev=0" ;; "HEAD")))) "9.2.4" )
;; (provide 'org-version)
;; (use-package git)
) #+end_src
** org capture templates :PROPERTIES: :CUSTOM_ID: h:7B2FC50C-4C28-4E16-96B9-CF3CB51DBE08 :END: #+begin_src emacs-lisp (use-package org :init (setq org-capture-templates `(("b" "Blog" entry (file+headline "personal/todo.org" "Blog") ,(concat "* WRITE %^{Title} %^g\n" "SCHEDULED: %^t\n" ":PROPERTIES:\n" ":CAPTURED: %U\n:END:\n\n" "%i%?")) ("d" "New Diary Entry" entry(file+olp+datetree"~/org/personal/diary.org" "Daily Logs") "* %^{thought for the day} :PROPERTIES: :CATEGORY: %^{category} :SUBJECT: %^{subject} :MOOD: %^{mood} :END: :RESOURCES: :END:
\*What was one good thing you learned today?*:
- %^{whatilearnedtoday}
\*List one thing you could have done better*:
- %^{onethingdobetter}
\*Describe in your own words how your day was*:
- %?")
("i" "Inbox" entry
(file+headline "personal/todo.org" "Inbox")
,(concat "* %^{Title}\n"
":PROPERTIES:\n"
":CAPTURED: %U\n"
":END:\n\n"
"%i%l"))
("u" "New URL Entry" entry
(file+function "~/org/personal/dailies.org" org-reverse-datetree-goto-date-in-file)
"* [[%^{URL}][%^{Description}]] %^g %?")
("w" "Work" entry
(file+headline "personal/todo.org" "Work")
,(concat "* TODO [#A] %^{Title} :@work:\n"
"SCHEDULED: %^t\n"
":PROPERTIES:\n:CAPTURED: %U\n:END:\n\n"
"%i%?"))))
)
#+end_src
** COMMENT org-toc :PROPERTIES: :CUSTOM_ID: h:7715C1A7-7228-4A41-92DB-7F3F1D3A88C4 :END: This function walks a particular directory searching for ~.org~ files and headings within them. It creates a table of contents of that directory, with links. It is useful to create an automatic ~index.org~ file for org directories. I currently use it for my knowledge library.
#+begin_src emacs-lisp (use-package org :init (defun lc/org-toc () (interactive) (let ((headings (delq nil (cl-loop for f in (f-entries "." (lambda (f) (f-ext? f "org")) t) append (with-current-buffer (find-file-noselect f) (org-map-entries (lambda () ;; < (when (> 2 (car (org-heading-components))) (cons f (nth 4 (org-heading-components))))))))))) (switch-to-buffer (get-buffer-create "toc")) (erase-buffer) (org-mode) (cl-loop for (file . file-headings) in (seq-group-by #'car headings) do (insert (format "* [[%s][%s]] \n" file (file-relative-name file))) (cl-loop for (file . heading) in file-headings do (insert (format "** [[%s::*%s][%s]]\n" file heading heading)))))) ) #+end_src
** cycle only one heading :PROPERTIES: :CUSTOM_ID: h:06CE7B8F-EFC7-4216-99C5-DE419A649C83 :END: #+begin_src emacs-lisp (use-package org :init (defun +org-cycle-only-current-subtree-h (&optional arg) "Toggle the local fold at the point, and no deeper. `org-cycle's standard behavior is to cycle between three levels: collapsed, subtree and whole document. This is slow, especially in larger org buffer. Most of the time I just want to peek into the current subtree -- at most, expand ,only the current subtree.
All my (performant) foldings needs are met between this and org-show-subtree' (on zO for evil users), and
org-cycle' on shift-TAB if I need it."
(interactive "P")
(unless (eq this-command 'org-shifttab)
(save-excursion
(org-beginning-of-line)
(let (invisible-p)
(when (and (org-at-heading-p)
(or org-cycle-open-archived-trees
(not (member org-archive-tag (org-get-tags))))
(or (not arg)
(setq invisible-p (outline-invisible-p (line-end-position)))))
(unless invisible-p
(setq org-cycle-subtree-status 'subtree))
(org-cycle-internal-local)
t)))))
:config
;; Only fold the current tree, rather than recursively
(add-hook 'org-tab-first-hook #'+org-cycle-only-current-subtree-h)
)
#+end_src
** async tangle :PROPERTIES: :CUSTOM_ID: h:16B948EA-5375-44DE-ACD7-3664D4A9CE5F :END: Taken from https://github.com/KaratasFurkan/.emacs.d
#+begin_src emacs-lisp (use-package org :config (require 's) (defun lc/async-process (command &optional name filter) "Start an async process by running the COMMAND string with bash. Return the process object for it.
NAME is name for the process. Default is "async-process".
FILTER is function that runs after the process is finished, its args should be "(process output)". Default is just messages the output." (make-process :command `("bash" "-c" ,command) :name (if name name "async-process") :filter (if filter filter (lambda (process output) (message (s-trim output))))))
(defun lc/tangle-config () "Export code blocks from the literate config file asynchronously." (interactive) (let ((command (if (file-directory-p "/Applications/Emacs.app") "/Applications/Emacs.app/Contents/MacOS/Emacs %s --batch --eval '(org-babel-tangle nil "%s")'" ;; on iPad "emacs %s --batch --eval '(org-babel-tangle nil "%s")'" ;; "emacs %s --batch --eval '(org-babel-tangle nil "%s")' 2>&1 | grep -v '^Loading.*...$' | grep -v '^Using ' | grep -v '^dump '| grep -v '^Finding '" ))) ;; prevent emacs from killing until tangle-process finished ;; (add-to-list 'kill-emacs-query-functions ;; (lambda () ;; (or (not (process-live-p (get-process "tangle-process"))) ;; (y-or-n-p ""fk/tangle-config" is running; kill it? ")))) ;; tangle config asynchronously (lc/async-process (format command (expand-file-name "readme.org" user-emacs-directory) (expand-file-name "init.el" user-emacs-directory)) "tangle-process") )
)
) #+end_src
** org reverse datetree :PROPERTIES: :CUSTOM_ID: h:5640311D-E41F-495D-BF61-9A1CE260B67D :END: #+begin_src emacs-lisp (use-package org-reverse-datetree :after org :demand) #+end_src
** org-superstar :PROPERTIES: :CUSTOM_ID: h:9F509775-5901-47BA-AE19-C193598F3FE8 :END: #+BEGIN_SRC emacs-lisp (use-package org-superstar :hook (org-mode . org-superstar-mode) :init (setq org-superstar-headline-bullets-list '("✖" "✚" "◉" "○" "▶") ;; org-superstar-special-todo-items t org-ellipsis " ↴ ") ) #+END_SRC
** COMMENT bigger org headings :PROPERTIES: :CUSTOM_ID: h:199FAA28-4FB5-40EA-80F9-6D69F759221E :END: #+begin_src emacs-lisp (use-package org :config (let* ((variable-tuple (cond ((x-list-fonts "Fira Code") '(:font "Fira Code")) (nil (warn "Cannot find a Fira Code Font. Install it.")))) (base-font-color (face-foreground 'default nil 'default)) (headline `(:inherit default :weight bold :foreground ,base-font-color)))
(custom-theme-set-faces
'user
`(org-level-8 ((t (,@headline ,@variable-tuple))))
`(org-level-7 ((t (,@headline ,@variable-tuple))))
`(org-level-6 ((t (,@headline ,@variable-tuple))))
`(org-level-5 ((t (,@headline ,@variable-tuple))))
`(org-level-4 ((t (,@headline ,@variable-tuple :height 1.1))))
`(org-level-3 ((t (,@headline ,@variable-tuple :height 1.2))))
`(org-level-2 ((t (,@headline ,@variable-tuple :height 1.3))))
`(org-level-1 ((t (,@headline ,@variable-tuple :height 1.4))))
`(org-document-title ((t (,@headline ,@variable-tuple :height 1.5 :underline nil))))))
) #+end_src
** highlight todo :PROPERTIES: :CUSTOM_ID: h:6944ED2A-A880-48CC-A6F6-86847D15BF65 :END: Look at ~hl-todo-keyword-faces~ to know the keywords (can't get to change them..). #+begin_src emacs-lisp (use-package hl-todo :hook ((prog-mode org-mode) . lc/hl-todo-init) :init (defun lc/hl-todo-init () (setq-local hl-todo-keyword-faces '(("HOLD" . "#cfdf30") ("TODO" . "#ff9977") ("NEXT" . "#b6a0ff") ("PROG" . "#00d3d0") ("FIXME" . "#ff9977") ("DONE" . "#44bc44") ("REVIEW" . "#6ae4b9") ("DEPRECATED" . "#bfd9ff"))) (hl-todo-mode)) ) #+end_src
** org babel :PROPERTIES: :CUSTOM_ID: h:9C85D837-71F4-4205-B1DD-5ECBE3FD4B11 :END: #+BEGIN_SRC emacs-lisp (use-package org :general (lc/local-leader-keys :keymaps 'org-mode-map "'" '(org-edit-special :wk "edit") "-" '(org-babel-demarcate-block :wk "split block") "z" '(org-babel-hide-result-toggle :wk "fold result")) (lc/local-leader-keys :keymaps 'org-src-mode-map "'" '(org-edit-src-exit :wk "exit")) ;;FIXME :init (setq org-confirm-babel-evaluate nil) :config (org-babel-do-load-languages 'org-babel-load-languages '((emacs-lisp . t) ;; (clojure . t) ;; (ledger . t) (shell . t))) (add-hook 'org-babel-after-execute-hook 'org-display-inline-images 'append) )
;; enable mermaid diagram blocks ;; (use-package ob-mermaid ;; :custom (ob-mermaid-cli-path "~/.asdf/shims/mmdc")) #+END_SRC
** ob-async :PROPERTIES: :CUSTOM_ID: h:D407A727-7E47-48F6-AA29-F487A8890F43 :END: #+begin_src emacs-lisp (use-package ob-async :hook (org-load . (lambda () (require 'ob-async))) :init (setq ob-async-no-async-languages-alist '("jupyter-python" "jupyter-R" "jupyter-julia"))) #+end_src
** org-tree-slide :PROPERTIES: :CUSTOM_ID: h:0642C8C0-3B4E-4C72-BD41-40F58FFAB736 :END: #+begin_src emacs-lisp (use-package org-tree-slide :after org :hook ((org-tree-slide-play . (lambda () (+remap-faces-at-start-present))) (org-tree-slide-stop . (lambda () (+remap-faces-at-stop-present)))) :general (lc/leader-keys "t p" '(org-tree-slide-mode :wk "present")) (general-nmap :keymaps '(org-tree-slide-mode-map org-mode-map) "C-j" 'org-tree-slide-move-next-tree "C-k" 'org-tree-slide-move-previous-tree) :init (setq org-tree-slide-activate-message "Presentation mode ON") (setq org-tree-slide-deactivate-message "Presentation mode OFF") (setq org-tree-slide-indicator nil) (setq org-tree-slide-breadcrumbs " > ") (setq org-tree-slide-heading-emphasis t) (setq org-tree-slide-slide-in-waiting 0.025) (setq org-tree-slide-content-margin-top 4) (defun +remap-faces-at-start-present () (setq-local face-remapping-alist '((default (:height 1.50) variable-pitch) (fixed-pitch (:height 1.2) fixed-pitch) ;; (org-verbatim (:height 1.2) org-verbatim) ;; (org-block (:height 1.2) org-block) )) ;; (setq-local olivetti-body-width 95) (olivetti-mode 1) (display-fill-column-indicator-mode 0) (hide-mode-line-mode 1) (diff-hl-mode 0) (centaur-tabs-mode 0)) (defun +remap-faces-at-stop-present () (setq-local face-remapping-alist '((default variable-pitch default))) ;; (setq-local olivetti-body-width 120) (olivetti-mode 0) (display-fill-column-indicator-mode 1) (hide-mode-line-mode 0) (doom-modeline-mode 1) (diff-hl-mode 1) (centaur-tabs-mode 1)) (setq org-tree-slide-breadcrumbs nil) (setq org-tree-slide-header nil) (setq org-tree-slide-slide-in-effect nil) (setq org-tree-slide-heading-emphasis nil) (setq org-tree-slide-cursor-init t) (setq org-tree-slide-modeline-display nil) (setq org-tree-slide-skip-done nil) (setq org-tree-slide-skip-comments t) (setq org-tree-slide-fold-subtrees-skipped t) (setq org-tree-slide-skip-outline-level 8) ;; or 0? (setq org-tree-slide-never-touch-face t) ;; :config ;; (org-tree-slide-presentation-profile) ;; :custom-face ;; (org-tree-slide-heading-level-1 ((t (:height 1.8 :weight bold)))) ;; (org-tree-slide-heading-level-2 ((t (:height 1.5 :weight bold)))) ;; (org-tree-slide-heading-level-3 ((t (:height 1.5 :weight bold)))) ;; (org-tree-slide-heading-level-4 ((t (:height 1.5 :weight bold)))) ) #+end_src
** evil-org-mode :PROPERTIES: :CUSTOM_ID: h:FB4154EE-27F2-4B52-B0BB-5F95D7920EAD :END: Taken from DOOM:
- nice ~+org/insert-item-below~ function
- ~evil~ bindings for ~org-agenda~
- text objects:
- use ~vie~ to select everything inside a src block
- use ~vir~ to select everything inside a heading
- use ==ie= to format a code block
#+begin_src emacs-lisp
(use-package evil-org-mode
:straight (evil-org-mode :type git :host github :repo "hlissner/evil-org-mode")
:hook ((org-mode . evil-org-mode)
(org-mode . (lambda ()
(require 'evil-org)
(evil-normalize-keymaps)
(evil-org-set-key-theme '(textobjects))
(require 'evil-org-agenda)
(evil-org-agenda-set-keys))))
:bind
([remap evil-org-org-insert-heading-respect-content-below] . +org/insert-item-below) ;; "<C-return>"
([remap evil-org-org-insert-todo-heading-respect-content-below] . +org/insert-item-above) ;; "<C-S-return>"
:general
(general-nmap
:keymaps 'org-mode-map
:states 'normal
"RET" #'org-open-at-point
;; "RET" #'+org/dwim-at-point
)
:init
(defun +org--insert-item (direction)
(let ((context (org-element-lineage
(org-element-context)
'(table table-row headline inlinetask item plain-list)
t)))
(pcase (org-element-type context)
;; Add a new list item (carrying over checkboxes if necessary)
((or item
plain-list)
;; Position determines where org-insert-todo-heading and org-insert-item
;; insert the new list item.
(if (eq direction 'above)
(org-beginning-of-item)
(org-end-of-item)
(backward-char))
(org-insert-item (org-element-property :checkbox context))
;; Handle edge case where current item is empty and bottom of list is
;; flush against a new heading.
(when (and (eq direction 'below)
(eq (org-element-property :contents-begin context)
(org-element-property :contents-end context)))
(org-end-of-item)
(org-end-of-line)))
;; Add a new table row
((or `table `table-row)
(pcase direction
('below (save-excursion (org-table-insert-row t))
(org-table-next-row))
('above (save-excursion (org-shiftmetadown))
(+org/table-previous-row))))
;; Otherwise, add a new heading, carrying over any todo state, if
;; necessary.
(_
(let ((level (or (org-current-level) 1)))
;; I intentionally avoid `org-insert-heading' and the like because they
;; impose unpredictable whitespace rules depending on the cursor
;; position. It's simpler to express this command's responsibility at a
;; lower level than work around all the quirks in org's API.
(pcase direction
(`below
(let (org-insert-heading-respect-content)
(goto-char (line-end-position))
(org-end-of-subtree)
(insert "\n" (make-string level ?*) " ")))
(`above
(org-back-to-heading)
(insert (make-string level ?*) " ")
(save-excursion (insert "\n"))))
(when-let* ((todo-keyword (org-element-property :todo-keyword context))
(todo-type (org-element-property :todo-type context)))
(org-todo
(cond ((eq todo-type 'done)
;; Doesn't make sense to create more "DONE" headings
(car (+org-get-todo-keywords-for todo-keyword)))
(todo-keyword)
('todo)))))))
(when (org-invisible-p)
(org-show-hidden-entry))
(when (and (bound-and-true-p evil-local-mode)
(not (evil-emacs-state-p)))
(evil-insert 1))))
(defun +org/insert-item-below (count) "Inserts a new heading, table cell or item below the current one." (interactive "p") (dotimes (_ count) (+org--insert-item 'below)))
(defun +org/insert-item-above (count) "Inserts a new heading, table cell or item above the current one." (interactive "p") (dotimes (_ count) (+org--insert-item 'above)))
) #+end_src
** exporters :org_export: :PROPERTIES: :CUSTOM_ID: h:EB525EBF-91AA-4A9F-8D49-5D1DFFE670FB :header-args: :emacs-lisp :tangle ./lisp/init-org-export.el :END: *** org-html-themify :PROPERTIES: :CUSTOM_ID: h:89A2FA66-9647-4BF8-A45C-EA61D5D95FDC :END: I use this package to export my config to HTML. I then push it to the ~gh-pages~ branch
NOTE:
- Make sure the mode is active
- Run ~org-export-dispatch~ and export to HTML
- Make sure to set ~org-html-themify-themes~ to lighter variant so it is easier to read
- The second export will not generate correct .css . Restart emacs and retry
#+begin_src emacs-lisp (use-package org-html-themify :after modus-themes :straight (org-html-themify :type git :host github :repo "DogLooksGood/org-html-themify" :files (".el" ".js" "*.css")) :hook (org-mode . org-html-themify-mode) :init (setq org-html-themify-themes '((light . modus-operandi) (dark . modus-operandi))) :config ;; otherwise it complains about invalid face (require 'hl-line)
)
(use-package htmlize :after org-html-themify) #+end_src
*** ox-gfm :PROPERTIES: :CUSTOM_ID: h:021F6686-3272-4900-BB50-CB98C5C5C2BA :END: #+BEGIN_SRC emacs-lisp (use-package ox-gfm :commands (org-gfm-export-as-markdown org-gfm-export-to-markdown) :after org ) #+END_SRC
*** ox-ipynb :PROPERTIES: :CUSTOM_ID: h:F97C3D33-1B2E-4D80-BD51-E4052A5535DE :END: The first block of the org file is used to determine the exported language. To override this we can write: #+begin_example #+OX-IPYNB-LANGUAGE: ipython #+end_example
It seems that also ~jupyter-python~ should be replaced with ~ipython~ for the export to work.
#+BEGIN_SRC emacs-lisp (use-package ox-ipynb :straight (ox-ipynb :type git :host github :repo "jkitchin/ox-ipynb") :commands (ox-ipynb-export-org-file-to-ipynb-file)) #+END_SRC
*** ox-reveal :PROPERTIES: :CUSTOM_ID: h:6181675A-C397-4449-A8D9-AFDAECD6D4EE :END: #+begin_src emacs-lisp (use-package org-re-reveal :after org :init ;; (setq org-re-reveal-root (expand-file-name "../../" (locate-library "dist/reveal.js" t)) ;; org-re-reveal-revealjs-version "4") (setq org-re-reveal-root "./reveal.js" org-re-reveal-revealjs-version "3.8" org-re-reveal-external-plugins '((progress . "{ src: '%s/plugin/toc-progress/toc-progress.js', async: true, callback: function() { toc_progress.initialize(); toc_progress.create();} }")) )) #+end_src
*** weblorg :PROPERTIES: :CUSTOM_ID: h:8739EFFA-1436-4DF9-AD0D-AD0C94144A40 :END: #+begin_src emacs-lisp (use-package weblorg)
(use-package templatel)
(use-package htmlize) #+end_src
*** COMMENT LaTeX export :PROPERTIES: :CUSTOM_ID: h:A590CE55-C9B6-4559-BA39-0C4833030010 :END: #+begin_src emacs-lisp (use-package org :config (with-eval-after-load 'ox-latex (add-to-list 'org-latex-classes '("org-plain-latex" "\documentclass{article} [NO-DEFAULT-PACKAGES] [PACKAGES] [EXTRA]" ("\section{%s}" . "\section*{%s}") ("\subsection{%s}" . "\subsection*{%s}") ("\subsubsection{%s}" . "\subsubsection*{%s}") ("\paragraph{%s}" . "\paragraph*{%s}") ("\subparagraph{%s}" . "\subparagraph*{%s}"))) (setq org-latex-listings 't) (add-to-list 'org-latex-packages-alist '("" "listings")) (add-to-list 'org-latex-packages-alist '("" "color")) ;; (setq org-latex-listings 'minted) ;; (add-to-list 'org-latex-packages-alist '("newfloat" "minted")) ) ) #+end_src
In the beginning of the org document: #+begin_example #+SETUPFILE: ../work/latex.setup #+end_example
*** ox-cv :PROPERTIES: :CUSTOM_ID: h:9AB653A8-CACD-45B4-A330-7EB2421370E6 :END: #+begin_src emacs-lisp (use-package ox-altacv :straight (ox-altacv :type git :host github :repo "lccambiaghi/org-cv") :config (require 'ox-altacv)) #+end_src
** org-appear :PROPERTIES: :CUSTOM_ID: h:474F4B7B-336B-48A8-B888-B46584E331AC :END: Automatically disaply emphasis markers and links when the cursor is on them. #+begin_src emacs-lisp (use-package org-appear :straight (org-appear :type git :host github :repo "awth13/org-appear") :hook (org-mode . org-appear-mode) :init (setq org-appear-autoemphasis t) (setq org-appear-autolinks t) (setq org-appear-autosubmarkers t) )
#+end_src
** automatic latex preview :PROPERTIES: :CUSTOM_ID: h:040DD3F1-043C-403F-A145-813BA69FC42E :END: #+begin_src emacs-lisp (use-package org-fragtog :hook (org-mode . org-fragtog-mode)) #+end_src
** COMMENT org-encrypt :PROPERTIES: :CUSTOM_ID: h:65931801-3A7E-4828-B052-F978731F3004 :END:
- Use ~org-encrypt-entry~ on a headline
- Use ~org-decrypt-entry~ to decrypt #+begin_src emacs-lisp (use-package org :config (require 'org-crypt) (require 'epa-file) (epa-file-enable) (org-crypt-use-before-save-magic) (setq org-tags-exclude-from-inheritance (quote ("crypt"))) (setq org-crypt-key nil) (defun ag/reveal-and-move-back () (org-reveal) (goto-char ag/old-point)) (defun ag/org-reveal-after-save-on () (setq ag/old-point (point)) (add-hook 'after-save-hook 'ag/reveal-and-move-back)) (defun ag/org-reveal-after-save-off () (remove-hook 'after-save-hook 'ag/reveal-and-move-back)) (add-hook 'org-babel-pre-tangle-hook 'ag/org-reveal-after-save-on) (add-hook 'org-babel-post-tangle-hook 'ag/org-reveal-after-save-off) ) #+end_src
** use org-id in links :PROPERTIES: :CUSTOM_ID: h:AC175A47-E576-4AA6-A9C7-709129F4C56F :END: Taken from https://writequit.org/articles/emacs-org-mode-generate-ids.html
Problem: when exporting org files to HTML, the header anchors are volatile. Once I publish a new HTML version of this file, the previous version's links are no longer valid.
This function adds ~CUSTOM_ID~ property to all headings in a file (one-time). We can then use this to link to that heading forever.
Adding it as a ~after-save-hook~ automatically adds a ~CUSTOM_ID~ to newly created headers.
#+begin_src emacs-lisp (use-package org :init (defun lc/org-custom-id-get (&optional pom create prefix) "Get the CUSTOM_ID property of the entry at point-or-marker POM. If POM is nil, refer to the entry at point. If the entry does not have an CUSTOM_ID, the function returns nil. However, when CREATE is non nil, create a CUSTOM_ID if none is present already. PREFIX will be passed through to `org-id-new'. In any case, the CUSTOM_ID of the entry is returned." (interactive) (org-with-point-at pom (let ((id (org-entry-get nil "CUSTOM_ID"))) (cond ((and id (stringp id) (string-match "\S-" id)) id) (create (setq id (org-id-new (concat prefix "h"))) (org-entry-put pom "CUSTOM_ID" id) (org-id-add-location id (buffer-file-name (buffer-base-buffer))) id)))))
(defun lc/org-add-ids-to-headlines-in-file ()
"Add CUSTOM_ID properties to all headlines in the current
file which do not already have one. Only adds ids if the
auto-id' option is set to
t' in the file somewhere. ie,
,#+OPTIONS: auto-id:t"
(interactive)
(save-excursion
(widen)
(goto-char (point-min))
(when (re-search-forward "^#\+OPTIONS:.*auto-id:t" 10000 t)
(org-map-entries (lambda () (lc/org-custom-id-get (point) 'create))))))
:config
(require 'org-id)
(setq org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id)
)
#+end_src
** org-jupyter-mode :prog_jupyter: :PROPERTIES: :CUSTOM_ID: h:DE534B1B-9DF0-4966-A21C-B65B76B6A64E :header-args: :emacs-lisp :tangle ./lisp/init-prog-jupyter.el :END: #+begin_src emacs-lisp (use-package emacs :hook ((org-jupyter-mode . (lambda () (visual-line-mode -1) (advice-add 'org-cycle :around #'lc/org-cycle-or-py-complete))) (org-mode . (lambda () (when (lc/is-jupyter-org-buffer?) (org-jupyter-mode))))) :init (defun lc/is-jupyter-org-buffer? () (with-current-buffer (buffer-name) (goto-char (point-min)) (re-search-forward "begin_src jupyter-" 10000 t))) (defun lc/org-cycle-or-py-complete (orig-fun &rest args) "If in a jupyter-python code block, call py-indent-or-complete, otherwise use org-cycle" (if (and (org-in-src-block-p) (eq (intern (org-element-property :language (org-element-at-point))) 'jupyter-python)) (lc/py-indent-or-complete) (apply orig-fun args))) (define-minor-mode org-jupyter-mode "Minor mode which is active when an org file has the string begin_src jupyter-python in the first few hundred rows" ;; :keymap (let ((map (make-sparse-keymap))) ;; (define-key map (kbd "C-c f") 'insert-foo) ;; map) ) ) #+end_src
** org-roam :org_roam: :PROPERTIES: :CUSTOM_ID: h:175B1F5E-17E0-4D19-86CE-9577FBC6609B :header-args: :emacs-lisp :tangle ./lisp/init-org-roam.el :END: To set up roam:
- =ln -s ~/OneDrive/.../worknotes ~/roam/work=
- =ln -s /Users/cambiaghiluca/Library/Mobile\ Documents/iCloud~com~appsonthemove~beorg/Documents/org/roam ~/roam/personal=
:PROPERTIES: :CUSTOM_ID: h:7a406451-6ae8-4d26-a80b-3b7d9e29c023 :END: #+begin_src emacs-lisp (use-package org-roam :after org :init (setq org-roam-directory (file-truename "~/roam")) (setq org-roam-v2-ack t) (setq org-roam-capture-templates '(("d" "default" plain "%?" :target (file+head "personal/%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t) ("w" "work" plain "%?" :target (file+head "work/%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t))) :general (lc/leader-keys "TAB n" '((lambda () (interactive) (persp-switch "notes")) :wk "notes") "n n" '((lambda () (interactive) (persp-switch "notes") (org-roam-node-find)) :wk "notes workspace") "n b" 'org-roam-buffer-toggle "n f" 'org-roam-node-find "n g" 'org-roam-graph "n i" 'org-roam-node-insert "n c" 'org-roam-capture "n t" 'org-roam-tag-add "n r" 'org-roam-ref-add "n a" 'org-roam-alias-add ;; Dailies "n j" 'org-roam-dailies-capture-today "n J" 'org-roam-dailies-goto-today ;; todos "o t" '((lambda () (interactive) (persp-switch "notes") (find-file (concat org-roam-directory "/work/todo.org"))) :wk "work todos") "o n" '((lambda () (interactive) (persp-switch "notes") (org-roam-node-find)) :wk "notes") ) :config (org-roam-setup) ;; If using org-roam-protocol ;; (require 'org-roam-protocol) (add-to-list 'display-buffer-alist '(("org-roam" (display-buffer-in-direction) (direction . right) (window-width . 0.33) (window-height . fit-window-to-buffer))))
) #+end_src
- UI :PROPERTIES: :CUSTOM_ID: h:239ABF35-3C15-416B-8C10-353F711E5541 :header-args: :emacs-lisp :tangle ./lisp/init-core.el :END: ** all the icons :PROPERTIES: :CUSTOM_ID: h:502F0F06-A555-40FF-8ADA-0A7AA9E67D7E :END: #+BEGIN_SRC emacs-lisp (use-package all-the-icons :if (not lc/is-ipad) :demand ) #+END_SRC
** all the icons completion :PROPERTIES: :CUSTOM_ID: h:46FD92F6-91D6-47B8-887F-98375B978F7C :END: #+begin_src emacs-lisp (use-package all-the-icons-completion :after (marginalia all-the-icons) :hook (marginalia-mode . all-the-icons-completion-marginalia-setup) :init (all-the-icons-completion-mode)) #+end_src
** doom modeline :PROPERTIES: :CUSTOM_ID: h:77D92E3F-D17F-408C-A168-928D64D1AEF8 :END: #+BEGIN_SRC emacs-lisp (use-package doom-modeline :demand :init (setq doom-modeline-buffer-encoding nil) (setq doom-modeline-env-enable-python nil) (setq doom-modeline-project-detection 'projectile) (setq doom-modeline-buffer-file-name-style 'relative-to-project) :config (doom-modeline-mode 1) ;; (set-face-attribute 'doom-modeline-evil-insert-state nil :foreground "orange") (setq doom-modeline-height 20) ) #+END_SRC
** Modus themes + alternate light/dark themes :modus_themes: :PROPERTIES: :CUSTOM_ID: h:5F1EC880-5646-4E50-A460-C2F23BD864FC :END: I use a particular emacs build which has additional feature for macOS: https://github.com/railwaycat/homebrew-emacsmacport This defines a hook that is run when macOS system theme changes from light to dark. We use this hook to switch from light to dark theme.
#+BEGIN_SRC emacs-lisp (use-package emacs ;; :straight (modus-themes :type git :host gitlab :repo "protesilaos/modus-themes" :branch "main") ;; :demand :if (display-graphic-p) :hook (modus-themes-after-load-theme . lc/fix-fill-column-indicator) :general (lc/leader-keys "t t" '((lambda () (interactive) (modus-themes-toggle)) :wk "toggle theme")) :init (setq modus-themes-italic-constructs t ;; modus-themes-no-mixed-fonts t modus-themes-bold-constructs t modus-themes-fringes 'nil ; {nil,'subtle,'intense} modus-themes-mode-line '(3d) ; {nil,'3d,'moody} modus-themes-prompts nil ; {nil,'subtle,'intense} ;; modus-themes-completions 'moderate ; {nil,'moderate,'opinionated} ;; modus-themes-diffs nil ; {nil,'desaturated,'fg-only} modus-themes-org-blocks 'greyscale ; {nil,'greyscale,'rainbow} ;; modus-themes-headings ; Read further below in the manual for this one ;; (quote ((1 . t) ; keep the default style ;; (2 . (background overline)) ;; (t . (rainbow)))) modus-themes-variable-pitch-headings t modus-themes-scale-headings t modus-themes-scale-1 1.1 modus-themes-scale-2 1.15 modus-themes-scale-3 1.21 modus-themes-scale-4 1.27 modus-themes-scale-5 1.33) (defun lc/override-colors () (setq modus-themes-operandi-color-overrides '((bg-main . "#fefcf4") (bg-dim . "#faf6ef") (bg-alt . "#f7efe5") (bg-hl-line . "#f4f0e3") (bg-active . "#e8dfd1") (bg-inactive . "#f6ece5") (bg-region . "#c6bab1") (bg-header . "#ede3e0") (bg-tab-bar . "#dcd3d3") (bg-tab-active . "#fdf6eb") (bg-tab-inactive . "#c8bab8") (fg-unfocused ."#55556f"))) (setq modus-themes-vivendi-color-overrides '((bg-main . "#100b17") (bg-dim . "#161129") (bg-alt . "#181732") (bg-hl-line . "#191628") (bg-active . "#282e46") (bg-inactive . "#1a1e39") (bg-region . "#393a53") (bg-header . "#202037") (bg-tab-bar . "#262b41") (bg-tab-active . "#120f18") (bg-tab-inactive . "#3a3a5a") (fg-unfocused . "#9a9aab"))) ) (defun lc/load-dark-theme () (setq lc/theme 'dark) ;; (with-eval-after-load 'org (plist-put org-format-latex-options :foreground "whitesmoke")) (with-eval-after-load 'org (plist-put org-format-latex-options :background "Transparent")) (with-eval-after-load 'org-html-themify (setq org-html-themify-themes '((light . modus-vivendi) (dark . modus-vivendi)))) (load-theme 'modus-vivendi t) (when (bound-and-true-p centaur-tabs-mode) (lc/update-centaur-tabs)) ) (defun lc/load-light-theme () (setq lc/theme 'light) ;; (with-eval-after-load 'org (plist-put org-format-latex-options :foreground "dark")) (with-eval-after-load 'org (plist-put org-format-latex-options :background "Transparent")) (with-eval-after-load 'org-html-themify (setq org-html-themify-themes '((light . modus-operandi) (dark . modus-operandi)))) (setenv "BAT_THEME" "ansi") (load-theme 'modus-operandi t) (when (bound-and-true-p centaur-tabs-mode) (lc/update-centaur-tabs))) (defun lc/update-centaur-tabs () (centaur-tabs-display-update) (centaur-tabs-headline-match) (set-face-attribute 'centaur-tabs-selected nil :overline (face-background 'centaur-tabs-active-bar-face))) (defun lc/change-theme-with-mac-system () (let ((appearance (plist-get (mac-application-state) :appearance))) (cond ((equal appearance "NSAppearanceNameAqua") (lc/load-light-theme)) ((equal appearance "NSAppearanceNameDarkAqua") (lc/load-dark-theme))))) (defun lc/change-theme-with-timers () (run-at-time "00:00" (* 60 60 24) 'lc/load-dark-theme) (run-at-time "08:00" (* 60 60 24) 'lc/load-light-theme) (run-at-time "20:00" (* 60 60 24) 'lc/load-dark-theme)) (defun lc/fix-fill-column-indicator () (when (display-graphic-p) (modus-themes-with-colors (custom-set-faces `(fill-column-indicator ((,class :background ,bg-inactive :foreground ,bg-inactive))))))) (when (display-graphic-p) (lc/override-colors)) (if (and (boundp 'mac-effective-appearance-change-hook) (plist-get (mac-application-state) :appearance)) (progn (add-hook 'after-init-hook 'lc/change-theme-with-mac-system) (add-hook 'mac-effective-appearance-change-hook 'lc/change-theme-with-mac-system)) (add-hook 'emacs-startup-hook 'lc/change-theme-with-timers) ) ) #+END_SRC
** COMMENT centaur tabs :PROPERTIES: :CUSTOM_ID: h:44BB321D-0EB1-4E28-AD98-55621DC07597 :END: #+begin_src emacs-lisp (use-package centaur-tabs :hook (emacs-startup . centaur-tabs-mode) :general (general-nmap "gt" 'centaur-tabs-forward "gT" 'centaur-tabs-backward) (lc/leader-keys "b K" '(centaur-tabs-kill-other-buffers-in-current-group :wk "kill other buffers")) :init (setq centaur-tabs-set-icons t) (setq centaur-tabs-set-modified-marker t centaur-tabs-modified-marker "M" centaur-tabs-cycle-scope 'tabs) (setq centaur-tabs-set-close-button nil) (setq centaur-tabs-enable-ido-completion nil) :config (centaur-tabs-mode t) ;; (centaur-tabs-headline-match) (centaur-tabs-group-by-projectile-project) ) #+end_src
** COMMENT bespoke modeline :PROPERTIES: :CUSTOM_ID: h:4857520F-F4E7-4959-9162-505E93C94F21 :END: #+begin_src emacs-lisp (use-package bespoke-modeline :straight (:type git :host github :repo "mclear-tools/bespoke-modeline") :demand :init ;; Set header line (setq bespoke-modeline-position 'top) ;; Set mode-line height (setq bespoke-modeline-size 3) ;; Show diff lines in mode-line (setq bespoke-modeline-git-diff-mode-line nil) ;; Set mode-line cleaner (setq bespoke-modeline-cleaner t) ;; Use mode-line visual bell (setq bespoke-modeline-visual-bell t) ;; Set vc symbol ;; (setq bespoke-modeline-vc-symbol "G:") :config (bespoke-modeline-mode) ;; (set-face-attribute 'bespoke-modeline-inactive-status-RO nil :box 'unspecified) ;; (set-face-attribute 'bespoke-modeline-inactive-status-** nil :box 'unspecified) ;; (set-face-attribute 'bespoke-modeline-inactive-status-RW nil :box 'unspecified) ;; (set-face-attribute 'bespoke-modeline-inactive-secondary nil :bacground '#3c4353) ;; (set-face-attribute 'bespoke-modeline-inactive-secondary nil :bacground '#3c4353) )
#+end_src
** COMMENT bespoke theme :PROPERTIES: :CUSTOM_ID: h:EAC1CA44-DBF8-4BC9-A3FF-C55F06B60C07 :END: NOTE:
- requires Symbola font: https://fontlibrary.org/en/font/symbola #+begin_src emacs-lisp (use-package bespoke-themes :demand :straight (:host github :repo "mclear-tools/bespoke-themes" :branch "main") :init (defun what-face (pos) (interactive "d") (let ((face (or (get-char-property (point) 'read-face-name) (get-char-property (point) 'face)))) (if face (message "Face: %s" face) (message "No face at %d" pos)))) :config ;; Set evil cursor colors (setq bespoke-set-evil-cursors t) ;; Set use of italics (setq bespoke-set-italic-comments t bespoke-set-italic-keywords t) ;; Set variable pitch (setq bespoke-set-variable-pitch t) ;; Set initial theme variant (setq bespoke-set-theme 'dark) ;; Load theme (load-theme 'bespoke t) )
;; Vertical window divider (use-package frame :straight (:type built-in) ;; Make sure new frames use window-divider :hook (before-make-frame . window-divider-mode) :custom (window-divider-default-right-width 12) (window-divider-default-bottom-width 1) (window-divider-default-places 'right-only) (window-divider-mode t) :config (setq-default default-frame-alist (append (list ;; '(font . "SF Mono:style=medium:size=15") ;; NOTE: substitute whatever font you prefer here '(internal-border-width . 20) ;; '(left-fringe . 0) '(right-fringe . 0) '(tool-bar-lines . 0) '(menu-bar-lines . 0) '(vertical-scroll-bars . nil)))) (setq-default window-resize-pixelwise t) (setq-default frame-resize-pixelwise t) )
(use-package fontset :straight (:type built-in) ;; only include this if you use straight :config ;; Use symbola for proper unicode (when (member "Symbola" (font-family-list)) (set-fontset-font t 'symbol "Symbola" nil 'prepend))) #+end_src
** COMMENT rainbow-mode :PROPERTIES: :CUSTOM_ID: h:CBF37512-DDB2-4FC5-88C7-F997A67064D5 :END: #+begin_src emacs-lisp (use-package rainbow-mode :config (rainbow-mode) ) #+end_src
** COMMENT stimmung themes :PROPERTIES: :CUSTOM_ID: h:8346727C-A954-4C8B-B002-BCB942B0980C :END: #+begin_src emacs-lisp (use-package stimmung-themes :straight (stimmung-themes :host github :repo "motform/stimmung-themes") ; if you are a straight shooter :demand :config (load-theme 'stimmung-themes-light t) ;; (load-theme 'stimmung-themes-dark t) ) #+end_src
** COMMENT simple modeline :PROPERTIES: :CUSTOM_ID: h:72CD809A-97CD-4CA7-918C-DC5946C66ED3 :END: #+begin_src emacs-lisp (use-package emacs :init (defun simple-mode-line-render (left right) "Return a string of `window-width' length. Containing LEFT, and RIGHT aligned respectively." (let ((available-width (- (window-total-width) (+ (length (format-mode-line left)) (length (format-mode-line right)))))) (append left (list (format (format "%%%ds" available-width) "")) right))) ;; Display to mode-line buffer name relative to current-project. ;; SOURCE: https://www.reddit.com/r/emacs/comments/8xobt3/tip_in_modeline_show_buffer_file_path_relative_to/ (with-eval-after-load 'subr-x (setq-default mode-line-buffer-identification '(:eval (format-mode-line (propertized-buffer-identification (or (when-let* ((buffer-file-truename buffer-file-truename) (prj (cdr-safe (project-current))) (prj-parent (file-name-directory (directory-file-name (expand-file-name prj))))) (concat (file-relative-name (file-name-directory buffer-file-truename) prj-parent) (file-name-nondirectory buffer-file-truename))) "%b"))))))
(setq-default column-number-mode t mode-line-format '((:eval (simple-mode-line-render '("%e" ; left side mode-line-front-space mode-line-modified mode-line-remote mode-line-frame-identification mode-line-buffer-identification " " "%l:%c") '("%" mode-line-misc-info ; right side " " mode-line-process mode-line-end-spaces " "))))) ) #+end_src
** dashboard :dashboard:
:PROPERTIES:
:CUSTOM_ID: h:2F4C0A6C-96BE-4818-B794-D1593C23FB00
:END:
#+BEGIN_SRC emacs-lisp
(use-package dashboard
:demand
:init
(setq initial-buffer-choice (lambda () (get-buffer "dashboard")))
(setq dashboard-center-content t)
(setq dashboard-projects-backend 'projectile)
(setq dashboard-set-heading-icons t)
(setq dashboard-set-file-icons t)
(defun lc/is-after-17-or-weekends? ()
(or (thread-first (nth 3 (split-string (current-time-string) " ")) ;; time of the day e.g. 18
;; (substring 0 2)
(string-to-number) ;;<
(> 16))
(thread-first (substring (current-time-string) 0 3) ;; day of the week e.g. Fri
(member '("Sat" "Sun")))))
(setq dashboard-banner-logo-title nil)
(setq dashboard-set-footer nil)
;; (setq dashboard-startup-banner [VALUE])
(setq dashboard-set-navigator t)
(setq dashboard-navigator-buttons
((;; Github (,(all-the-icons-octicon "mark-github" :height 1.1 :v-adjust 0.0) "Github" "Go to wondercast" (lambda (&rest _) (browse-url "https://github.com/Maersk-Global/wondercast"))) ;; Codebase (,(all-the-icons-faicon "briefcase" :height 1.1 :v-adjust -0.1) "JIRA" "Go to Kanban" (lambda (&rest _) (browse-url "https://jira.maerskdev.net/secure/RapidBoard.jspa?rapidView=6378&projectKey=AVOC&quickFilter=15697"))) ;; Perspectives (,(all-the-icons-octicon "history" :height 1.1 :v-adjust 0.0) "Restore" "Restore" (lambda (&rest _) (persp-state-load persp-state-default-file))) ))) (defun lc/dashboard-agenda-entry-format () "Format agenda entry to show it on dashboard. Compared to the original, we remove tags at the end" (let* ((scheduled-time (org-get-scheduled-time (point))) (deadline-time (org-get-deadline-time (point))) (entry-time (or scheduled-time deadline-time)) (item (org-agenda-format-item (dashboard-agenda--formatted-time) (dashboard-agenda--formatted-headline) (org-outline-level) (org-get-category) nil;; (org-get-tags) )) (loc (point)) (file (buffer-file-name)) (todo-state (org-get-todo-state)) (todo-index (and todo-state (length (member todo-state org-todo-keywords-1)))) (entry-data (list (cons 'time entry-time) (cons 'todo-index todo-index)))) (list item loc file entry-data))) (defun lc/dashboard-get-agenda () "Get agenda items for today or for a week from now." (org-compile-prefix-format 'agenda) (org-map-entries 'lc/dashboard-agenda-entry-format dashboard-match-agenda-entry 'agenda dashboard-filter-agenda-entry)) (defun lc/dashboard-get-next () "Get agenda items for today or for a week from now." (org-compile-prefix-format 'agenda) (org-map-entries 'lc/dashboard-agenda-entry-format dashboard-match-next-entry 'agenda)) (defun lc/dashboard-insert-next (list-size) "Add the list of LIST-SIZE items of next tasks" (require 'org-agenda) (let ((next (lc/dashboard-get-next))) (dashboard-insert-section "Next tasks" next list-size 'next "n"
(lambda (&rest ignore)
(let ((buffer (find-file-other-window (nth 2 ',el))))
(with-current-buffer buffer
(goto-char (nth 1 ',el))
(switch-to-buffer buffer))))
(format "%s" (nth 0 el)))))
:config
;; exclude work items after 17 and on weekends
(setq dashboard-match-next-entry "TODO="NEXT"-work")
(run-at-time "00:00" (* 60 60 24)
(lambda ()
(if (lc/is-after-17-or-weekends?)
(setq dashboard-match-agenda-entry "life|habits"
dashboard-match-next-entry "TODO="NEXT"-work")
(setq dashboard-match-agenda-entry "work|life|habits"
dashboard-match-next-entry "TODO="NEXT""
))))
(dashboard-setup-startup-hook)
(set-face-attribute 'dashboard-items-face nil :height (lc/get-font-size))
;; do not show tags in agenda view
(advice-add 'dashboard-get-agenda :override #'lc/dashboard-get-agenda)
;; show next tasks in dashboard
(add-to-list 'dashboard-item-generators '(next . lc/dashboard-insert-next))
(setq dashboard-items '((agenda . 5)
(next . 10)
(bookmarks . 5)
;; (recents . 5)
;; (projects . 5)
))
)
#+END_SRC
** popup management :PROPERTIES: :CUSTOM_ID: h:91E3AC2B-6981-4915-8508-4CA5D7182939 :END: Taken from https://emacs.stackexchange.com/questions/46210/reuse-help-window #+begin_src emacs-lisp (use-package emacs :init (setq display-buffer-alist `((,(rx bos (or "Apropos" "Help" "helpful" "info" "Summary") (0+ not-newline)) (display-buffer-reuse-mode-window display-buffer-below-selected) (window-height . 0.33) (mode apropos-mode help-mode helpful-mode Info-mode Man-mode)))) ) ;; reuse existing windows ;; (setq display-buffer-alist ;; '(("." ;; (display-buffer-reuse-window display-buffer-same-window) ;; (reusable-frames . t))))
;; (setq even-window-sizes nil) ; display-buffer hint: avoid resizing #+end_src
** centered cursor mode :ui_extra: :PROPERTIES: :CUSTOM_ID: h:26FC27A5-5E20-4440-BA86-48FAA8707D00 :header-args: :emacs-lisp :tangle ./lisp/init-ui-extra.el :END: #+begin_src emacs-lisp (use-package centered-cursor-mode :general (lc/leader-keys "t =" '((lambda () (interactive) (centered-cursor-mode 'toggle)) :wk "center cursor") ) ) #+end_src
** hide mode line :ui_extra: :PROPERTIES: :CUSTOM_ID: h:89BB7025-084D-4465-897D-C731EB02161A :header-args: :emacs-lisp :tangle ./lisp/init-ui-extra.el :END: #+begin_src emacs-lisp (use-package hide-mode-line :commands (hide-mode-line-mode)) #+end_src
** winum :ui_extra: :PROPERTIES: :CUSTOM_ID: h:991499E8-6FF8-41DB-B533-6D627602DFD4 :header-args: :emacs-lisp :tangle ./lisp/init-ui-extra.el :END: #+begin_src emacs-lisp (use-package winum :general (lc/leader-keys "1" '(winum-select-window-1 :wk "win 1") "2" '(winum-select-window-2 :wk "win 2") "3" '(winum-select-window-3 :wk "win 3") "4" '(winum-select-window-4 :wk "win 4") "5" '(winum-select-window-5 :wk "win 5") "6" '(winum-select-window-6 :wk "win 6") ) :config (winum-mode)) #+end_src
** transpose frame :ui_extra: :PROPERTIES: :CUSTOM_ID: h:9E3C0942-1D8C-403F-9D44-5BEDA2966C58 :header-args: :emacs-lisp :tangle ./lisp/init-ui-extra.el :END: #+begin_src emacs-lisp (use-package transpose-frame :general (lc/leader-keys "w t" '(transpose-frame :wk "transpose") "w f" '(rotate-frame :wk "flip"))) #+end_src
** Fill column indicator :PROPERTIES: :CUSTOM_ID: h:A7A49256-4E2B-45CD-A898-347C37867645 :END: With ~evil~ you can:
- ~gww~ to fill the line
- ~gqq~ to fill the line and move to the end of it
- ~gwp~ to fill paragraph
#+begin_src emacs-lisp (use-package display-fill-column-indicator :straight (:type built-in) :hook (python-mode . display-fill-column-indicator-mode) :init (setq-default fill-column 90) ;; (setq display-fill-column-indicator-character "|") ) #+end_src
** COMMENT Whitespace mode :PROPERTIES: :CUSTOM_ID: h:EE0D61ED-C9F2-47DE-9DEC-78C2F995B06A :END: #+begin_src emacs-lisp (use-package emacs :hook ((org-jupyter-mode . (lambda () (whitespace-mode -1))) (org-mode . whitespace-mode)) :init (setq-default whitespace-line-column 90 whitespace-style '(face lines-tail))) #+end_src
** Highlight indentation guides :PROPERTIES: :CUSTOM_ID: h:98E70637-DC1F-4528-B848-C12D5092BD7A :END: #+BEGIN_SRC emacs-lisp ;; add a visual intent guide (use-package highlight-indent-guides :hook (prog-mode . highlight-indent-guides-mode) :init ;; (setq highlight-indent-guides-method 'column) ;; (setq highlight-indent-guides-method 'bitmap) (setq highlight-indent-guides-method 'character) (setq highlight-indent-guides-character ?‖) (setq highlight-indent-guides-responsive 'top) ;; (setq highlight-indent-guides-responsive 'stack) ;; (setq highlight-indent-guides-auto-enabled nil) ;; (set-face-background 'highlight-indent-guides-odd-face "darkgray") ;; (set-face-background 'highlight-indent-guides-even-face "dimgray") ;; (set-face-foreground 'highlight-indent-guides-character-face "dimgray") ) #+END_SRC
** Enlarge window :PROPERTIES: :CUSTOM_ID: h:2D8DEB14-A1F1-4B46-B08A-CF97A0A9B237 :END: Taken from DOOM
#+begin_src emacs-lisp (use-package emacs :general (lc/leader-keys "w o" '(doom/window-enlargen :wk "enlargen")) :init (defun doom/window-enlargen (&optional arg) "Enlargen the current window to focus on this one. Does not close other windows (unlike `doom/window-maximize-buffer'). Activate again to undo." (interactive "P") (let ((param 'doom--enlargen-last-wconf)) (cl-destructuring-bind (window . wconf) (or (frame-parameter nil param) (cons nil nil)) (set-frame-parameter nil param (if (and (equal window (selected-window)) (not arg) wconf) (ignore (let ((source-window (selected-window))) (set-window-configuration wconf) (when (window-live-p source-window) (select-window source-window)))) (prog1 (cons (selected-window) (or wconf (current-window-configuration))) (let* ((window (selected-window)) (dedicated-p (window-dedicated-p window)) (preserved-p (window-parameter window 'window-preserved-size)) (ignore-window-parameters t) (window-resize-pixelwise nil) (frame-resize-pixelwise nil)) (unwind-protect (progn (when dedicated-p (set-window-dedicated-p window nil)) (when preserved-p (set-window-parameter window 'window-preserved-size nil)) (maximize-window window)) (set-window-dedicated-p window dedicated-p) (when preserved-p (set-window-parameter window 'window-preserved-size preserved-p)) (add-hook 'doom-switch-window-hook #'doom--enlargened-forget-last-wconf-h))))))))) )
#+end_src
** 8 colors theme :PROPERTIES: :CUSTOM_ID: h:EA99CF6B-278E-482F-A865-7E31407734CE :END: When using ~emacs~ on my jailbroken iPad, I cannot set ~TERM=xterm-256color~ because of some ~terminfo~ error. I therefore do what I can with the 8 colors I can use.
The default theme ~manoj-dark~ does a pretty good job OOTB. I add a few manual tweaks. The theme defintion gets saved in ~custom-theme-directory~.
#+begin_src emacs-lisp :tangle themes/8colors-theme.el (deftheme 8colors "Theme using only 8 colors")
;; (custom-theme-set-variables ;; '8colors ;; '(overline-margin 0) ;; )
(custom-theme-set-faces '8colors '(centaur-tabs-unselected ((t (:foreground "white" :background "black"))) t) '(centaur-tabs-unselected-modified ((t (:foreground "white" :background "black"))) t) '(tool-bar ((t (:background "black"))) t) '(selectrum-current-candidate ((t (:background "blue"))) t) '(org-code ((t (:foreground "magenta"))) t) '(org-special-keyword ((t (:foreground "magenta"))) t) '(mode-line ((t (:background "black"))) t) '(doom-modeline-buffer-file ((t (:background "black"))) t) '(tab-line ((t (:background "black"))) t) '(magit-diff-removed-highlight ((t (:background "red" :foreground "white"))) t) '(magit-diff-added-highlight ((t (:background "green" :foreground "white"))) t) '(magit-hash ((t (:background "black" :foreground "white"))) t) '(iedit-occurrence ((t (:background "blue" :foreground "white"))) t) )
(provide-theme '8colors) #+end_src
#+begin_src emacs-lisp (use-package emacs :init (unless (> (display-color-cells) 8) (setq custom-theme-directory (concat user-emacs-directory "themes")) (custom-set-variables '(custom-enabled-themes '(8colors manoj-dark))) )) #+end_src
** COMMENT Fancy titlebar for macOS :PROPERTIES: :CUSTOM_ID: h:73688165-BE4C-411D-904C-2DD65E56766E :END: #+BEGIN_SRC emacs-lisp (use-package emacs :init (add-to-list 'default-frame-alist '(ns-transparent-titlebar . t)) (add-to-list 'default-frame-alist '(ns-appearance . dark)) (setq ns-use-proxy-icon nil) (setq frame-title-format nil) ) #+END_SRC
** COMMENT Show emoji on macOS :PROPERTIES: :CUSTOM_ID: h:CDFFE28E-AD1A-4C9D-9B70-EF7D1E22CE56 :END: You can use ~insert-char~ to insert the emoji or ~emojify-insert-emoji~
#+begin_src emacs-lisp (use-package emojify :commands (emojify-insert-emoji) :hook (after-init . global-emojify-mode) :config (when (member "Apple Emoji" (font-family-list)) (set-fontset-font t 'symbol (font-spec :family "Apple Emoji") nil 'prepend)) )
#+end_src
** COMMENT Alerts :PROPERTIES: :CUSTOM_ID: h:17A9115B-AB79-4445-9F12-EFD086750CDA :END: #+begin_src emacs-lisp (use-package alert :if (lc/is-macos) :config (setq ;; alert-default-style 'notifier alert-default-style 'osx-notifier ) ;; (alert "This is an alert" :severity 'high) ;; (alert "This is an alert" :title "My Alert" :category 'debug) ) #+end_src
** Transparent frame :PROPERTIES: :CUSTOM_ID: h:E54A78C6-FD42-40C8-BB33-E076D0D1EB94 :END: #+begin_src emacs-lisp (use-package emacs :init (set-frame-parameter (selected-frame) 'alpha '(93 . 93)) (add-to-list 'default-frame-alist '(alpha . (93 . 93))) ) #+end_src
- Completion framework :PROPERTIES: :CUSTOM_ID: h:06E0EA9F-7CF4-4B99-8A4A-2C63A4F8A6B6 :header-args: :emacs-lisp :tangle ./lisp/init-core.el :END: ** marginalia :PROPERTIES: :CUSTOM_ID: h:37ACBBF7-989F-4A57-9454-06B79B8EB4F0 :END: #+BEGIN_SRC emacs-lisp (use-package marginalia :after vertico :init (setq marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil)) (marginalia-mode) (with-eval-after-load 'projectile (add-to-list 'marginalia-command-categories '(projectile-find-file . file))) ) #+END_SRC
** embark :PROPERTIES: :CUSTOM_ID: h:D28488FC-484F-4AD9-8989-736BE88C9AA2 :END: NOTE:
- You can act on candidates with =C-l=
- You can run ~embark-export~ on all results (e.g. after a ~consult-line~) with =C-l E=
- You can run ~embark-export-snapshot~ with =C-l S=
#+BEGIN_SRC emacs-lisp (use-package embark :after vertico :general (general-nmap "C-l" 'embark-act) (vertico-map "C-l" #'embark-act ) (:keymaps 'embark-file-map ;; "o" 'find-file-other-window "x" 'lc/dired-open-externally ) :init ;; Optionally replace the key help with a completing-read interface (setq prefix-help-command #'embark-prefix-help-command) :config ;; Hide the mode line of the Embark live/completions buffers (add-to-list 'display-buffer-alist '("\`\Embark Collect \(Live\|Completions\)\" nil (window-parameters (mode-line-format . none)))) ;; (add-hook 'embark-setup-hook 'selectrum-set-selected-candidate) ) #+END_SRC
** wgrep :PROPERTIES: :CUSTOM_ID: h:61053422-6027-47A9-8175-8F8479F78E5F :END: After running ~embark-export~, we can edit the results with ~wgrep~ and commit the edits. This is extremely powerful for refactorings such as changing the name of a class or a function across files in the project.
#+begin_src emacs-lisp (use-package wgrep :general (grep-mode-map "W" 'wgrep-change-to-wgrep-mode) :init (setq wgrep-auto-save-buffer t) (setq wgrep-change-readonly-file t) ) #+end_src
** consult :PROPERTIES: :CUSTOM_ID: h:E08EB7E2-CBD9-460C-B77E-9EFF7846C249 :END: NOTE:
- After =consult-line= you can press =M-n= twice to search for the symbol at point
#+BEGIN_SRC emacs-lisp (use-package consult :commands (consult-ripgrep) :general (general-nmap :states '(normal insert) "C-p" 'consult-yank-pop) (lc/leader-keys "r r" '(consult-bookmark :wk "go to bookmark") "s i" '(consult-isearch :wk "isearch") "s o" '(consult-outline :which-key "outline") "s s" 'consult-line "s p" '(consult-ripgrep :wk "ripgrep project") "b b" 'consult-buffer ;; TODO consult mark "f r" 'consult-recent-file ;; "s !" '(consult-flymake :wk "flymake") ) :init (setq xref-show-xrefs-function #'consult-xref xref-show-definitions-function #'consult-xref) ;; (setq consult-preview-key "C-l") ;; (setq consult-narrow-key ">") :config (autoload 'projectile-project-root "projectile") (setq consult-project-root-function #'projectile-project-root) (with-eval-after-load 'selectrum (require 'consult-selectrum)) ) #+END_SRC
** embark-consult :PROPERTIES: :CUSTOM_ID: h:002E04ED-FEBA-4058-8570-561963C2450F :END: #+begin_src emacs-lisp (use-package embark-consult :after (embark consult) ;; :demand t ; only necessary if you have the hook below ;; if you want to have consult previews as you move around an ;; auto-updating embark collect buffer ;; :hook ;; (embark-collect-mode . embark-consult-preview-minor-mode) ) #+end_src
** vertico :PROPERTIES: :CUSTOM_ID: h:CAEABB84-0DAE-41CB-B08B-A77B956B991E :END: NOTE:
- ~vertico-indexed~ lets you choose candidates according to their index, e.g. =C-3 RET= will select third candidate.
#+begin_src emacs-lisp
(use-package vertico
;; :straight (vertico :type git :host github :repo "minad/vertico")
:straight (vertico :files (:defaults "extensions/*")
:includes (vertico-indexed
vertico-flat
vertico-grid
vertico-mouse
;; vertico-quick
vertico-buffer
vertico-repeat
vertico-reverse
vertico-directory
vertico-multiform
vertico-unobtrusive
))
:demand
:hook
((minibuffer-setup . vertico-repeat-save) ; Make sure vertico state is saved for `vertico-repeat'
(rfn-eshadow-update-overlay . vertico-directory-tidy) ; Clean up file path when typing
)
:general
(:keymaps 'vertico-map
"C-j" #'vertico-next
"C-k" #'vertico-previous
"
;; multiform extension (setq vertico-grid-separator " ") (setq vertico-grid-lookahead 50) (setq vertico-buffer-display-action '(display-buffer-reuse-window)) (setq vertico-multiform-categories '((file indexed) (consult-grep buffer) (consult-location) (imenu buffer) (library reverse indexed) (org-roam-node reverse indexed) (t reverse) )) (setq vertico-multiform-commands '(("flyspell-correct-*" grid reverse) (org-refile grid reverse indexed) (consult-yank-pop indexed) (consult-flycheck) (consult-lsp-diagnostics) )) (defun kb/vertico-multiform-flat-toggle () "Toggle between flat and reverse." (interactive) (vertico-multiform--display-toggle 'vertico-flat-mode) (if vertico-flat-mode (vertico-multiform--temporary-mode 'vertico-reverse-mode -1) (vertico-multiform--temporary-mode 'vertico-reverse-mode 1)))
;; Workaround for problem with tramp' hostname completions. This overrides ;; the completion style specifically for remote files! See ;; https://github.com/minad/vertico#tramp-hostname-completion (defun lc/basic-remote-try-completion (string table pred point) (and (vertico--remote-p string) (completion-basic-try-completion string table pred point))) (defun lc/basic-remote-all-completions (string table pred point) (and (vertico--remote-p string) (completion-basic-all-completions string table pred point))) (add-to-list 'completion-styles-alist '(basic-remote ; Name of
completion-style'
lc/basic-remote-try-completion lc/basic-remote-all-completions nil))
(setq completion-in-region-function (lambda (&rest args) (apply (if vertico-mode #'consult-completion-in-region #'completion--in-region) args)))
:config ;; (vertico-multiform-mode) (vertico-mode) ;; (vertico-indexed-mode)
;; Prefix the current candidate with “» ”. From ;; https://github.com/minad/vertico/wiki#prefix-current-candidate-with-arrow (advice-add #'vertico--format-candidate :around (lambda (orig cand prefix suffix index _start) (setq cand (funcall orig cand prefix suffix index _start)) (concat (if (= vertico--index index) (propertize "» " 'face 'vertico-current) " ") cand)))
)
(use-package orderless :init ;; Configure a custom style dispatcher (see the Consult wiki) ;; (setq orderless-style-dispatchers '(+orderless-dispatch) ;; orderless-component-separator #'orderless-escapable-split-on-space) (setq completion-styles '(orderless) completion-category-defaults nil completion-category-overrides '((file (styles partial-completion)))))
(use-package savehist :init (savehist-mode))
;; A few more useful configurations...
(use-package emacs
:init
;; Add prompt indicator to completing-read-multiple'. ;; Alternatively try
consult-completing-read-multiple'.
(defun crm-indicator (args)
(cons (concat "[CRM] " (car args)) (cdr args)))
(advice-add #'completing-read-multiple :filter-args #'crm-indicator)
;; Do not allow the cursor in the minibuffer prompt (setq minibuffer-prompt-properties '(read-only t cursor-intangible t face minibuffer-prompt)) (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
;; Emacs 28: Hide commands in M-x which do not work in the current mode. ;; Vertico commands are hidden in normal buffers. ;; (setq read-extended-command-predicate ;; #'command-completion-default-include-p)
;; Enable recursive minibuffers (setq enable-recursive-minibuffers t)) #+end_src
** COMMENT consult-selectrum :PROPERTIES: :CUSTOM_ID: h:37452726-47A2-44E3-818C-01835F9DCBCD :END: #+BEGIN_SRC emacs-lisp (use-package consult-selectrum :straight (consult-selectrum :host github :repo "minad/consult" :branch "main") :after consult :demand) #+END_SRC
** COMMENT selectrum :PROPERTIES: :CUSTOM_ID: h:7AC334FB-E159-43C3-B4BD-9D8FDC07900C :END: #+BEGIN_SRC emacs-lisp (use-package selectrum :demand :general (selectrum-minibuffer-map "C-j" 'selectrum-next-candidate "C-k" 'selectrum-previous-candidate) :config (selectrum-mode t) ) #+END_SRC
** COMMENT prescient :PROPERTIES: :CUSTOM_ID: h:A05881AE-31E0-498C-B107-0FBD5E1103BF :END: #+BEGIN_SRC emacs-lisp (use-package selectrum-prescient :after selectrum :demand :config (prescient-persist-mode t) (selectrum-prescient-mode t) ) #+END_SRC
** COMMENT fancy dabbrev :PROPERTIES: :CUSTOM_ID: h:f59f64dc-f38f-474c-95eb-d404c5f598b7 :END: #+begin_src emacs-lisp (use-package fancy-dabbrev :demand :commands (fancy-dabbrev-mode) :config (setq fancy-dabbrev-preview-delay 0.1) (setq fancy-dabbrev-preview-context 'before-non-word)
(setq fancy-dabbrev-expansion-on-preview-only t) (setq fancy-dabbrev-indent-command 'tab-to-tab-stop)
(define-key evil-insert-state-map (kbd "
;; Only while in insert mode. (with-eval-after-load 'evil (add-hook 'evil-insert-state-entry-hook (lambda () (fancy-dabbrev-mode 1))) (add-hook 'evil-insert-state-exit-hook (lambda () (fancy-dabbrev-mode 0)))) )
#+end_src
** COMMENT company :PROPERTIES: :CUSTOM_ID: h:DF88C7D3-3774-45BD-95DE-CD0BE0F7F043 :END: *** company-mode :PROPERTIES: :CUSTOM_ID: h:0A172DDA-7B18-46EF-87C6-33D12234AEEC :END: ~company-tng-mode~ (tab-n-go):
- Select candidates with =C-j= / =C-k= or =TAB= / =S-TAB=
- don't press =RET= to confirm
#+BEGIN_SRC emacs-lisp (use-package company ;; :demand :hook ((after-init . global-company-mode) ;; (python-mode . (lambda () (setq-local company-backends '((company-capf :with company-files))))) ) :general (company-mode-map :states 'insert "TAB" 'company-indent-or-complete-common ) :init (setq company-minimum-prefix-length 1) (setq company-idle-delay nil) (setq company-tooltip-align-annotations t) (setq company-tooltip-maximum-width 50 company-tooltip-minimum-width 50) (setq company-tooltip-limit 12) ;; don't autocomplete when single candidate (setq company-auto-complete nil) (setq company-auto-complete-chars nil) (setq company-dabbrev-code-other-buffers nil) (setq company-dabbrev-ignore-case nil) (setq company-dabbrev-downcase nil) ;; manually configure tng ;; (setq company-tng-auto-configure nil) ;; (setq company-frontends '(company-tng-frontend ;; company-pseudo-tooltip-frontend ;; company-echo-metadata-frontend)) (setq company-backends '((company-capf company-keywords company-files :with company-yasnippet))) ;; :custom-face ;; (company-tooltip ;; ((t (:family "Fira Code")))) :config (global-company-mode) (with-eval-after-load 'evil (add-hook 'company-mode-hook #'evil-normalize-keymaps)) ;; needed in case we only have one candidate (define-key company-active-map (kbd "C-j") 'company-select-next) ;; (define-key company-mode-map [remap indent-for-tab-command] #'company-indent-or-complete-common) ) #+END_SRC
*** company prescient :PROPERTIES: :CUSTOM_ID: h:DBC4211D-4E14-4A05-9925-2B1221CD7694 :END: #+BEGIN_SRC emacs-lisp (use-package company-prescient :after company :demand :config (company-prescient-mode t)) #+END_SRC
*** COMMENT company box :PROPERTIES: :CUSTOM_ID: h:179D6081-F535-4869-BBF1-E92D005C5EBE :END: Taken from DOOM #+begin_src emacs-lisp (use-package company-box :if (display-graphic-p) :hook (company-mode . company-box-mode) :config (with-no-warnings ;; Prettify icons (defun my-company-box-icons--elisp (candidate) (when (derived-mode-p 'emacs-lisp-mode) (let ((sym (intern candidate))) (cond ((fboundp sym) 'Function) ((featurep sym) 'Module) ((facep sym) 'Color) ((boundp sym) 'Variable) ((symbolp sym) 'Text) (t . nil))))) (advice-add #'company-box-icons--elisp :override #'my-company-box-icons--elisp))
(declare-function all-the-icons-faicon 'all-the-icons) (declare-function all-the-icons-material 'all-the-icons) (declare-function all-the-icons-octicon 'all-the-icons)
(setq company-box-icons-all-the-icons `((Unknown . ,(all-the-icons-material "find_in_page" :height 0.8 :v-adjust -0.15)) (Text . ,(all-the-icons-faicon "text-width" :height 0.8 :v-adjust -0.02)) (Method . ,(all-the-icons-faicon "cube" :height 0.8 :v-adjust -0.02 :face 'all-the-icons-purple)) (Function . ,(all-the-icons-faicon "cube" :height 0.8 :v-adjust -0.02 :face 'all-the-icons-purple)) (Constructor . ,(all-the-icons-faicon "cube" :height 0.8 :v-adjust -0.02 :face 'all-the-icons-purple)) (Field . ,(all-the-icons-octicon "tag" :height 0.85 :v-adjust 0 :face 'all-the-icons-lblue)) (Variable . ,(all-the-icons-octicon "tag" :height 0.85 :v-adjust 0 :face 'all-the-icons-lblue)) (Class . ,(all-the-icons-material "settings_input_component" :height 0.8 :v-adjust -0.15 :face 'all-the-icons-orange)) (Interface . ,(all-the-icons-material "share" :height 0.8 :v-adjust -0.15 :face 'all-the-icons-lblue)) (Module . ,(all-the-icons-material "view_module" :height 0.8 :v-adjust -0.15 :face 'all-the-icons-lblue)) (Property . ,(all-the-icons-faicon "wrench" :height 0.8 :v-adjust -0.02)) (Unit . ,(all-the-icons-material "settings_system_daydream" :height 0.8 :v-adjust -0.15)) (Value . ,(all-the-icons-material "format_align_right" :height 0.8 :v-adjust -0.15 :face 'all-the-icons-lblue)) (Enum . ,(all-the-icons-material "storage" :height 0.8 :v-adjust -0.15 :face 'all-the-icons-orange)) (Keyword . ,(all-the-icons-material "filter_center_focus" :height 0.8 :v-adjust -0.15)) (Snippet . ,(all-the-icons-material "format_align_center" :height 0.8 :v-adjust -0.15)) (Color . ,(all-the-icons-material "palette" :height 0.8 :v-adjust -0.15)) (File . ,(all-the-icons-faicon "file-o" :height 0.8 :v-adjust -0.02)) (Reference . ,(all-the-icons-material "collections_bookmark" :height 0.8 :v-adjust -0.15)) (Folder . ,(all-the-icons-faicon "folder-open" :height 0.8 :v-adjust -0.02)) (EnumMember . ,(all-the-icons-material "format_align_right" :height 0.8 :v-adjust -0.15)) (Constant . ,(all-the-icons-faicon "square-o" :height 0.8 :v-adjust -0.1)) (Struct . ,(all-the-icons-material "settings_input_component" :height 0.8 :v-adjust -0.15 :face 'all-the-icons-orange)) (Event . ,(all-the-icons-octicon "zap" :height 0.8 :v-adjust 0 :face 'all-the-icons-orange)) (Operator . ,(all-the-icons-material "control_point" :height 0.8 :v-adjust -0.15)) (TypeParameter . ,(all-the-icons-faicon "arrows" :height 0.8 :v-adjust -0.02)) (Template . ,(all-the-icons-material "format_align_left" :height 0.8 :v-adjust -0.15))) company-box-icons-alist 'company-box-icons-all-the-icons)
(setq company-box-show-single-candidate t company-box-backends-colors nil company-box-max-candidates 10) ;; Disable tab-bar in company-box child frames (add-to-list 'company-box-frame-parameters '(tab-bar-lines . 0)) ) #+end_src
*** COMMENT company posframe :PROPERTIES: :CUSTOM_ID: h:3A912EC4-EC8E-4410-8EE3-2F00311A614B :END: #+begin_src emacs-lisp (use-package company-posframe :hook (company-mode . company-posframe-mode) ) #+end_src
** corfu :PROPERTIES: :CUSTOM_ID: h:A2B7EF59-9D10-4C12-98D1-9F569EF9BE38 :END: #+begin_src emacs-lisp ;; Configure corfu (use-package corfu :straight (corfu :type git :host github :repo "minad/corfu") ;; :hook (after-init . corfu-global-mode) :hook ((prog-mode . corfu-mode) (org-mode . corfu-mode)) :bind (:map corfu-map ("C-j" . corfu-next) ("C-k" . corfu-previous)) :general (evil-insert-state-map "C-k" nil) :init (setq corfu-auto nil) ;; Enable auto completion (setq corfu-cycle t) ;; Enable cycling for `corfu-next/previous' (setq corfu-min-width 80) (setq corfu-max-width corfu-min-width) ; Always have the same width (setq corfu-preselect-first t)
(defun corfu-enable-always-in-minibuffer () "Enable Corfu in the minibuffer if Vertico/Mct are not active." (unless (or (bound-and-true-p mct--active) ; Useful if I ever use MCT (bound-and-true-p vertico--input)) (setq-local corfu-auto nil) ; Ensure auto completion is disabled (corfu-mode 1))) (add-hook 'minibuffer-setup-hook #'corfu-enable-always-in-minibuffer 1) ;; :custom ;; (corfu-commit-predicate nil) ;; Do not commit selected candidates on next input ;; (corfu-quit-at-boundary t) ;; Automatically quit at word boundary ;; (corfu-quit-no-match t) ;; Automatically quit if there is no match ;; (corfu-preview-current nil) ;; Disable current candidate preview ;; (corfu-preselect-first nil) ;; Disable candidate preselection ;; (corfu-echo-documentation nil) ;; Disable documentation in the echo area ;; (corfu-scroll-margin 5) ;; Use scroll margin ) #+end_src
** COMMENT dabbrev :PROPERTIES: :CUSTOM_ID: h:240FC4A5-CDED-4456-9EBA-9EDF05CE62B9 :END: NOTE:
- When =TAB= does not work, use =S-TAB= as backup
#+begin_src emacs-lisp
(use-package dabbrev
:general
(python-mode-map
:states 'insert
"
** cape
:PROPERTIES:
:CUSTOM_ID: h:E2D8F1CB-9FB9-4045-A087-7045C6FAA084
:END:
#+begin_src emacs-lisp
;; Add extensions
(use-package cape
:hook ((org-mode . lc/add-cape-functions)
(lsp-completion-mode . lc/add-cape-functions))
:init
;; Add completion-at-point-functions', used by
completion-at-point'.
(defun lc/add-cape-functions ()
(interactive)
(add-to-list 'completion-at-point-functions #'cape-file t)
;; (fset #'cape-path (cape-company-to-capf #'company-files))
;; (add-to-list 'completion-at-point-functions #'cape-path t)
(add-to-list 'completion-at-point-functions #'cape-dabbrev t)
)
;;(add-to-list 'completion-at-point-functions #'cape-history)
;;(add-to-list 'completion-at-point-functions #'cape-keyword)
;;(add-to-list 'completion-at-point-functions #'cape-tex)
;;(add-to-list 'completion-at-point-functions #'cape-sgml)
;;(add-to-list 'completion-at-point-functions #'cape-rfc1345)
;;(add-to-list 'completion-at-point-functions #'cape-abbrev)
;;(add-to-list 'completion-at-point-functions #'cape-ispell)
;;(add-to-list 'completion-at-point-functions #'cape-dict)
;;(add-to-list 'completion-at-point-functions #'cape-symbol)
;;(add-to-list 'completion-at-point-functions #'cape-line)
)
#+end_src
** kind-icon :PROPERTIES: :CUSTOM_ID: h:713949BB-4722-41EB-A86A-64A7A8531DE6 :END: #+begin_src emacs-lisp (use-package kind-icon :straight (kind-icon :type git :host github :repo "jdtsmith/kind-icon") :after corfu :demand :init (setq kind-icon-default-face 'corfu-default) ; to compute blended backgrounds correctly (setq kind-icon-blend-background nil) ; Use midpoint color between foreground and background colors ("blended")? (setq kind-icon-blend-frac 0.08) :config (add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter) ;; refresh kind icon cache to match theme (with-eval-after-load 'modus-themes (add-hook 'modus-themes-after-load-theme-hook #'(lambda () (interactive) (kind-icon-reset-cache))))
) #+end_src
** bookmarks :PROPERTIES: :CUSTOM_ID: h:7BC2D32A-F652-48F9-AEA6-D595ACB41386 :END: #+begin_src emacs-lisp (use-package emacs :straight (:type built-in) :general (lc/leader-keys "r m" '(bookmark-set :wk "set bookmark") "r d" '(bookmark-delete :wk "delete bookmark") ) ) #+end_src
- Programming :PROPERTIES: :CUSTOM_ID: h:EB91F91E-8984-4806-8254-B0487044D30C :header-args: :emacs-lisp :tangle ./lisp/init-core.el :END: ** project :PROPERTIES: :CUSTOM_ID: h:0F53A833-88C3-4AEC-A469-E15AD657BEB0 :END: *** projectile :PROPERTIES: :CUSTOM_ID: h:788EC6E4-44DD-4E93-A1FC-517CA9213396 :END: NOTE:
- ~projectile~ struggles with monorepos where ~.git~ folder is at the root but each subproject has e.g a ~pyproject.toml~. In those cases, we need to create a ~.projectile~ file in the root of the subprojects.
- ~projectile~ excludes git ignored files from ~projectile-find-file~. Use ~lc/projectile-find-file-all~ when opening data
#+BEGIN_SRC emacs-lisp
(use-package projectile
:demand
:general
(lc/leader-keys
:states 'normal
"p" '(:keymap projectile-command-map :which-key "project")
"p
*** perspective :PROPERTIES: :CUSTOM_ID: h:6E4E5BD6-1930-4DCE-8E26-5ADAC2B9A152 :END: NOTE:
- You can use ~persp-state-load~ to restore the perspective when emacs was killed
#+BEGIN_SRC emacs-lisp (use-package perspective :commands (persp-new persp-switch persp-state-save) :general (lc/leader-keys "TAB" '(:ignore true :wk "tab") "TAB TAB" 'persp-switch "TAB `" 'persp-switch-last "TAB d" 'persp-kill "TAB h" 'persp-prev "TAB l" 'persp-next "TAB x" '((lambda () (interactive) (persp-kill (persp-current-name))) :wk "kill current") "TAB X" '((lambda () (interactive) (seq-doseq (name (persp-names)) (persp-kill name)) (lc/main-tab)) :wk "kill all") "TAB m" '(lc/main-tab :wk "main") ) :init (setq persp-state-default-file (expand-file-name ".persp" user-emacs-directory)) (defun lc/main-tab () "Jump to the dashboard buffer, if doesn't exists create one." (interactive) (persp-switch "main") (switch-to-buffer dashboard-buffer-name) (dashboard-mode) (dashboard-insert-startupify-lists) (dashboard-refresh-buffer)) (defun lc/is-persp-empty? () (seq-filter ;; filter away buffers which should be hidden (lambda (buffer-name) (not (string-prefix-p "*" buffer-name))) ;; get list of buffer names in current perspective (mapcar (lambda (elm) (buffer-name (car elm))) (centaur-tabs-view (centaur-tabs-current-tabset))) )) :config (persp-mode) (add-hook 'kill-emacs-hook #'persp-state-save)) #+END_SRC
*** persp-projectile :PROPERTIES: :CUSTOM_ID: h:85ED0544-8351-4B05-843D-8BB9F3454041 :END: NOTE:
- Use =SPC TAB r= to reload a project when something went wrong with =SPC p p=
#+BEGIN_SRC emacs-lisp (use-package persp-projectile :after projectile :init (defun lc/get-last-folder-from-known-proj (path) "/path/to/something/ returns something" (car (last (split-string path "/") 2))) (defun lc/find-project-from-persp (persp-name) "known-proj returns /path/to/known-proj" (car (seq-filter (lambda (proj) (string= persp-name (lc/get-last-folder-from-known-proj proj))) projectile-known-projects-on-file))) (defun lc/persp-reload-project () (interactive) (let* ((persp (persp-current-name)) (proj-root (lc/find-project-from-persp persp))) (persp-kill persp) (projectile-persp-switch-project proj-root))) :general (lc/leader-keys "p p" 'projectile-persp-switch-project "TAB r" '(lc/persp-reload-project :wk "reload") ;; "TAB o" '((lambda () (interactive) ;; (let ((projectile-switch-project-action #'projectile-find-file)) ;; (projectile-persp-switch-project "org"))) ;; :wk "org") ) ) #+END_SRC
** dired and friends :PROPERTIES: :CUSTOM_ID: h:BA5D7535-070B-494B-A27C-6B9FFC3CC88E :END:
- Jump to current file with =SPC f j=
- With a ~dired~ buffer open, use ~dired-other-window~ to open another folder where you want to move/copy files from/to
- Hide details with ~(~ )
- Show/hide dotfiles with =H=
- Mark with ~m~, unmark with ~u~
- Invert selection with ~t~
- ~*~ has some helpers for marking
- First mark some files and then ~K~ to "hide" them
- Open directory in right window with ~S-RET~
- When copying from left window, target will be right window
- Copy with ~C~
- Open subdir in buffer below with ~I~
- Open them as subtree with =i=
- Open files with macos with =O=
- View files with =go= and exit with ~q~ *** dired :PROPERTIES: :CUSTOM_ID: h:3789628F-1F87-48C6-BC70-2E31E6F485D0 :END: NOTE:
- To get full path of a file =SPC U 0 Y=
:PROPERTIES: :CUSTOM_ID: h:D6BC5C09-6F03-4D08-9237-F955D6B2F39D :END: #+BEGIN_SRC emacs-lisp (use-package dired :straight (:type built-in) :hook (dired-mode . dired-hide-details-mode) :general (lc/leader-keys "f d" 'dired "f j" 'dired-jump) (dired-mode-map :states 'normal "h" 'dired-up-directory "l" 'dired-find-file "q" 'kill-current-buffer "F" '((lambda () (interactive) (let ((fn (dired-get-file-for-visit))) (start-process "open-directory" nil "open" "-R" fn))) :wk "open finder") "X" '(lc/dired-open-externally :wk "open external")) :init (setq dired-omit-files "^\.[^.]\|$Rhistory\|$RData\|pycache") (setq dired-listing-switches "-lah") (setq ls-lisp-dirs-first t) (setq ls-lisp-use-insert-directory-program nil) (setq dired-dwim-target t) (setf dired-kill-when-opening-new-dired-buffer t) (defun lc/dired-open-externally () "Open marked dired file/folder(s) (or file/folder(s) at point if no marks) with external application" (interactive) (let ((fn (dired-get-file-for-visit))) (start-process "open-external" nil "open" fn))) )
(use-package all-the-icons-dired :if (display-graphic-p) :hook (dired-mode . (lambda () (interactive) (unless (file-remote-p default-directory) (all-the-icons-dired-mode)))))
(use-package dired-hide-dotfiles :hook (dired-mode . dired-hide-dotfiles-mode) :config (evil-collection-define-key 'normal 'dired-mode-map "H" 'dired-hide-dotfiles-mode)) #+END_SRC
*** dired subtree :PROPERTIES: :CUSTOM_ID: h:230AF0C3-8214-46BB-AB84-C81C047DC8C8 :END: #+BEGIN_SRC emacs-lisp (use-package dired-subtree :general (dired-mode-map :states 'normal "i" 'dired-subtree-toggle) :config (advice-add 'dired-subtree-toggle :after (lambda () (interactive) (when all-the-icons-dired-mode (revert-buffer))))) #+END_SRC
*** COMMENT dired rsync :PROPERTIES: :CUSTOM_ID: h:629AEC4E-F112-457A-BAF9-6B5786DEC8EF :END: #+begin_src emacs-lisp (use-package dired-rsync :general (lc/local-leader-keys :keymaps 'dired-mode-map :states 'normal "r" 'dired-rsync)) #+end_src
** persistent scratch :PROPERTIES: :CUSTOM_ID: h:FF4B176D-E133-4013-9926-87F9A20E3BBD :END: #+begin_src emacs-lisp (use-package persistent-scratch :hook (org-mode . (lambda () "only set initial-major-mode after loading org" (setq initial-major-mode 'org-mode))) :general (lc/leader-keys "bs" '((lambda () "Load persistent-scratch if not already loaded" (interactive) (progn (unless (boundp 'persistent-scratch-mode) (require 'persistent-scratch)) (pop-to-buffer "scratch"))) :wk "scratch")) :init (setq persistent-scratch-autosave-interval 60) :config (persistent-scratch-setup-default)) #+end_src
** rainbow parenthesis :PROPERTIES: :CUSTOM_ID: h:D5084868-D46D-4AC7-ACE4-A7EDB10703EE :END: #+BEGIN_SRC emacs-lisp (use-package rainbow-delimiters :hook ((emacs-lisp-mode . rainbow-delimiters-mode) (clojure-mode . rainbow-delimiters-mode)) ) #+END_SRC
** restart-emacs :PROPERTIES: :CUSTOM_ID: h:4C37CFFC-D045-47B4-BFDC-801977247199 :END: #+begin_src emacs-lisp (use-package restart-emacs :general (lc/leader-keys "R" '(restart-emacs :wk "restart")) ) #+end_src
** term :PROPERTIES: :CUSTOM_ID: h:e38bee3c-2451-4c32-b22c-228c2f2c4d4f :END: #+begin_src emacs-lisp (use-package term :if lc/is-ipad :straight (:type built-in) :general (lc/leader-keys "'" (lambda () (interactive) (term "/bin/zsh"))) )
(use-package term :if lc/is-windows :straight (:type built-in) :general (lc/leader-keys "'" (lambda () (interactive) (let ((explicit-shell-file-name "C:/Program Files/Git/bin/bash")) (call-interactively 'shell)))) ;; (setq explicit-shell-file-name "C:/Program Files/Git/bin/bash") ;; (setq explicit-bash.exe-args '("--login" "-i")) )
#+end_src
** tramp :PROPERTIES: :CUSTOM_ID: h:48EFC0F4-8C5C-47CF-A464-420A618A01C2 :END:
- Call e.g. ~dired~ and input ~/ssh:user@hostname:/path/to/file~
- In ~.ssh/config~ you can set ~ControlMaster Yes~ for a host, then ssh with the terminal
#+begin_src emacs-lisp (use-package tramp :straight (:type built-in) :init ;; Disable version control on tramp buffers to avoid freezes. (setq vc-ignore-dir-regexp (format "\(%s\)\|\(%s\)" vc-ignore-dir-regexp tramp-file-name-regexp)) (setq tramp-default-method "ssh") (setq tramp-auto-save-directory (expand-file-name "tramp-auto-save" user-emacs-directory)) (setq tramp-persistency-file-name (expand-file-name "tramp-connection-history" user-emacs-directory)) (setq password-cache-expiry nil) (setq tramp-use-ssh-controlmaster-options nil) (setq remote-file-name-inhibit-cache nil) :config (customize-set-variable 'tramp-ssh-controlmaster-options (concat "-o ControlPath=/tmp/ssh-tramp-%%r@%%h:%%p " "-o ControlMaster=auto -o ControlPersist=yes")) (with-eval-after-load 'lsp-mode (lsp-register-client (make-lsp-client :new-connection (lsp-tramp-connection "pyright") :major-modes '(python-mode) :remote? t :server-id 'pyright-remote)) ) )
(use-package docker-tramp) #+end_src
** undo fu :PROPERTIES: :CUSTOM_ID: h:FEB4E3B3-47E7-4AAE-ADD7-524A57387301 :END: #+begin_src emacs-lisp (use-package undo-fu ;; :demand :general (:states 'normal "u" 'undo-fu-only-undo "s-z" 'undo-fu-only-undo "\C-r" 'undo-fu-only-redo)) #+end_src
** undo fu session (persistent undo history) :PROPERTIES: :CUSTOM_ID: h:FC2D5A9A-DBD5-4878-AB4E-BBF5826B98E8 :END: #+begin_src emacs-lisp (use-package undo-fu-session :after undo-fu :demand :init (setq undo-fu-session-incompatible-files '("/COMMIT_EDITMSG\'" "/git-rebase-todo\'")) :config (global-undo-fu-session-mode) ) #+end_src
** git :git: :PROPERTIES: :CUSTOM_ID: h:0D3218A4-4F45-4C20-9320-087750D5A961 :END: *** magit :PROPERTIES: :CUSTOM_ID: h:61B8B839-46CA-4AE6-AD57-A6D291E7C225 :END: 50/72 rule for commit messages: https://www.midori-global.com/blog/2018/04/02/git-50-72-rule
NOTE:
- ~magit-cycle-margin-style~ to show more precise commit timestamps
- On iPad, we may need to ~(require 'sendmail)~ before calling ~magit-status~
- You can use ~magit-diff-range~ to compare branches if you select the branch as target
#+BEGIN_SRC emacs-lisp
(use-package magit
:general
(lc/leader-keys
"g b" 'magit-blame
"g g" 'magit-status
"g G" 'magit-status-here
"g l" 'magit-log)
(general-nmap
:keymaps '(magit-status-mode-map
magit-stash-mode-map
magit-revision-mode-map
magit-process-mode-map
magit-diff-mode-map)
"TAB" #'magit-section-toggle
"
*** COMMENT forge :PROPERTIES: :CUSTOM_ID: h:6776E02F-A2E6-4BBA-91A1-81EEE4CFB3AB :END: #+BEGIN_SRC emacs-lisp ;; NOTE: Make sure to configure a GitHub token before using this package! ;; - https://magit.vc/manual/forge/Token-Creation.html#Token-Creation ;; - https://magit.vc/manual/ghub/Getting-Started.html#Getting-Started (use-package forge :after magit) #+END_SRC
*** git-timemachine :PROPERTIES: :CUSTOM_ID: h:5CA4BCDE-A8D6-472F-9FA1-FA5514CC9388 :END: #+begin_src emacs-lisp (use-package git-timemachine :hook (git-time-machine-mode . evil-normalize-keymaps) :init (setq git-timemachine-show-minibuffer-details t) :general (general-nmap "SPC g t" 'git-timemachine-toggle) (git-timemachine-mode-map "C-k" 'git-timemachine-show-previous-revision "C-j" 'git-timemachine-show-next-revision "q" 'git-timemachine-quit)) #+end_src
*** diff-hl :PROPERTIES: :CUSTOM_ID: h:DA2BAD8C-A37A-4A89-BEE0-A7FB367CD345 :END: When an heading includes a change, the ~org-ellipsis~ not shown correctly. This is caused by an empty line with ~diff-hl~ fringe that gets appended to the heading. To work around this and show the ellipsis, you have to add a whitespace in that empty line.
#+begin_src emacs-lisp (use-package diff-hl :demand :general (lc/leader-keys "g n" '(diff-hl-next-hunk :wk "next hunk") "g p" '(diff-hl-previous-hunk :wk "prev hunk")) :hook ((magit-pre-refresh . diff-hl-magit-pre-refresh) (magit-post-refresh . diff-hl-magit-post-refresh)) :init (setq diff-hl-draw-borders nil) ;; (setq diff-hl-global-modes '(not org-mode)) ;; (setq diff-hl-fringe-bmp-function 'diff-hl-fringe-bmp-from-type) ;; (setq diff-hl-global-modes (not '(image-mode org-mode))) :config (global-diff-hl-mode) ) #+end_src
:PROPERTIES: :CUSTOM_ID: h:6C6EA9DD-42EE-49CD-A7FC-5BE9FAB42F7F :END: *** smerge + hydra-smerge :PROPERTIES: :CUSTOM_ID: h:DADD41F3-F805-4E89-9EDB-B21350A81A19 :END: #+begin_src emacs-lisp (use-package hydra :after evil :demand :general (lc/leader-keys "w w" 'evil-windows-hydra/body) :init (defhydra evil-windows-hydra (:hint nil ;; :pre (smerge-mode 1) ;; :post (smerge-auto-leave) ) " [h] ⇢⇠ decrease width [l] ⇠⇢ increase width [j] decrease height [k] increase height │ [q] quit" ("h" evil-window-decrease-width) ("l" evil-window-increase-width) ("j" evil-window-decrease-height) ("k" evil-window-increase-height) ("q" nil :color blue) ) )
(use-package smerge-mode :straight (:type built-in) :after hydra :general (lc/leader-keys "g m" 'smerge-hydra/body) :hook (magit-diff-visit-file . (lambda () (when smerge-mode (smerge-hydra/body)))) :init (defhydra smerge-hydra (:hint nil :pre (smerge-mode 1) ;; Disable `smerge-mode' when quitting hydra if ;; no merge conflicts remain. :post (smerge-auto-leave)) " ╭────────┐ Movement Keep Diff Other │ smerge │ ╭─────────────────────────────────────────────────┴────────╯ ^g^ [b] base [<] upper/base [C] Combine ^C-k^ [u] upper [=] upper/lower [r] resolve ^k ↑^ [l] lower [>] base/lower [R] remove ^j ↓^ [a] all [H] hightlight ^C-j^ [RET] current [E] ediff ╭────────── ^G^ │ [q] quit" ("g" (progn (goto-char (point-min)) (smerge-next))) ("G" (progn (goto-char (point-max)) (smerge-prev))) ("C-j" smerge-next) ("C-k" smerge-prev) ("j" next-line) ("k" previous-line) ("b" smerge-keep-base) ("u" smerge-keep-upper) ("l" smerge-keep-lower) ("a" smerge-keep-all) ("RET" smerge-keep-current) ("\C-m" smerge-keep-current) ("<" smerge-diff-base-upper) ("=" smerge-diff-upper-lower) (">" smerge-diff-base-lower) ("H" smerge-refine) ("E" smerge-ediff) ("C" smerge-combine-with-next) ("r" smerge-resolve) ("R" smerge-kill-current) ("q" nil :color blue))) #+end_src
** emacs tree-sitter :prog_tree_sitter: :PROPERTIES: :CUSTOM_ID: h:1FD9CDF3-4C5D-450E-99DE-034077C3D8BC :header-args: :emacs-lisp :tangle ./lisp/init-prog-tree-sitter.el :END: #+BEGIN_SRC emacs-lisp (use-package tree-sitter ;; :straight (tree-sitter :host github :repo "ubolonton/emacs-tree-sitter" :depth full) :hook (python-mode . (lambda () (require 'tree-sitter) (require 'tree-sitter-langs) (require 'tree-sitter-hl) (tree-sitter-hl-mode) )))
(use-package tree-sitter-langs) #+END_SRC
** envrc :direnv: :PROPERTIES: :CUSTOM_ID: h:65206410-8DD7-499E-AA70-6D9C781C0E0D :END: Running ~direnv~ is expensive so I only do it when it is necessary. I need it in two situations:
- ~python-mode~
- ~ob-jupyter~
Instead of simply enabling ~envrc-mode~ in every org buffer, I check with the buffer includes a ~jupyter-python~ block. In the [[*ob-jupyter][ob-jupyter]] section I then load ~ob-jupyter~ only when ~envrc-mode~ is loaded and ~jupyter~ is found on the ~PATH~
#+begin_src emacs-lisp (use-package inheritenv :straight (inheritenv :type git :host github :repo "purcell/inheritenv")) #+end_src
#+begin_src emacs-lisp (use-package envrc :straight (envrc :type git :host github :repo "purcell/envrc") :commands (envrc-mode) :hook ((python-mode . envrc-mode) (org-jupyter-mode . envrc-mode)) ) #+end_src
** snippets :yasnippet: :PROPERTIES: :CUSTOM_ID: h:8E2A5EAF-B690-457E-86E7-9070B51297A7 :END: *** yasnippet :PROPERTIES: :CUSTOM_ID: h:ae484d90-a853-4e7a-a073-42485a76f0aa :END: We use =C-TAB= to expand snippets instead of =TAB= .
You can have ~#condition: 'auto~ for the snippet to auto-expand.
See [[http://joaotavora.github.io/yasnippet/snippet-organization.html#org7468fa9][here]] to share snippets across modes
#+begin_src emacs-lisp (use-package yasnippet :general (yas-minor-mode-map :states 'insert "TAB" 'nil "C-TAB" 'yas-expand) :hook ((prog-mode org-mode dap-ui-repl-mode vterm-mode) . yas-minor-mode) :init ;; (setq yas-prompt-functions '(yas-ido-prompt)) (defun lc/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)))) :config (yas-reload-all) (add-hook 'post-command-hook #'lc/yas-try-expanding-auto-snippets) ) #+end_src
*** LaTeX yasnippets :PROPERTIES: :CUSTOM_ID: h:83403D79-9668-48DC-82FB-98FAFFD7DF11 :END: #+begin_src emacs-lisp (use-package yasnippet :config (setq lc/greek-alphabet '(("a" . "\alpha") ("b" . "\beta" ) ("g" . "\gamma") ("d" . "\delta") ("e" . "\epsilon") ("z" . "\zeta") ("h" . "\eta") ("t" . "\theta") ("i" . "\iota") ("k" . "\kappa") ("l" . "\lambda") ("m" . "\mu") ("n" . "\nu") ("x" . "\xi") ("p" . "\pi") ("r" . "\rho") ("s" . "\sigma") ("t" . "\tau") ("u" . "\upsilon") ("f" . "\phi") ("c" . "\chi") ("v" . "\psi") ("g" . "\omega")))
(setq lc/latex-greek-prefix "'")
;; The same for capitalized letters (dolist (elem lc/greek-alphabet) (let ((key (car elem)) (value (cdr elem))) (when (string-equal key (downcase key)) (add-to-list 'lc/greek-alphabet (cons (capitalize (car elem)) (concat (substring value 0 1) (capitalize (substring value 1 2)) (substring value 2)))))))
(yas-define-snippets 'latex-mode (mapcar (lambda (elem) (list (concat lc/latex-greek-prefix (car elem)) (cdr elem) (concat "Greek letter " (car elem)))) lc/greek-alphabet))
(setq lc/english-alphabet '("a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"))
(dolist (elem lc/english-alphabet) (when (string-equal elem (downcase elem)) (add-to-list 'lc/english-alphabet (upcase elem))))
(setq lc/latex-mathbb-prefix "`")
(yas-define-snippets 'latex-mode (mapcar (lambda (elem) (list (concat lc/latex-mathbb-prefix elem) (concat "\mathbb{" elem "}") (concat "Mathbb letter " elem))) lc/english-alphabet))
(setq lc/latex-math-symbols '(("x" . "\times") ("." . "\cdot") ("v" . "\forall") ("s" . "\sum_{$1}^{$2}$0") ("p" . "\prod_{$1}^{$2}$0") ("e" . "\exists") ("i" . "\int_{$1}^{$2}$0") ("c" . "\cap") ("u" . "\cup") ("0" . "\emptyset")))
(setq lc/latex-math-prefix "''")
(yas-define-snippets 'latex-mode (mapcar (lambda (elem) (let ((key (car elem)) (value (cdr elem))) (list (concat lc/latex-math-prefix key) value (concat "Math symbol " value)))) lc/latex-math-symbols)) ) #+end_src
** vterm and friends :prog_vterm: :PROPERTIES: :CUSTOM_ID: h:55C74553-9DAF-49E6-955A-C772FD7B4402 :header-args: :emacs-lisp :tangle ./lisp/init-prog-vterm.el :END: *** vterm :PROPERTIES: :CUSTOM_ID: h:2dc32a09-6e88-4d10-9e30-f138f4345143 :END: #+BEGIN_SRC emacs-lisp (use-package vterm :if (not lc/is-ipad) :general (general-imap :keymaps 'vterm-mode-map "M-l" 'vterm-send-right "M-h" 'vterm-send-left) :config (setq vterm-shell (executable-find "fish") vterm-max-scrollback 10000)) #+END_SRC
*** vterm toggle :PROPERTIES: :CUSTOM_ID: h:1162BDDB-9DC6-4750-8EF8-9C5D2AF51892 :END: NOTE:
- You can use universal argument to create a new vterm buffer (=SPC U SPC '=)
#+begin_src emacs-lisp (use-package vterm-toggle :if (not lc/is-ipad) :general (lc/leader-keys "'" 'vterm-toggle) :init (setq vterm-toggle-scope 'project) ) #+end_src
** search google :prog_extra: :PROPERTIES: :CUSTOM_ID: h:01E26AB9-2829-4076-9665-E218832FB1A3 :END: #+begin_src emacs-lisp (use-package emacs :general (lc/leader-keys "s g" '(google-search :wk "google")) :init (defun google-search-str (str) (browse-url (concat "https://www.google.com/search?q=" str))) (defun google-search () "Google search region, if active, or ask for search string." (interactive) (if (region-active-p) (google-search-str (buffer-substring-no-properties (region-beginning) (region-end))) (google-search-str (read-from-minibuffer "Search: ")))) ) #+end_src
** search github :prog_extra: :PROPERTIES: :CUSTOM_ID: h:6872D17A-1A2E-4394-A83B-16D5328D88BC :END: #+begin_src emacs-lisp (use-package emacs :general (lc/leader-keys "s c" '(github-code-search :wk "code (github)")) :init (defun github-code-search () "Search code on github for a given language." (interactive) (let ((language (completing-read "Language: " '("Emacs Lisp" "Python" "Clojure" "R"))) (code (read-string "Code: "))) (browse-url (concat "https://github.com/search?l=" language "&type=code&q=" code)))) ) #+end_src
** transient help commands :prog_extra:
:PROPERTIES:
:CUSTOM_ID: h:14F8ECDE-9E15-46F7-B903-ECE383251C48
:END:
#+begin_src emacs-lisp
(use-package transient
:general
(lc/leader-keys
"h h" 'lc/help-transient)
:config
(transient-define-prefix lc/help-transient ()
["Help Commands"
["Mode & Bindings"
("m" "Mode" describe-mode)
("b" "Major Bindings" which-key-show-full-major-mode)
("B" "Minor Bindings" which-key-show-full-minor-mode-keymap)
("d" "Descbinds" describe-bindings)
]
["Describe"
("c" "Command" helpful-command)
("f" "Function" helpful-callable)
("v" "Variable" helpful-variable)
("k" "Key" helpful-key)
]
["Info on"
("C-c" "Emacs Command" Info-goto-emacs-command-node)
("C-f" "Function" info-lookup-symbol)
("C-v" "Variable" info-lookup-symbol)
("C-k" "Emacs Key" Info-goto-emacs-key-command-node)
]
["Goto Source"
("L" "Library" find-library)
("F" "Function" find-function)
("V" "Variable" find-variable)
("K" "Key" find-function-on-key)
]
]
[
["Internals"
("e" "Echo Messages" view-echo-area-messages)
("l" "Lossage" view-lossage)
]
["Describe"
("s" "Symbol" helpful-symbol)
("." "At Point " helpful-at-point)
;; ("C-f" "Face" counsel-describe-face)
("w" "Where Is" where-is)
("=" "Position" what-cursor-position)
]
["Info Manuals"
("C-i" "Info" info)
("C-4" "Other Window " info-other-window)
("C-e" "Emacs" info-emacs-manual)
;; ("C-l" "Elisp" info-elisp-manual)
]
["Exit"
("q" "Quit" transient-quit-one)
("
** transient increase/decrease font size :prog_extra: :PROPERTIES: :CUSTOM_ID: h:884FB8DF-D672-496E-9068-1FD15F0250E5 :END: NOTE:
- If after increasing and resetting font size your modeline is still "fat", you can reset, decrease and reset to fix it
#+begin_src emacs-lisp (use-package default-text-scale :hook (emacs-startup . default-text-scale-mode) )
(use-package transient :general (lc/leader-keys "t f" 'lc/font-size-transient) :config (transient-define-prefix lc/font-size-transient () "Change font size" ["Font size" ("+" "Increase" (lambda () (interactive) (default-text-scale-increase) (with-eval-after-load 'doom-modeline (doom-modeline-refresh-font-width-cache)) (lc/font-size-transient))) ("-" "Decrease" (lambda () (interactive) (default-text-scale-decrease) (with-eval-after-load 'doom-modeline (doom-modeline-refresh-font-width-cache)) (lc/font-size-transient))) ("0" "Reset" (lambda () (interactive) (setq default-text-scale--complement 0) (set-face-attribute 'default nil :height (lc/get-font-size)) (message "Default font size is now %d" (face-attribute 'default :height)) (lc/font-size-transient))) ]) (transient-bind-q-to-quit) ) #+end_src
** isearch-mb :prog_extra: :PROPERTIES: :CUSTOM_ID: h:58E5AE2F-4E1C-4B72-9B63-B96AEF55F4DA :END: You can use ~consult-history~ to browse past searches
#+begin_src emacs-lisp (use-package isearch-mb :straight (isearch-mb :type git :host github :repo "astoff/isearch-mb") :demand :init (setq-default ;; Match count next to minibuffer prompt isearch-lazy-count t ;; Don't be stingy with history; default is to keep just 16 entries search-ring-max 200 regexp-search-ring-max 200 ;; fuzzy match with space isearch-regexp-lax-whitespace t search-whitespace-regexp ".*?" ) :config (add-to-list 'isearch-mb--with-buffer #'loccur-isearch) (define-key isearch-mb-minibuffer-map (kbd "C-o") #'loccur-isearch) ) #+end_src
** olivetti mode :extra_focus: :PROPERTIES: :CUSTOM_ID: h:78EE4DFB-9A75-4BB0-BD4D-CFF94ACE3CF6 :header-args: :emacs-lisp :tangle ./lisp/init-extra-focus.el :END: #+begin_src emacs-lisp (use-package olivetti :general (lc/leader-keys "t o" '(olivetti-mode :wk "olivetti")) :init (setq olivetti-body-width 100) (setq olivetti-recall-visual-line-mode-entry-state t)) #+end_src
** darkroom :extra_focus: :PROPERTIES: :CUSTOM_ID: h:EC24FC48-E3A5-4C16-9F52-3A6E14DBA564 :header-args: :emacs-lisp :tangle ./lisp/init-extra-focus.el :END: #+begin_src emacs-lisp (use-package darkroom :init ;; Don't scale the text, so ugly man! (setq darkroom-text-scale-increase 3) :general (lc/leader-keys "t F" '(darkroom-tentative-mode :wk "focus"))) #+end_src
** avy :PROPERTIES: :CUSTOM_ID: h:37FF0EE6-B8B7-4208-8F31-7361AB22DC52 :END: #+begin_src emacs-lisp (use-package avy :general (general-nmap ;; "gs" 'avy-goto-char-2) "gs" 'avy-goto-char-timer) ;; :bind (("C-:" . avy-goto-char) ;; ("C-'" . avy-goto-char-2) ;; ("C-;" . avy-goto-char-2) ;; ("M-g f" . avy-goto-line) ;; ("M-g w" . avy-goto-word-1) ;; ("M-g e" . avy-goto-word-0)) :hook (after-init . avy-setup-default) :init (setq avy-style 'pre) ;; :custom ( avy-all-windows nil ;; avy-all-windows-alt t ;; avy-background t ;; avy-style 'pre) ) #+end_src
** devdocs :PROPERTIES: :CUSTOM_ID: h:21F53DE6-4F2C-4B38-9C72-98E303687C7D :END: NOTE:
- =devdocs-install= to install docs of e.g. ~pandas~ #+begin_src emacs-lisp (use-package devdocs :demand :general (lc/leader-keys "hD" 'devdocs-lookup ) ) #+end_src
** imenu-list :PROPERTIES: :CUSTOM_ID: h:82A4886B-7891-4109-A164-0865E8E93CAD :END: #+begin_src emacs-lisp (use-package imenu-list :general (lc/leader-keys "t i" 'imenu-list-smart-toggle )
) #+end_src
** COMMENT kubernetes :PROPERTIES: :CUSTOM_ID: h:3645D06E-69FC-4B56-AEAF-A5967E66FD85 :END: #+begin_src emacs-lisp (use-package kubernetes :hook (kubernetes-overview-mode . lc/load-kubernetes-evil) :general (lc/leader-keys "k k" 'kubernetes-overview) :init ;; refresh manually with gr (setq kubernetes-poll-frequency 3600) (setq kubernetes-redraw-frequency 3600) (defun lc/load-kubernetes-evil () "Copied from kubernetes-evil.el" (evil-set-initial-state 'kubernetes-mode 'motion) (evil-set-initial-state 'kubernetes-display-thing-mode 'motion) (evil-set-initial-state 'kubernetes-log-line-mode 'motion) (evil-set-initial-state 'kubernetes-logs-mode 'motion) (evil-set-initial-state 'kubernetes-overview-mode 'motion)
(evil-define-key 'motion kubernetes-mode-map
(kbd "p") #'magit-section-backward
(kbd "n") #'magit-section-forward
(kbd "M-p") #'magit-section-backward-sibling
(kbd "M-n") #'magit-section-forward-sibling
(kbd "C-i") #'magit-section-toggle
(kbd "^") #'magit-section-up
[tab] #'magit-section-toggle
[C-tab] #'magit-section-cycle
[M-tab] #'magit-section-cycle-diffs
[S-tab] #'magit-section-cycle-global
[remap evil-next-line] #'next-line
[remap evil-previous-line] #'previous-line
[remap evil-next-visual-line] #'next-line
[remap evil-previous-visual-line] #'previous-line
(kbd "q") #'quit-window
(kbd "RET") #'kubernetes-navigate
(kbd "M-w") #'kubernetes-copy-thing-at-point
(kbd "?") #'kubernetes-overview-popup
(kbd "c") #'kubernetes-config-popup
(kbd "g r") #'kubernetes-refresh
(kbd "h") #'describe-mode
(kbd "d") #'kubernetes-describe-popup
(kbd "D") #'kubernetes-mark-for-delete
(kbd "e") #'kubernetes-exec-popup
(kbd "u") #'kubernetes-unmark
(kbd "U") #'kubernetes-unmark-all
(kbd "x") #'kubernetes-execute-marks
(kbd "l") #'kubernetes-logs-popup
(kbd "L") #'kubernetes-labels-popup)
(evil-define-key 'motion kubernetes-overview-mode-map
(kbd "v") #'kubernetes-overview-set-sections)
(evil-define-key 'motion kubernetes-logs-mode-map
(kbd "n") #'kubernetes-logs-forward-line
(kbd "p") #'kubernetes-logs-previous-line
(kbd "RET") #'kubernetes-logs-inspect-line)
(evil-define-key 'motion kubernetes-log-line-mode-map
(kbd "n") #'kubernetes-logs-forward-line
(kbd "p") #'kubernetes-logs-previous-line))
) #+end_src
** COMMENT loccurr :PROPERTIES: :CUSTOM_ID: h:3FC3E32D-BE2D-421C-B599-94E802009AB0 :END: #+begin_src emacs-lisp (use-package loccur :commands (loccur-isearch) ) #+end_src
- Programming languages
:PROPERTIES:
:CUSTOM_ID: h:844F8FAD-8F11-4727-BAC4-25B449C56B51
:header-args: :emacs-lisp :tangle ./lisp/init-extra.el
:END:
** lsp mode and friends :prog_lsp:
:PROPERTIES:
:CUSTOM_ID: h:6BC08822-D2B3-4BE9-9EBE-C42F89F0E688
:header-args: :emacs-lisp :tangle ./lisp/init-prog-lsp.el
:END:
*** lsp-mode
:PROPERTIES: :CUSTOM_ID: h:28CB5546-FBE4-481D-B620-623006DC0FDA :END: #+BEGIN_SRC emacs-lisp (use-package lsp-mode :commands (lsp lsp-deferred) :hook ((lsp-mode . (lambda () (setq-local evil-lookup-func #'lsp-describe-thing-at-point))) (lsp-mode . lsp-enable-which-key-integration)) :general (lc/local-leader-keys :states 'normal :keymaps 'lsp-mode-map "i" '(:ignore t :which-key "import") "i o" '(lsp-organize-imports :wk "optimize") "l" '(:keymap lsp-command-map :wk "lsp") "a" '(lsp-execute-code-action :wk "code action") "r" '(lsp-rename :wk "rename")) ;; (lsp-mode-map ;; :states 'normal ;; "gD" 'lsp-find-references) :init (setq lsp-restart 'ignore) (setq lsp-eldoc-enable-hover nil) (setq lsp-enable-file-watchers nil) (setq lsp-signature-auto-activate nil) (setq lsp-modeline-diagnostics-enable nil) (setq lsp-keep-workspace-alive nil) (setq lsp-auto-execute-action nil) (setq lsp-before-save-edits nil) (setq lsp-headerline-breadcrumb-enable nil) (setq lsp-diagnostics-provider :none) ) #+END_SRC
*** lsp-ui
:PROPERTIES:
:CUSTOM_ID: h:B69B077F-B96E-4A86-859D-A3D29547D39C
:END:
#+BEGIN_SRC emacs-lisp
(use-package lsp-ui
:hook
((lsp-mode . lsp-ui-mode)
;; (lsp-mode . (lambda () (setq-local evil-goto-definition-functions '(lambda (&rest args) (lsp-ui-peek-find-definitions)))))
)
;; :bind
;; (:map lsp-ui-mode-map
;; ([remap lsp-find-references] . lsp-ui-peek-find-references))
:general
;; (lc/local-leader-keys
;; "h" 'lsp-ui-doc-show
;; "H" 'lsp-ui-doc-hide)
(lsp-ui-peek-mode-map
:states 'normal
"C-j" 'lsp-ui-peek--select-next
"C-k" 'lsp-ui-peek--select-prev)
(outline-mode-map
:states 'normal
"C-j" 'nil
"C-k" 'nil)
:init
(setq lsp-ui-doc-show-with-cursor nil)
(setq lsp-ui-doc-show-with-mouse nil)
(setq lsp-ui-peek-always-show t)
(setq lsp-ui-peek-fontify 'always)
)
#+END_SRC
*** dap-mode
:PROPERTIES:
:CUSTOM_ID: h:85405E87-7858-4F5C-A229-B72E70F68597
:END:
#+BEGIN_SRC emacs-lisp
(use-package dap-mode
:hook
((dap-mode . corfu-mode)
(dap-terminated . lc/hide-debug-windows)
(dap-session-created . (lambda (_arg) (projectile-save-project-buffers)))
(dap-ui-repl-mode . (lambda () (setq-local truncate-lines t))))
:general
(lc/local-leader-keys
:states '(normal)
:keymaps '(python-mode-map dap-ui-repl-mode-map)
"d d" '(dap-debug :wk "debug")
"d b" '(dap-breakpoint-toggle :wk "breakpoint toggle")
"d B" '(dap-ui-breakpoints-list :wk "breakpoint list")
"d c" '(dap-continue :wk "continue")
"d n" '(dap-next :wk "next")
"d e" '(dap-eval-thing-at-point :wk "eval")
"d i" '(dap-step-in :wk "step in")
"d l" '(dap-debug-last :wk "step in")
"d q" '(dap-disconnect :wk "quit")
"d r" '(dap-ui-repl :wk "repl")
"d h" '(dap-hydra :wk "hydra")
"d i" '(lc/dap-inspect-df :wk "view df")
;; "d t" '(lc/dap-dtale-df :wk "dtale df")
)
(dap-ui-repl-mode-map
:states '(insert)
"((side . bottom) (slot . 5) (window-width . 0.20)))) ;; (delete-window window)) (lc/kill-output-buffer) ;; delete dataframe inspector window ;; (when-let ;; (win (get-buffer-window (get-file-buffer lc/dap-temp-dataframe-path))) ;; (delete-window win)) ) ) (defun lc/dap-python--executable-find (orig-fun &rest args) (executable-find "python")) (defun lc/kill-output-buffer () "Go to output buffer." (interactive) (let ((win (display-buffer-in-side-window (dap--debug-session-output-buffer (dap--cur-session-or-die))
((side . bottom) (slot . 5) (window-width . 0.20)))))
(delete-window win)))
(defun lc/window-resize-to-percentage (percentage)
(interactive)
(window-resize nil (- (truncate (* percentage (frame-height))) (window-height))))
(defun lc/reset-dap-windows ()
(interactive)
;; display sessions and repl
(seq-doseq (feature-start-stop dap-auto-configure-features)
(when-let
(start-stop (alist-get feature-start-stop
;; <
dap-features->windows
))
(funcall (car start-stop))))
;; display output buffer
(save-excursion (dap-go-to-output-buffer t))
;; resize window
(save-window-excursion
;; switch to main window
(winum-select-window-1)
(lc/window-resize-to-percentage 0.66)
)
)
:config ;; configure windows (require 'dap-ui) (setq dap-ui-buffer-configurations '(("dap-ui-sessions" (side . bottom) (slot . 1) (window-height . 0.33)) ("debug-window" (side . bottom) (slot . 2) (window-height . 0.33)) ("dap-ui-repl" (side . bottom) (slot . 3) (window-height . 0.33)))) (dap-ui-mode 1) ;; python virtualenv (require 'dap-python) (advice-add 'dap-python--pyenv-executable-find :around #'lc/dap-python--executable-find) ;; debug templates (defvar dap-script-args (list :type "python" :args [] :cwd "${workspaceFolder}" :justMyCode :json-false :request "launch" :debugger 'debugpy :name "dap-debug-script")) (defvar dap-test-args (list :type "python-test-at-point" :args "" :justMyCode :json-false ;; :cwd "${workspaceFolder}" :request "launch" :module "pytest" :debugger 'debugpy :name "dap-debug-test-at-point")) (defvar flight-tower-mill (list :name "mill" :type "python" :request "launch" :program (expand-file-name "~/git/Sodra.Common.FlightTower/flight_tower/main.py") ;; :env '(("NO_JSON_LOG" . "true")) :args ["-m" "mill" "--config" "user_luca"])) (defvar flight-tower-calibration (list :name "mill" :type "python" :request "launch" :program (expand-file-name "~/git/Sodra.Common.FlightTower/flight_tower/main.py") ;; :env '(("NO_JSON_LOG" . "true")) :args ["-m" "mill" ;; "--config" "user_luca" ;; "--config" "calibration_g292imp_41x185" ;; "--config" "calibration_41x185_38x89" "--config" "calibration_jan22" ] )) (defvar flight-tower-e2e (list :name "mill" :type "python" :request "launch" :program (expand-file-name "~/git/Sodra.Common.FlightTower/flight_tower/main.py") ;; :env '(("NO_JSON_LOG" . "true")) :args ["-m" "wood_processing_e2e" "--config" "user_luca"] )) (defvar mill-data-factory (list :name "mill" :type "python" :request "launch" :program (expand-file-name "~/git/Sodra.Common.FlightTower.Datafactory/ft_pipelines/main.py") :args ["-m" "wood_processing_e2e" "--config" "user_luca" ] ))
(dap-register-debug-template "dap-debug-script" dap-script-args) (dap-register-debug-template "dap-debug-test-at-point" dap-test-args) (dap-register-debug-template "flight-tower-mill" flight-tower-mill) (dap-register-debug-template "flight-tower-e2e" flight-tower-e2e) (dap-register-debug-template "flight-tower-calibration" flight-tower-calibration) (dap-register-debug-template "mill-data-factory" mill-data-factory) ;; bind the templates (lc/local-leader-keys :keymaps 'python-mode-map "d t" '((lambda () (interactive) (dap-debug dap-test-args)) :wk "test") "d s" '((lambda () (interactive) (dap-debug dap-script-args)) :wk "script") ) ) #+END_SRC
** Python :prog_python: :PROPERTIES: :CUSTOM_ID: h:541B5295-9C9C-4138-8A42-EA8DC9D4FD87 :header-args: :emacs-lisp :tangle ./lisp/init-prog-python.el :END: *** python mode :PROPERTIES: :CUSTOM_ID: h:95658AC9-ADFE-4134-81C4-DEC01069B716 :END: NOTE:
- In a python buffer use =run-python= to start an inferior python process or =,'=
- Use eval operator so eval lines with =grr=
#+BEGIN_SRC emacs-lisp
(use-package python-mode
:hook
((envrc-mode . (lambda ()
(when (executable-find "ipython")
(setq python-shell-interpreter (executable-find "ipython"))))))
:general
(lc/local-leader-keys
:keymaps 'python-mode-map
"'" 'run-python)
(python-mode-map
:states 'normal
"gz" nil
"C-j" nil)
(python-mode-map
:states 'insert
"TAB" 'lc/py-indent-or-complete)
:init
(setq python-indent-offset 0)
(defun lc/py-indent-or-complete ()
(interactive "")
(window-configuration-to-register py--windows-config-register)
(cond ((use-region-p)
(py-indent-region (region-beginning) (region-end)))
((or (bolp)
(member (char-before) (list 9 10 12 13 32 ?: ;; ([{
?) ?] ?}))
;; (not (looking-at "[ \t]$"))
)
(py-indent-line))
((comint-check-proc (current-buffer))
(ignore-errors (completion-at-point)))
(t
(completion-at-point))))
:config
(setq python-shell-interpreter-args "-i --simple-prompt --no-color-info"
python-shell-prompt-regexp "In \[[0-9]+\]: "
python-shell-prompt-block-regexp "\.\.\.\.: "
python-shell-prompt-output-regexp "Out\[[0-9]+\]: "
python-shell-completion-setup-code
"from IPython.core.completerlib import module_completion"
python-shell-completion-string-code
"';'.join(get_ipython().Completer.all_completions('''%s'''))\n")
)
#+END_SRC
*** lsp-pyright :PROPERTIES: :CUSTOM_ID: h:373160D0-6591-4D96-9928-33EE610CEACE :END: Here the configuration options: https://github.com/emacs-lsp/lsp-pyright#configuration #+BEGIN_SRC emacs-lisp (use-package lsp-pyright :init (setq lsp-pyright-typechecking-mode "basic") ;; too much noise in "real" projects :hook (python-mode . (lambda () (require 'lsp-pyright) (lsp-deferred)))) #+END_SRC
*** pytest :PROPERTIES: :CUSTOM_ID: h:8C50BED5-6727-41D9-83BE-E5ADB96D7C88 :END: #+begin_src emacs-lisp (use-package python-pytest :general (lc/local-leader-keys :keymaps 'python-mode-map "t" '(:ignore t :wk "test") "t d" '(python-pytest-dispatch :wk "dispatch") "t f" '(python-pytest-file :wk "file") "t t" '(python-pytest-function :wk "function")) :init (setq python-pytest-arguments '("--color" "--failed-first")) (defun lc/pytest-use-venv (orig-fun &rest args) (if-let ((python-pytest-executable (executable-find "pytest"))) (apply orig-fun args) (apply orig-fun args))) :config (advice-add 'python-pytest--run :around #'lc/pytest-use-venv) ) #+end_src
*** flycheck :PROPERTIES: :CUSTOM_ID: h:A98624AB-1B3D-47A2-873F-E961FDE431D9 :END: ~flycheck-verify-setup~ is your best friend.
#+begin_src emacs-lisp (use-package flycheck :hook ((lsp-mode . flycheck-mode) (envrc-mode . (lambda () (setq flycheck-python-flake8-executable (executable-find "python")) (setq flycheck-checker 'python-flake8) (setq flycheck-flake8rc ".flake8") ))) :init (setq flycheck-indication-mode 'right-fringe) ;; only check on save (setq flycheck-check-syntax-automatically '(mode-enabled save)) ) #+end_src
*** blacken :PROPERTIES: :CUSTOM_ID: h:2DC8F5D9-BD12-4CEA-9CBD-34B4CAC53495 :END: #+begin_src emacs-lisp (use-package blacken :general (lc/local-leader-keys :keymaps 'python-mode-map "=" '(blacken-buffer :wk "format")) ) #+end_src
*** csv mode :PROPERTIES: :CUSTOM_ID: h:A0F0925F-11FB-43A8-8E26-A068FD70D7D0 :END: #+begin_src emacs-lisp (use-package csv-mode :hook (csv-mode . lc/init-csv-mode) :general (lc/local-leader-keys :keymaps 'csv-mode-map :states 'normal "a" '(csv-align-fields :wk "align fields") "A" '(lc/csv-align-visible :wk "align fields, visible") "i" '(lc/init-csv-mode :wk "init csv mode") "u" '(csv-unalign-fields :wk "unalign fields") "s" '(csv-sort-fields :wk "sort fields") ";" '(lc/set-csv-semicolon-separator :wk "set semicolon sep") "," '(lc/reset-csv-separators :wk "set comma sep")) :init (defun lc/csv-align-visible (&optional arg) "Align visible fields" (interactive "P") (csv-align-fields nil (window-start) (window-end))) (defun lc/set-csv-semicolon-separator () (interactive) (customize-set-variable 'csv-separators '(";"))) (defun lc/reset-csv-separators () (interactive) (customize-set-variable 'csv-separators lc/default-csv-separators)) (defun lc/init-csv-mode () (interactive) (lc/set-csv-separators) (lc/csv-highlight) (call-interactively 'csv-align-fields)) :config (require 'cl) (require 'color) (defun lc/set-csv-separators () (interactive) (let* ((n-commas (count-matches "," (point-at-bol) (point-at-eol))) (n-semicolons (count-matches ";" (point-at-bol) (point-at-eol)))) (if ( ; < > n-commas n-semicolons) (customize-set-variable 'csv-separators '("," " ")) (customize-set-variable 'csv-separators '(";" " "))))) (defun lc/csv-highlight () (interactive) (font-lock-mode 1) (let* ((separator (string-to-char (car csv-separators))) (n (count-matches (string separator) (point-at-bol) (point-at-eol))) (colors (loop for i from 0 to 1.0 by (/ 2.0 n) collect (apply #'color-rgb-to-hex (color-hsl-to-rgb i 0.3 0.5))))) (loop for i from 2 to n by 2 for c in colors for r = (format "^\([^%c\n]+%c\)\{%d\}" separator separator i) do (font-lock-add-keywords nil `((,r (1 '(face (:foreground ,c))))))))) ) #+end_src
*** COMMENT flymake :PROPERTIES: :CUSTOM_ID: h:F49B684F-1911-45E1-99AB-79EB14913FFC :END: Disabled ~flymake~ as I can't find a way to make it work with ~flake8~ on a python project. Switched to ~flycheck~ instead. #+begin_src emacs-lisp (use-package flymake :straight (:type built-in) :hook ((emacs-lisp-mode . flymake-mode) (python-mode . (lambda () (when (executable-find "flake8") (require 'python) (setq python-flymake-command (executable-find "flake8")) (setq flymake-diagnostic-functions '(python-flymake t)) )))) :init ;; (setq python-flymake-command '("flake8" "--ignore=E402,F401" "-")) (setq flymake-fringe-indicator-position 'right-fringe) :general (general-nmap "] !" 'flymake-goto-next-error) (general-nmap "[ !" 'flymake-goto-prev-error) ) #+end_src
*** COMMENT auto-import :PROPERTIES: :CUSTOM_ID: h:CD1D1A97-50EC-4B72-814C-3BC0297C42B1 :END: #+begin_src emacs-lisp (use-package pyimport :general (lc/local-leader-keys :keymaps 'python-mode-map "i i" '(pyimport-insert-missing :wk "autoimport"))) #+end_src
*** COMMENT dash at point :PROPERTIES: :CUSTOM_ID: h:CAE53061-F38A-49C9-9256-2087E6D89052 :END: #+begin_src emacs-lisp (use-package dash-at-point :general (lc/local-leader-keys :keymaps 'python-mode-map "h" '(dash-at-point :wk "docs")) ) #+end_src
*** code-cells :PROPERTIES: :CUSTOM_ID: h:72656E4E-C0B1-49E4-92AB-961F08655435 :END: #+begin_src emacs-lisp (use-package code-cells :hook (python-mode . code-cells-mode) :config (let ((map code-cells-mode-map)) (define-key map [remap evil-search-next] (code-cells-speed-key 'code-cells-forward-cell)) ;; n (define-key map [remap evil-paste-after] (code-cells-speed-key 'code-cells-backward-cell)) ;; p (define-key map [remap evil-backward-word-begin] (code-cells-speed-key 'code-cells-eval-above)) ;; b (define-key map [remap evil-forward-word-end] (code-cells-speed-key 'code-cells-eval)) ;; e (define-key map [remap evil-jump-forward] (code-cells-speed-key 'outline-cycle))) ;; TAB ) #+end_src
** Jupyter :prog_jupyter: :PROPERTIES: :CUSTOM_ID: h:63CBAB4B-1BB6-4D26-BA0D-D2A1E0B8BC6F :header-args: :emacs-lisp :tangle ./lisp/init-prog-jupyter.el :END: *** jupyter :PROPERTIES: :CUSTOM_ID: h:388AA3FF-BC18-4628-93DC-9292B568AE9F :END: ~zmq~ installation:
- Need to have ~automake~, ~autoconf~
- In ~straight/build/zmq/src~ run ~autoreconf -i~
- In ~straight/build/zmq~ run ~make~
~emacs-zmq~ installation:
-
In ~straight/build/emacs-zmq~ run ~wget https://github.com/nnicandro/emacs-zmq/releases/download/v0.10.10/emacs-zmq-x86_64-apple-darwin17.4.0.tar.gz~
-
Then ~tar -xzf emacs-zmq-x86_64-apple-darwin17.4.0.tar.gz~
-
Finally ~cp emacs-zmq-x86_64-apple-darwin17.4.0/emacs-zmq.so emacs-zmq.dylib~
-
In the REPL you can use =M-p= / =M-n= to navigate previous prompts
#+begin_src emacs-lisp
(use-package jupyter
:straight (:no-native-compile t :no-byte-compile t) ;; otherwise we get jupyter-channel void
:general
(lc/local-leader-keys
:keymaps '(jupyter-org-interaction-mode-map jupyter-repl-interaction-mode-map)
:states 'normal
"e" '(:ignore true :wk "eval")
"e e" '(jupyter-eval-line-or-region :wk "line")
"e d" '(jupyter-eval-defun :wk "defun")
"e b" '((lambda () (interactive) (lc/jupyter-eval-buffer)) :wk "buffer")
"e r" '(jupyter-eval-remove-overlays :wk "remove overlays")
"k" '(:ignore true :wk "kernel")
"k d" '(lc/kill-repl-kernel :wk "kill")
"k i" '(jupyter-org-interrupt-kernel :wk "interrupt")
"k r" '(jupyter-repl-restart-kernel :wk "restart")
"J" '(lc/jupyter-repl :wk "jupyter REPL")
)
(lc/local-leader-keys
:keymaps '(jupyter-org-interaction-mode-map jupyter-repl-interaction-mode-map)
:states 'visual
"e" '(jupyter-eval-line-or-region :wk "region")
)
:init
(setq jupyter-repl-prompt-margin-width 4)
(setq jupyter-eval-use-overlays t)
(defun jupyter-command-venv (&rest args)
"This overrides jupyter-command to use the virtualenv's jupyter"
(let ((jupyter-executable (executable-find "jupyter")))
(with-temp-buffer
(when (zerop (apply #'process-file jupyter-executable nil t nil args))
(string-trim-right (buffer-string))))))
(defun lc/jupyter-eval-buffer ()
"Send the contents of BUFFER using jupyter-current-client'." (interactive) (jupyter-eval-string (jupyter-load-file-code (buffer-file-name)))) (defun lc/jupyter-repl () "If a buffer is already associated with a jupyter buffer, then pop to it. Otherwise start a jupyter kernel." (interactive) (if (bound-and-true-p jupyter-current-client) (jupyter-repl-pop-to-buffer) (call-interactively 'jupyter-repl-associate-buffer))) (defun lc/kill-repl-kernel () "Kill repl buffer associated with current jupyter kernel" (interactive) (if jupyter-current-client (jupyter-with-repl-buffer jupyter-current-client (kill-buffer (current-buffer))) (error "Buffer not associated with a REPL, see
jupyter-repl-associate-buffer'"))
)
(advice-add 'jupyter-command :override #'jupyter-command-venv)
;; TODO refactor to avoid duplication of dap code
(setq lc/jupyter-temp-dataframe-buffer "inspect-df")
(setq lc/jupyter-temp-dataframe-path "~/tmp-inspect-df.csv")
(defun lc/jupyter-inspect-df (dataframe)
"Save the df to csv and open the file with csv-mode"
(interactive (list (read-from-minibuffer "DataFrame: " (evil-find-symbol nil))))
(jupyter-eval (format "%s.to_csv('%s', index=False)" dataframe lc/jupyter-temp-dataframe-path))
(find-file-other-window lc/jupyter-temp-dataframe-path)
)
)
#+end_src
*** ob-jupyter :PROPERTIES: :CUSTOM_ID: h:600809B3-9B92-43F9-9A99-3D007CEE044D :END: Note:
- We can only load ~ob-jupyter~ when we have ~jupyter~ on our ~PATH~.
- We assume ~jupyter~ is always installed in a virtual env associated with an ~.envrc~ file
- We load jupyter when we activate ~envrc-mode~ if ~jupyter~ is available
- We need to add a =:session= to each code block
- We can use the snippet =+ha=
- Also use ~:display plain~
- First install ~zmq~ . Then run ~envrc-allow~ and then ~lc/load-ob-jupyter~ to load it
- Use ~toggle-truncate-lines~ when printing dataframes
When exporting ~.org~ file to HTML, we can add this header: #+begin_src org ,#+HTML_HEAD: #+end_src
We can avoid evaluation of code with: #+begin_quote #+PROPERTY: header-args :eval never-export #+end_quote
#+begin_src emacs-lisp (use-package jupyter :straight (:no-native-compile t :no-byte-compile t) ;; otherwise we get jupyter-channel void :general (lc/local-leader-keys :keymaps 'org-mode-map "=" '((lambda () (interactive) (jupyter-org-insert-src-block t nil)) :wk "block below") "," 'org-ctrl-c-ctrl-c "m" '(jupyter-org-merge-blocks :wk "merge") "+" '(jupyter-org-insert-src-block :wk "block above") "?" '(jupyter-inspect-at-point :wk "inspect") "x" '(jupyter-org-kill-block-and-results :wk "kill block")) :hook ((jupyter-org-interaction-mode . (lambda () (lc/add-local-electric-pairs '((?' . ?'))))) (jupyter-repl-persistent-mode . (lambda () ;; we activate org-interaction-mode ourselves (when (derived-mode-p 'org-mode) ;; (setq-local company-backends '((company-capf))) (setq-local evil-lookup-func #'jupyter-inspect-at-point) (jupyter-org-interaction-mode)))) (envrc-mode . lc/load-ob-jupyter)) :init (setq org-babel-default-header-args:jupyter-python '((:async . "yes") (:pandoc t) (:kernel . "python3"))) (setq org-babel-default-header-args:jupyter-R '((:pandoc t) (:async . "yes") (:kernel . "ir"))) (defun lc/org-load-jupyter () (org-babel-do-load-languages 'org-babel-load-languages (append org-babel-load-languages '((jupyter . t))))) (defun lc/load-ob-jupyter () ;; only try to load in org-mode (when (derived-mode-p 'org-mode) ;; skip if already loaded (unless (member '(jupyter . t) org-babel-load-languages) ;; only load if jupyter is available (when (executable-find "jupyter") (lc/org-load-jupyter))))) :config (cl-defmethod jupyter-org--insert-result (_req context result) (let ((str (org-element-interpret-data (jupyter-org--wrap-result-maybe context (if (jupyter-org--stream-result-p result) (thread-last result jupyter-org-strip-last-newline jupyter-org-scalar) result))))) (if (< (length str) 100000) ;; > (insert str) (insert (format ": Result was too long! Length was %d" (length str))))) (when (/= (point) (line-beginning-position)) ;; Org objects such as file links do not have a newline added when ;; converting to their string representation by ;; `org-element-interpret-data' so insert one in these cases. (insert "\n"))) ;;Remove text/html since it's not human readable ;; (delete :text/html jupyter-org-mime-types) ;; (with-eval-after-load 'org-src ;; (add-to-list 'org-src-lang-modes '("jupyter-python" . python)) ;; (add-to-list 'org-src-lang-modes '("jupyter-R" . R))) ) #+end_src
** R :prog_R: :PROPERTIES: :CUSTOM_ID: h:74BD1AAB-0C5A-4BF2-927E-D11FEEA4C08A :header-args: :emacs-lisp :tangle ./lisp/init-prog-r.el :END: *** ess :PROPERTIES: :CUSTOM_ID: h:06BE4AA2-688D-4748-BF6D-9656EF6ED767 :END: #+begin_src emacs-lisp (use-package ess :general (lc/local-leader-keys :keymaps 'ess-r-mode-map :states 'normal "R" '(R :wk "R") "q" '(ess-quit :wk "quit") "RET" '(ess-eval-line-visibly-and-step :wk "line and step") ;; debug "d b" '(ess-bp-set :wk "breakpoint") "d n" '(ess-debug-command-next :wk "next") "d q" '(ess-debug-command-quit :wk "quit") "d c" '(ess-bp-next :wk "continue") "d f" '(ess-debug-flag-for-debugging :wk "flag function") "d F" '(ess-debug-unflag-for-debugging :wk "unflag function") "d p" '(ess-debug-goto-debug-point :wk "go to point") ;; "e l" '(ess-eval-line :wk "eval line") "e p" '(ess-eval-paragraph :wk "paragraph") "e f" '(ess-eval-function :wk "function") "h" '(:keymap ess-doc-map :which-key "help") ;; "h" '(ess-display-help-on-object :wk "help") ) (lc/local-leader-keys :keymaps 'ess-r-mode-map :states 'visual "RET" '(ess-eval-region-or-line-visibly-and-step :wk "line and step")) :init (setq ess-eval-visibly 'nowait) (setq ess-R-font-lock-keywords '((ess-R-fl-keyword:keywords . t) (ess-R-fl-keyword:constants . t) (ess-R-fl-keyword:modifiers . t) (ess-R-fl-keyword:fun-defs . t) (ess-R-fl-keyword:assign-ops . t) (ess-R-fl-keyword:%op% . t) (ess-fl-keyword:fun-calls . t) (ess-fl-keyword:numbers . t) (ess-fl-keyword:operators . t) (ess-fl-keyword:delimiters . t) (ess-fl-keyword:= . t) (ess-R-fl-keyword:F&T . t))) ;; (setq ess-first-continued-statement-offset 2 ;; ess-continued-statement-offset 0 ;; ess-expression-offset 2 ;; ess-nuke-trailing-whitespace-p t ;; ess-default-style 'DEFAULT) ;; (setq ess-r-flymake-linters "line_length_linter = 120") ) #+end_src
*** ESS data viewer :PROPERTIES: :CUSTOM_ID: h:9838BF54-50A8-4E07-8639-184253159FC3 :END: #+begin_src emacs-lisp (use-package ess-view-data :general (lc/local-leader-keys :keymaps 'ess-r-mode-map :states 'normal "hd" 'ess-R-dv-pprint "ht" 'ess-R-dv-ctable )) #+end_src
*** enable lsp-mode :PROPERTIES: :CUSTOM_ID: h:4492B9C6-4E27-4A4D-B927-13D3DDD44706 :END: #+begin_src emacs-lisp (use-package lsp-mode :hook (ess-r-mode . lsp-deferred) ) #+end_src
** emacs-lisp :prog_elisp: :PROPERTIES: :CUSTOM_ID: h:6956B874-2F21-42A1-8343-C4BF7B1123C9 :header-args: :emacs-lisp :tangle ./lisp/init-prog-elisp.el :END: *** emacs-lisp-mode :PROPERTIES: :CUSTOM_ID: h:96EF892B-7F9F-4F69-B72C-C01F011A054D :END: #+begin_src emacs-lisp (use-package emacs :straight (:type built-in) :general (general-nmap :keymaps 'emacs-lisp-mode-map :states 'normal "gr" nil) ;; interferes with eval-operator ) #+end_src
*** evil-lisp state :PROPERTIES: :CUSTOM_ID: h:C59E740E-F00B-4D2F-B5A3-36C3B99BCD5E :END: NOTE:
- Wrap with =SPC l w=
- Raise with =SPC l r=
- Enter ~lisp-state~ with =SPC l .=
- Navigate symbols with =j= and =k=
- Navigate forms with =h= and =l=
- Go to parent sexp with =U=
#+begin_src emacs-lisp (use-package evil-lisp-state :after evil :demand :init (setq evil-lisp-state-enter-lisp-state-on-command nil) (setq evil-lisp-state-global t) ;; (setq evil-lisp-state-major-modes '(org-mode emacs-lisp-mode clojure-mode clojurescript-mode lisp-interaction-mode)) :config (evil-lisp-state-leader "SPC l") ) #+end_src
*** eros: results in overlays :PROPERTIES: :CUSTOM_ID: h:309D0DC9-29FF-46E8-A98A-F2CD6CCEB12A :END: #+begin_src emacs-lisp (use-package eros :hook ((emacs-lisp-mode org-mode lisp-interaction-mode) . eros-mode) :general (lc/local-leader-keys :keymaps '(org-mode-map emacs-lisp-mode-map lisp-interaction-mode-map) :states 'normal "e l" '(eros-eval-last-sexp :wk "last sexp") ;; "e d" '((lambda () (interactive) (eros-eval-defun t)) :wk "defun") "e b" '(eval-buffer :wk "buffer")) (lc/local-leader-keys :keymaps '(org-mode-map emacs-lisp-mode-map lisp-interaction-mode-map) :states 'visual ;; "e" '((lambda (start end) ;; (interactive (list (region-beginning) (region-end))) ;; (eval-region start end t)) ;; :wk "region") ;; "e" '((lambda (start end) ;; (interactive (list (region-beginning) (region-end))) ;; (eros--eval-overlay ;; (eval-region start end) ;; end)) ;; :wk "region") "e" '(eros-eval-region :wk "region") ) :init (defun eros-eval-region (start end) (interactive "r") (eros--eval-overlay (string-trim (with-output-to-string (eval-region start end standard-output))) (max (point) (mark)))) ) #+end_src
** Nix :prog_nix: :PROPERTIES: :CUSTOM_ID: h:88E57F7B-DA1F-4BC1-BAD3-5BA459D054B7 :header-args: :emacs-lisp :tangle ./lisp/init-prog-nix.el :END: *** nix mode :PROPERTIES: :CUSTOM_ID: h:D9238686-7FDE-406A-BAE1-DF8293A02647 :END: #+begin_src emacs-lisp (use-package nix-mode :mode "\.nix\'") #+end_src
** Clojure :prog_clojure: :PROPERTIES: :CUSTOM_ID: h:2A226DAE-B566-464B-AF20-4BE86E554DC6 :header-args: :emacs-lisp :tangle ./lisp/init-prog-clojure.el :END: *** Clojure mode :PROPERTIES: :CUSTOM_ID: h:C757468F-281B-4A9D-84AF-26B9B656F01C :END: #+begin_src emacs-lisp (use-package clojure-mode :mode "\.clj$" :init (setq clojure-align-forms-automatically t) ) #+end_src
*** clojure-lsp :PROPERTIES: :CUSTOM_ID: h:1613B1A4-02B4-4EB0-AC4B-53FA0BF3CF60 :END:
#+begin_src emacs-lisp (use-package clojure-mode :hook ((clojure-mode clojurescript-mode) . (lambda () (setq-local lsp-enable-indentation nil ; cider indentation lsp-enable-completion-at-point nil ; cider completion ) (lsp-deferred))) ) #+end_src
*** Cider :PROPERTIES: :CUSTOM_ID: h:3D8B9BAA-05E9-4F0B-8988-4B56882BB607 :END: #+begin_src emacs-lisp (use-package cider :hook ((cider-repl-mode . evil-normalize-keymaps) (cider-mode . (lambda () (setq-local evil-lookup-func #'cider-doc))) (cider-mode . eldoc-mode)) :general (lc/local-leader-keys :keymaps 'clojure-mode-map "c" '(cider-connect-clj :wk "connect") "C" '(cider-connect-cljs :wk "connect (cljs)") "j" '(cider-jack-in :wk "jack in") "J" '(cider-jack-in-cljs :wk "jack in (cljs)") "d d" 'cider-debug-defun-at-point "e b" 'cider-eval-buffer "e l" 'cider-eval-last-sexp "e L" 'cider-pprint-eval-last-sexp-to-comment "e d" '(cider-eval-defun-at-point :wk "defun") "e D" 'cider-pprint-eval-defun-to-comment "h" 'cider-clojuredocs-web "K" 'cider-doc "q" '(cider-quit :qk "quit") ) (lc/local-leader-keys :keymaps 'clojure-mode-map :states 'visual "e" 'cider-eval-region) :init (setq nrepl-hide-special-buffers t) (setq nrepl-sync-request-timeout nil) (setq cider-repl-display-help-banner nil) ) #+end_src
*** COMMENT Eval sexp at point :PROPERTIES: :CUSTOM_ID: h:D23F2C41-0162-4E11-A052-17B37B48AF2D :END: #+begin_src emacs-lisp (use-package cider :init (defun mpereira/cider-eval-sexp-at-point (&optional output-to-current-buffer) "Evaluate the expression around point. If invoked with OUTPUT-TO-CURRENT-BUFFER, output the result to current buffer." (interactive "P") (save-excursion (goto-char (- (cadr (cider-sexp-at-point 'bounds)) 1)) (cider-eval-last-sexp output-to-current-buffer))) ) #+end_src
*** ob-clojure :PROPERTIES: :CUSTOM_ID: h:3B21567B-6B7B-4747-B44B-AA2480FA49E5 :END: #+begin_src emacs-lisp (use-package org :config (require 'ob-clojure) (setq org-babel-clojure-backend 'cider) ) #+end_src
*** aggressive-indent :PROPERTIES: :CUSTOM_ID: h:804F32D8-081E-427C-8949-90D3ECF5879F :END: #+begin_src emacs-lisp ;; keep the file indented (use-package aggressive-indent :hook ((clojure-mode . aggressive-indent-mode) (emacs-lisp-mode . aggressive-indent-mode))) #+end_src
** markdown :prog_markdown: :PROPERTIES: :CUSTOM_ID: h:C643DC36-8F5E-40E4-B8BB-126F341491FD :header-args: :emacs-lisp :tangle ./lisp/init-prog-markdown.el :END: #+begin_src emacs-lisp (use-package markdown-mode :commands (markdown-mode gfm-mode) :mode (("README\.md\'" . gfm-mode) ("\.md\'" . markdown-mode) ("\.markdown\'" . markdown-mode)) :init (setq markdown-command "multimarkdown") (setq markdown-fontify-code-blocks-natively t) ) #+end_src
** yaml mode :prog_markdown: :PROPERTIES: :CUSTOM_ID: h:351ADC7D-38F2-47FF-9D9B-1C3F2F7B61D3 :header-args: :emacs-lisp :tangle ./lisp/init-prog-markdown.el :END: #+begin_src emacs-lisp (use-package yaml-mode :mode ((rx ".yml" eos) . yaml-mode)) #+end_src
** toml mode :prog_markdown: :PROPERTIES: :CUSTOM_ID: h:4474E2AE-F934-48CD-ACB8-5729B7C26F0A :header-args: :emacs-lisp :tangle ./lisp/init-prog-markdown.el :END: #+begin_src emacs-lisp (use-package toml-mode :mode "\.toml\'") #+end_src
** stan mode :PROPERTIES: :CUSTOM_ID: h:33FE46F3-DB69-4F9F-B40B-9E1C970040D5 :header-args: :emacs-lisp :tangle ./lisp/init-prog-stan.el :END: #+begin_src emacs-lisp (use-package stan-mode :mode ("\.stan\'" . stan-mode) :hook (stan-mode . stan-mode-setup) ;; :config ;; The officially recommended offset is 2. (setq stan-indentation-offset 2)) #+end_src
- Gimmicks :PROPERTIES: :CUSTOM_ID: h:7D94EA42-5F85-4E18-9029-19BAD69FBF85 :END: ** web browser :extra_web: :PROPERTIES: :CUSTOM_ID: h:6B214C3A-22E3-47D0-9DD7-F379E07CF960 :header-args: :emacs-lisp :tangle ./lisp/init-extra-web.el :END: Use =SPC x x= to search the web! You can also visit a URL in the buffer. With the web browser open, scroll with =j= / =k= . To visit a link, =SPC x l= #+begin_src emacs-lisp (use-package xwwp :straight (xwwp :type git :host github :repo "canatella/xwwp") :commands (xwwp) :general (lc/leader-keys "x x" '((lambda () (interactive) (let ((current-prefix-arg 4)) ;; emulate C-u universal arg (call-interactively 'xwwp))) :wk "search or visit") "x l" '(xwwp-follow-link :wk "link") "x b" '(xwidget-webkit-back :wk "back")) ;; :custom ;; (setq xwwp-follow-link-completion-system 'ivy) ;; :bind (:map xwidget-webkit-mode-map ;; ("v" . xwwp-follow-link)) ) #+end_src
** elfeed :extra_rss: :PROPERTIES: :CUSTOM_ID: h:B0653EBC-9E48-4E3D-86A3-34E7450B4F03 :header-args: :emacs-lisp :tangle ./lisp/init-extra-rss.el :END: NOTE:
- Search with =s=
- Open in browser with =S-RET=
- Open in ~xwwp~ with =x=
#+begin_src emacs-lisp (use-package elfeed :straight (elfeed :type git :host github :repo "skeeto/elfeed") :hook (elfeed-search-mode . elfeed-update) :general (lc/leader-keys "s r" '(elfeed :wk "elfeed")) (general-nmap :keymaps 'elfeed-search-mode-map "x" 'lc/elfeed-xwwp-open) :init (defun lc/elfeed-xwwp-open (&optional use-generic-p) "open with eww" (interactive "P") (let ((entries (elfeed-search-selected))) (cl-loop for entry in entries do (elfeed-untag entry 'unread) when (elfeed-entry-link entry) do (xwwp it)) (mapc #'elfeed-search-update-entry entries) (unless (use-region-p) (forward-line)))) :config (setq elfeed-feeds'(("https://www.reddit.com/r/emacs.rss?sort=new" reddit emacs) ("http://emacsredux.com/atom.xml" emacs) ("http://irreal.org/blog/?tag=emacs&feed=rss2" emacs) ("https://www.reddit.com/search.rss?q=url%3A%28youtu.be+OR+youtube.com%29&sort=top&t=week&include_over_18=1&type=link" reddit youtube popular)))) #+end_src
** COMMENT clip2org :PROPERTIES: :CUSTOM_ID: h:6A493FA9-FC60-4E69-98F0-ADF2BDE452D2 :END: #+begin_src emacs-lisp (use-package clip2org :straight (clip2org :type git :host github :repo "kungsgeten/clip2org" :branch "master") :commands (clip2org) :init (setq clip2org-clippings-file "/Users/cambiaghiluca/Desktop/clippings.txt") (setq clip2org-include-date nil) ) #+end_src
** COMMENT reddit :PROPERTIES: :CUSTOM_ID: h:B616A404-0B56-4C56-9A8C-343E212F536A :END: #+begin_src emacs-lisp (use-package md4rd :general (lc/leader-keys "s r" '(md4rd :wk "reddit")) :init (setq md4rd-subs-active '(emacs apple clojure MachineLearning)) :config (add-hook 'md4rd-mode-hook 'md4rd-indent-all-the-lines) (require 'cl) ) #+end_src
** COMMENT dash docsets :PROPERTIES: :CUSTOM_ID: h:F60C9AFB-AF3C-434D-B2C9-14741185D0DB :END:
- ~dash-docs-install-docset~
- ~dash-docs-search~
#+begin_src emacs-lisp (use-package dash-docs :init ;; (setq dash-docs-browser-func 'eww) (setq dash-docs-common-docsets '("Pandas")) ) #+end_src
#+begin_src emacs-lisp (use-package dash-at-point :general (lc/leader-keys "s d" '(dash-at-point :which-key "search dash")) ) #+end_src
- Provide modules :PROPERTIES: :CUSTOM_ID: h:754DFB20-B2AB-4750-9BDA-D24E8014C504 :END: ** init-core :PROPERTIES: :CUSTOM_ID: h:24A7FE78-E6B9-4C81-A2BE-6A049A8209AD :header-args: :emacs-lisp :tangle ./lisp/init-core.el :END: #+begin_src emacs-lisp (provide 'init-core) ;;; init-core.el ends here #+end_src
** init-ui-extras :PROPERTIES: :CUSTOM_ID: h:E80DEB4B-6AC9-415D-AF36-0044479D1B5A :header-args: :emacs-lisp :tangle ./lisp/init-ui-extra.el :END: #+begin_src emacs-lisp (provide 'init-ui-extra) ;;; init-ui-extra.el ends here #+end_src
** init-org-export :PROPERTIES: :CUSTOM_ID: h:A646A19B-12BC-4B95-A592-BCB640E10659 :header-args: :emacs-lisp :tangle ./lisp/init-org-export.el :END: #+begin_src emacs-lisp (provide 'init-org-export) ;;; init-org-export.el ends here #+end_src
** init-prog-tree-sitter :PROPERTIES: :CUSTOM_ID: h:A646A19B-12BC-4B95-A592-BCB640E10659 :header-args: :emacs-lisp :tangle ./lisp/init-prog-tree-sitter.el :END: #+begin_src emacs-lisp (provide 'init-prog-tree-sitter) ;;; init-prog-tree-sitter.el ends here #+end_src
** init-prog-nix :PROPERTIES: :CUSTOM_ID: h:E80DEB4B-6AC9-415D-AF36-0044479D1B5A :header-args: :emacs-lisp :tangle ./lisp/init-prog-nix.el :END: #+begin_src emacs-lisp (provide 'init-prog-nix) ;;; init-prog-nix.el ends here #+end_src
** init-prog-lsp :PROPERTIES: :CUSTOM_ID: h:E80DEB4B-6AC9-415D-AF36-0044479D1B5A :header-args: :emacs-lisp :tangle ./lisp/init-prog-lsp.el :END: #+begin_src emacs-lisp (provide 'init-prog-lsp) ;;; init-prog-lsp.el ends here #+end_src
** init-prog-python :PROPERTIES: :CUSTOM_ID: h:E80DEB4B-6AC9-415D-AF36-0044479D1B5A :header-args: :emacs-lisp :tangle ./lisp/init-prog-python.el :END: #+begin_src emacs-lisp (provide 'init-prog-python) ;;; init-prog-python.el ends here #+end_src
** init-prog-jupyter :PROPERTIES: :CUSTOM_ID: h:FD3CCF1B-8F23-4863-8592-0AF46542AB21 :header-args: :emacs-lisp :tangle ./lisp/init-prog-jupyter.el :END: #+begin_src emacs-lisp (provide 'init-prog-jupyter) ;;; init-prog-jupyter.el ends here #+end_src
** init-org-roam :PROPERTIES: :CUSTOM_ID: h:8C169B84-C560-42FB-8A12-F052E4685ECB :header-args: :emacs-lisp :tangle ./lisp/init-org-roam.el :END: #+begin_src emacs-lisp (provide 'init-org-roam) ;;; init-org-roam.el ends here #+end_src
** init-prog-elisp :PROPERTIES: :CUSTOM_ID: h:6F1A571B-D934-4CF8-BE66-3363F695B7B5 :header-args: :emacs-lisp :tangle ./lisp/init-prog-elisp.el :END: #+begin_src emacs-lisp (provide 'init-prog-elisp) ;;; init-org-prog-elisp.el ends here #+end_src
** init-prog-r :PROPERTIES: :CUSTOM_ID: h:A480FCCD-E2E4-4BBA-ACA1-DEF5EFDC1D03 :header-args: :emacs-lisp :tangle ./lisp/init-prog-r.el :END: #+begin_src emacs-lisp (provide 'init-prog-r) ;;; init-org-prog-r.el ends here #+end_src
** init-prog-clojure :PROPERTIES: :CUSTOM_ID: h:39D468C7-8D6B-4F16-A3FE-8675917B3DBD :header-args: :emacs-lisp :tangle ./lisp/init-prog-clojure.el :END: #+begin_src emacs-lisp (provide 'init-prog-clojure) ;;; init-org-prog-clojure.el ends here #+end_src
** init-prog-vterm :PROPERTIES: :CUSTOM_ID: h:EE92BA80-1F88-4D69-A45C-69268595FA71 :header-args: :emacs-lisp :tangle ./lisp/init-prog-vterm.el :END: #+begin_src emacs-lisp (provide 'init-prog-vterm) ;;; init-prog-vterm.el ends here #+end_src
** init-prog-markdown :PROPERTIES: :CUSTOM_ID: h:B315364E-ECF0-4ABC-9ACB-7546F6BB734C :header-args: :emacs-lisp :tangle ./lisp/init-prog-markdown.el :END: #+begin_src emacs-lisp (provide 'init-prog-markdown) ;;; init-prog-markdown.el ends here #+end_src
** init-prog-stan :PROPERTIES: :CUSTOM_ID: h:B315364E-ECF0-4ABC-9ACB-7546F6BB734C :header-args: :emacs-lisp :tangle ./lisp/init-prog-stan.el :END: #+begin_src emacs-lisp (provide 'init-prog-stan) ;;; init-prog-stan.el ends here #+end_src
** init-extra-focus :PROPERTIES: :header-args: :emacs-lisp :tangle ./lisp/init-extra-focus.el :CUSTOM_ID: h:E8D67694-4B23-47E2-800B-10136B4D8F2A :END: #+begin_src emacs-lisp (provide 'init-extra-focus) ;;; init-org-extra-focus.el ends here #+end_src
** init-extra-web :PROPERTIES: :CUSTOM_ID: h:11871421-6FA2-4450-AA35-B779A525FE69 :header-args: :emacs-lisp :tangle ./lisp/init-extra-web.el :END: #+begin_src emacs-lisp (provide 'init-extra-web) ;;; init-org-extra-web.el ends here #+end_src
** init-extra-rss :PROPERTIES: :CUSTOM_ID: h:A8F1EDE6-D506-49E6-A459-3AF50486BC89 :header-args: :emacs-lisp :tangle ./lisp/init-extra-rss.el :END: #+begin_src emacs-lisp (provide 'init-extra-rss) ;;; init-org-extra-rss.el ends here #+end_src
** init-extras :PROPERTIES: :CUSTOM_ID: h:E80DEB4B-6AC9-415D-AF36-0044479D1B5A :header-args: :emacs-lisp :tangle ./lisp/init-extra.el :END: #+begin_src emacs-lisp (provide 'init-extra) ;;; init-extra.el ends here #+end_src
- COMMENT to add / to fix :PROPERTIES: :CUSTOM_ID: h:742F97D8-9FC2-4ED4-9985-A23192D75550 :END: ** To add :PROPERTIES: :CUSTOM_ID: h:167C14F0-55E7-4524-98BC-1C605BA44337 :END: *** Improve LaTeX setup :PROPERTIES: :CUSTOM_ID: h:10F1C33B-B19C-4769-895D-2F81411D18EA :END: https://gist.github.com/bigodel/56a4627afdfe9ad28f6dcc68b89a97f8 *** eval region in org :PROPERTIES: :CUSTOM_ID: h:A26EC598-6EA3-4CEB-AB36-8C417E385F38 :END: #+begin_src emacs-lisp (defun my/ess-eval () (interactive) (let* ((buffst)) (if (string-equal ess-language "SAS") (progn (if (and transient-mark-mode mark-active) (setq buffst (buffer-substring-no-properties (region-beginning) (region-end))) (setq buffst (buffer-substring-no-properties (beginning-of-line) (end-of-line)))) (save-window-excursion (switch-to-buffer "iESS[SAS]") (goto-char (point-max)) (comint-send-input) (goto-char (point-max)) (insert buffst) (comint-send-input) )) (progn (if (and transient-mark-mode mark-active) (call-interactively 'ess-eval-region) (call-interactively 'ess-eval-line-and-step)) )))) #+end_src
*** python: python docstrings :PROPERTIES: :CUSTOM_ID: h:5ED70817-7A77-4C7D-91E5-4CECC5E00990 :END:
- Have a look here: https://www.reddit.com/r/emacs/comments/lgqqsu/automatic_python_docstring_generation/
#+begin_src emacs-lisp (use-package docstr :straight (:host github :repo "jcs-elpa/docstr") :hook (after-init . global-docstr-mode) :config (cl-pushnew '(rustic-mode . docstr-writers-rust) docstr-writers-alist :test #'equal) (cl-pushnew '("/" . docstr-trigger-rust) docstr-trigger-alist :test #'equal)) #+end_src
*** projectile: Switch to ~project.el~ :PROPERTIES: :CUSTOM_ID: h:779BF318-A030-42EC-A00A-BAEE5CDB5A95 :END:
- Start here: https://protesilaos.com/dotemacs/#h:7862f39e-aed0-4d02-9f1e-60c4601a9734
- Then here: https://github.com/CIAvash/persp-mode-project-bridge
- ACTUALLY here: https://github.com/mclear-tools/tabspaces *** org-tree-slide: Switch from ~org-tree-slide~ to ~org-present~ :PROPERTIES: :CUSTOM_ID: h:36CDF8EA-BA0B-4BE1-994A-8A4FC8D6FCE1 :END: https://github.com/daviwil/emacs-from-scratch/blob/master/show-notes/Emacs-Tips-04.org *** jupyter: see dataframe in csv-mode :PROPERTIES: :CUSTOM_ID: h:97388CDF-A4DD-413E-8124-1D61EBDEFC5E :END: *** jupyter: kill kernel associated with buffer :PROPERTIES: :CUSTOM_ID: h:5D358503-AB43-4358-9069-536613B5DE60 :END: ** To fix :PROPERTIES: :CUSTOM_ID: h:92086A48-355B-426E-AB82-DB73FAA11A1C :END: *** org-html-themify: Can't export both light and dark themes, one of the two has wrong rainbow delimiters :PROPERTIES: :CUSTOM_ID: h:6E70D3BF-8DDD-429F-92B8-BCBFCB42F94C :END: *** org-html-themify: Can't export twice in a row :PROPERTIES: :CUSTOM_ID: h:5F766A45-274C-464F-AF6E-C7BB4BB17BC8 :END:
- COMMENT Local variables :PROPERTIES: :CUSTOM_ID: h:8CE072CD-CA85-4E53-B672-E0AC74E4E4EC :END: