diff --git a/.spacemacs b/.spacemacs index 67c3c4c..00dd7de 100644 --- a/.spacemacs +++ b/.spacemacs @@ -121,7 +121,7 @@ This function is called at the very end of Spacemacs initialization." '(objed-cursor-color "#ff6c6b") '(org-export-headline-levels 4) '(package-selected-packages - '(org-treeusage caddyfile-mode org-ref lsp-dart mu4e-maildirs-extension mu4e-alert helm-mu xkcd vmd-mode visual-fill-column typit mmt sudoku restclient-helm pony-mode pacmacs ox-reveal outorg ob-restclient ob-http meson-mode ibuffer-projectile lv helm-w3m w3m graphviz-dot-mode flycheck-gometalinter transient ess-smart-equals ess-R-data-view ctable ess julia-mode eshell-git-prompt emoji-cheat-sheet-plus edit-indirect dockerfile-mode docker docker-tramp company-restclient restclient know-your-http-well company-quickhelp company-emoji company-emacs-eclim eclim atomic-chrome websocket 2048-game ox-gfm slime-company slime common-lisp-snippets erlang insert-shebang fish-mode company-shell faceup racket-mode treepy graphql yapfify yaml-mode xterm-color web-beautify twittering-mode toml-mode tagedit stickyfunc-enhance smeargle slim-mode shell-pop selectric-mode scss-mode sass-mode ranger rainbow-identifiers pytest pyenv-mode py-isort pug-mode plantuml-mode phpunit phpcbf php-auto-yasnippets pdf-tools tablist ox-pandoc orgit org-present org-pomodoro alert log4e gntp ob-elixir multi-term markdown-toc magit-gitflow magit-gh-pulls livid-mode live-py-mode json-snatcher js2-refactor js-doc htmlize hlint-refactor hindent helm-pydoc helm-hoogle helm-gitignore helm-css-scss haskell-snippets haml-mode gnuplot glsl-mode gitignore-mode github-search github-clone github-browse-file gitconfig-mode gitattributes-mode git-messenger gist gh marshal logito pcache ht gh-md flyspell-correct-helm flyspell-correct flycheck-rust pos-tip flycheck-mix flycheck-credo eshell-z eshell-prompt-extras esh-help drupal-mode disaster cython-mode dash-functional tern company-ghci company-ghc ghc color-identifiers-mode cmm-mode clang-format cargo auto-dictionary alchemist modern-cpp-font-lock yasnippet-snippets x86-lookup web-mode srefactor racer pyvenv pip-requirements pandoc-mode org-projectile org-category-capture org-mime org-download nasm-mode json-reformat intero imenu-list hy-mode git-timemachine git-link geiser flycheck-pos-tip flycheck-haskell evil-magit emmet-mode cmake-mode anaconda-mode rust-mode elixir-mode flycheck haskell-mode multiple-cursors skewer-mode simple-httpd markdown-mode magit magit-popup git-commit ghub with-editor pythonic emms gmail-message-mode ham-mode html-to-markdown flymd edit-server image-dired+ go-guru go-eldoc company-go go-mode unfill mwim company-web web-completion-data company-tern company-cabal company-c-headers company-auctex company-anaconda elcord xresources-theme sql-indent rainbow-mode php-extras php-mode mmm-mode json-mode js2-mode csv-mode coffee-mode auctex helm-company helm-c-yasnippet fuzzy company-statistics company auto-yasnippet yasnippet ac-ispell auto-complete ws-butler winum which-key volatile-highlights vi-tilde-fringe uuidgen use-package toc-org spaceline powerline restart-emacs request rainbow-delimiters popwin persp-mode pcre2el paradox spinner org-plus-contrib org-bullets open-junk-file neotree move-text macrostep lorem-ipsum linum-relative link-hint indent-guide hydra hungry-delete hl-todo highlight-parentheses highlight-numbers parent-mode highlight-indentation helm-themes helm-swoop helm-projectile helm-mode-manager helm-make projectile pkg-info epl helm-flx helm-descbinds helm-ag google-translate golden-ratio flx-ido flx fill-column-indicator fancy-battery eyebrowse expand-region exec-path-from-shell evil-visualstar evil-visual-mark-mode evil-unimpaired evil-tutor evil-surround evil-search-highlight-persist evil-numbers evil-nerd-commenter evil-mc evil-matchit evil-lisp-state smartparens evil-indent-plus evil-iedit-state iedit evil-exchange evil-escape evil-ediff evil-args evil-anzu anzu evil goto-chg undo-tree eval-sexp-fu highlight elisp-slime-nav dumb-jump f dash s diminish define-word column-enforce-mode clean-aindent-mode bind-map bind-key auto-highlight-symbol auto-compile packed aggressive-indent adaptive-wrap ace-window ace-link ace-jump-helm-line helm avy helm-core popup async)) + '(curl-to-elisp org-tree-slide wrap-region helm-icons org-treeusage caddyfile-mode org-ref lsp-dart mu4e-maildirs-extension mu4e-alert helm-mu xkcd vmd-mode visual-fill-column typit mmt sudoku restclient-helm pony-mode pacmacs ox-reveal outorg ob-restclient ob-http meson-mode ibuffer-projectile lv helm-w3m w3m graphviz-dot-mode flycheck-gometalinter transient ess-smart-equals ess-R-data-view ctable ess julia-mode eshell-git-prompt emoji-cheat-sheet-plus edit-indirect dockerfile-mode docker docker-tramp company-restclient restclient know-your-http-well company-quickhelp company-emoji company-emacs-eclim eclim atomic-chrome websocket 2048-game ox-gfm slime-company slime common-lisp-snippets erlang insert-shebang fish-mode company-shell faceup racket-mode treepy graphql yapfify yaml-mode xterm-color web-beautify twittering-mode toml-mode tagedit stickyfunc-enhance smeargle slim-mode shell-pop selectric-mode scss-mode sass-mode ranger rainbow-identifiers pytest pyenv-mode py-isort pug-mode plantuml-mode phpunit phpcbf php-auto-yasnippets pdf-tools tablist ox-pandoc orgit org-present org-pomodoro alert log4e gntp ob-elixir multi-term markdown-toc magit-gitflow magit-gh-pulls livid-mode live-py-mode json-snatcher js2-refactor js-doc htmlize hlint-refactor hindent helm-pydoc helm-hoogle helm-gitignore helm-css-scss haskell-snippets haml-mode gnuplot glsl-mode gitignore-mode github-search github-clone github-browse-file gitconfig-mode gitattributes-mode git-messenger gist gh marshal logito pcache ht gh-md flyspell-correct-helm flyspell-correct flycheck-rust pos-tip flycheck-mix flycheck-credo eshell-z eshell-prompt-extras esh-help drupal-mode disaster cython-mode dash-functional tern company-ghci company-ghc ghc color-identifiers-mode cmm-mode clang-format cargo auto-dictionary alchemist modern-cpp-font-lock yasnippet-snippets x86-lookup web-mode srefactor racer pyvenv pip-requirements pandoc-mode org-projectile org-category-capture org-mime org-download nasm-mode json-reformat intero imenu-list hy-mode git-timemachine git-link geiser flycheck-pos-tip flycheck-haskell evil-magit emmet-mode cmake-mode anaconda-mode rust-mode elixir-mode flycheck haskell-mode multiple-cursors skewer-mode simple-httpd markdown-mode magit magit-popup git-commit ghub with-editor pythonic emms gmail-message-mode ham-mode html-to-markdown flymd edit-server image-dired+ go-guru go-eldoc company-go go-mode unfill mwim company-web web-completion-data company-tern company-cabal company-c-headers company-auctex company-anaconda elcord xresources-theme sql-indent rainbow-mode php-extras php-mode mmm-mode json-mode js2-mode csv-mode coffee-mode auctex helm-company helm-c-yasnippet fuzzy company-statistics company auto-yasnippet yasnippet ac-ispell auto-complete ws-butler winum which-key volatile-highlights vi-tilde-fringe uuidgen use-package toc-org spaceline powerline restart-emacs request rainbow-delimiters popwin persp-mode pcre2el paradox spinner org-plus-contrib org-bullets open-junk-file neotree move-text macrostep lorem-ipsum linum-relative link-hint indent-guide hydra hungry-delete hl-todo highlight-parentheses highlight-numbers parent-mode highlight-indentation helm-themes helm-swoop helm-projectile helm-mode-manager helm-make projectile pkg-info epl helm-flx helm-descbinds helm-ag google-translate golden-ratio flx-ido flx fill-column-indicator fancy-battery eyebrowse expand-region exec-path-from-shell evil-visualstar evil-visual-mark-mode evil-unimpaired evil-tutor evil-surround evil-search-highlight-persist evil-numbers evil-nerd-commenter evil-mc evil-matchit evil-lisp-state smartparens evil-indent-plus evil-iedit-state iedit evil-exchange evil-escape evil-ediff evil-args evil-anzu anzu evil goto-chg undo-tree eval-sexp-fu highlight elisp-slime-nav dumb-jump f dash s diminish define-word column-enforce-mode clean-aindent-mode bind-map bind-key auto-highlight-symbol auto-compile packed aggressive-indent adaptive-wrap ace-window ace-link ace-jump-helm-line helm avy helm-core popup async)) '(pdf-view-midnight-colors '("#655370" . "#fbf8ef")) '(safe-local-variable-values '((org-confirm-babel-evaluate) diff --git a/org/config/spacemacs.org b/org/config/spacemacs.org index f41bfe7..e62085b 100644 --- a/org/config/spacemacs.org +++ b/org/config/spacemacs.org @@ -1,4 +1,3 @@ -# -*- org-confirm-babel-evaluate: nil -*- #+title: Spacemacs Configuration #+setupfile: headers #+OPTIONS: auto-id:t @@ -22,7 +21,7 @@ * Spacemacs layers and packages :PROPERTIES: - :header-args:emacs-lisp: :tangle ~/.config/emacs/private/spacemacs-layers.el :exports code :results silent + :header-args:emacs-lisp: :mkdir yes :tangle ~/.config/emacs/private/spacemacs-layers.el :exports code :results silent :CUSTOM_ID: Spacemacs_layers_and_packages-6d318b87 :END: Here will be our layer configuration set. Everything here is set with a @@ -98,14 +97,17 @@ | doom-themes | some cool themes | | edit-indirect | edit region in separate buffer | | elcord | rich integration of Emacs in Discord | + | helm-icons | Integration between helm and treemacs icons | | kaolin-themes | some cool themes | | lsp-dart | apparently, it isn’t included in the Dart layer | | magit-gitflow | integrate gitflow in Magit | | multiple-cursors | I don’t like the layer, I prefer this package alone | | org-sidebar | display on the side the outline of an Org buffer | + | org-tree-slide | presentation tool for org-mode | | outorg | edit comments as Org-mode buffers | | pinentry | enter a GPG password from Emacs | | visual-fill-column | allow the use of ~fill-column~ in ~visual-line-mode~ | + | wrap-region | easily wrap region with delimiters | | wttrin | weather in Emacs | | yasnippet-snippets | snippets for YaSnippet | @@ -586,7 +588,7 @@ * Init :PROPERTIES: - :header-args:emacs-lisp: :tangle ~/.config/emacs/private/spacemacs-init.el :exports code :results silent + :header-args:emacs-lisp: :mkdir yes :tangle ~/.config/emacs/private/spacemacs-init.el :exports code :results silent :CUSTOM_ID: Init-99a4b561 :END: The ~dotspacemacs/init~ function is the one called at the very begining of the @@ -1258,7 +1260,7 @@ * User Initialization :PROPERTIES: - :header-args:emacs-lisp: :tangle ~/.config/emacs/private/user-init.el :exports code :results silent + :header-args:emacs-lisp: :mkdir yes :tangle ~/.config/emacs/private/user-init.el :exports code :results silent :CUSTOM_ID: User_Initialization-e0d21089 :END: @@ -1306,7 +1308,7 @@ * User Configuration :PROPERTIES: - :header-args:emacs-lisp: :tangle ~/.config/emacs/private/user-config.el :exports code :results silent + :header-args:emacs-lisp: :mkdir yes :tangle ~/.config/emacs/private/user-config.el :exports code :results silent :CUSTOM_ID: User_Configuration-4a937fe5 :END: ** Custom functions @@ -1331,13 +1333,13 @@ function. It also comes with a helper function that parses the arguments given to the ~new~ function. #+BEGIN_SRC emacs-lisp - (defun phundrak//yas-snippet-split-args (arg-string) + (defun phundrak//yas-snippet-split-rust-args ($arg-string) "Split a Rust argument string into ((name, default)...) tuples" - (mapcar (lambda (x) - (split-string x "[[:blank:]]*:[[:blank:]]*" t)) - (split-string arg-string "[[:blank:]]*,[[:blank:]]*" t))) + (mapcar (lambda ($elem) + (split-string $elem "[[:blank:]]*:[[:blank:]]*" t)) + (split-string $arg-string "[[:blank:]]*,[[:blank:]]*" t))) - (defun phundrak/yas-rust-new-assignments (arg-string) + (defun phundrak/yas-rust-new-assignments ($arg-string) "Return a typical new assignment for arguments. Inspired from elpy’s functions https://github.com/jorgenschaefer/elpy" @@ -1345,11 +1347,11 @@ (goto-char start-point) (current-indentation)) ?\s))) - (mapconcat (lambda (arg) - (if (string-match "^\\*" (car arg)) + (mapconcat (lambda ($elem) + (if (string-match "^\\*" (car $elem)) "" - (format "%s,\n%s" (car arg) indentation))) - (phundrak//yas-snippet-split-args arg-string) + (format "%s,\n%s" (car $elem) indentation))) + (phundrak//yas-snippet-split-rust-args $arg-string) ""))) #+END_SRC @@ -1358,14 +1360,14 @@ :CUSTOM_ID: User_Configuration-Custom_functions-phundrakadd-all-to-list-7e34472b :END: #+BEGIN_SRC emacs-lisp - (defun phundrak/add-all-to-list (list &rest elements) - "Add all elements from `elements' to the list `list'. If an - element from `elements' is already part of `list', it will be + (defun phundrak/add-all-to-list ($list &rest $elements) + "Add all $elements from `$elements' to the $list `$list'. If an + element from `$elements' is already part of `$list', it will be ignored." - (dolist (e elements) - (if (not (member e list)) - (add-to-list 'list e))) - list) + (dolist ($e $elements) + (if (not (member $e $list)) + (add-to-list '$list $e))) + $list) #+END_SRC *** ~phundrak/fill-paragraph~ @@ -1396,656 +1398,1299 @@ '("st")) #+END_SRC -** ASM configuration +** Emacs builtins :PROPERTIES: - :CUSTOM_ID: User_Configuration-ASM_configuration-f6dc7674 + :CUSTOM_ID: User_Configuration-Emacs_builtins-7822b8dd :END: - The first thing I will set with my ASM configuration is where the reference - PDF is located. - #+BEGIN_SRC emacs-lisp - (setq x86-lookup-pdf "~/Documents/code/asm/Intelx86/325383-sdm-vol-2abcd.pdf") - #+END_SRC - I will also modify what the comment character is, from a ~;~ to a ~#~: - #+BEGIN_SRC emacs-lisp - (setq asm-comment-char ?\#) - #+END_SRC - -** C/C++ - :PROPERTIES: - :CUSTOM_ID: User_Configuration-C-C++-76c3f997 - :END: - As the C/C++ syntax is checked by flycheck, let’s make sure we are using the - latest standard available, that is C++17 and C17, from Clang. - #+BEGIN_SRC emacs-lisp - (add-hook 'c-mode-hook - (lambda () - (setq flycheck-clang-language-standard "c17"))) - (add-hook 'c++-mode-hook - (lambda () - (setq flycheck-clang-language-standard "c++17"))) - #+END_SRC - -** Dart configuration - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Dart_configuration-ecf24ebf - :END: - For Dart, I mainly declared some custom shortcuts bound to ~dart-mode~ - related to flutter, so nothing too exciting here. Some prefix are declared in - order to avoid the shortcuts in helm to show up as just ~custom~. - #+begin_src emacs-lisp - (spacemacs/declare-prefix-for-mode 'dart-mode "mo" "user-defined") - (spacemacs/declare-prefix-for-mode 'dart-mode "mof" "flutter") - (spacemacs/declare-prefix-for-mode 'dart-mode "mofr" "flutter-run") - #+end_src - - Now, for the shortcuts themselves: - #+BEGIN_SRC emacs-lisp - (spacemacs/set-leader-keys-for-major-mode 'dart-mode - "ofH" 'flutter-hot-restart - "ofh" 'flutter-hot-reload - "ofq" 'flutter-quit - "ofr" (lambda () (interactive) (flutter-run "-v")) - "ofs" 'flutter-screenshot) - #+END_SRC - -** Dired - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Dired-ef8a7cac - :END: - When it comes to dired, I chose do modify some elements on how things are - sorted and shown, but there isn’t much configuration. First, I want to always - copy folders in a recursive way, no questions asked. - #+BEGIN_SRC emacs-lisp - (setq dired-recursive-copies 'always) - #+END_SRC - - Also, when I have two Dired buffers opened side by side, I generally want - them to interact, for example if I want to move something around. So, let’s - tell Emacs that: - #+BEGIN_SRC emacs-lisp - (setq dired-dwim-target t) - #+END_SRC - - Finally, let’s tell Dired how to sort the elements to be displayed: - directories first, non-hidden first. - #+BEGIN_SRC emacs-lisp - (setq dired-listing-switches "-ahl --group-directories-first") - #+END_SRC - - By the way, let’s enable ~org-download~ when we are in a Dired buffer: - #+BEGIN_SRC emacs-lisp - (add-hook 'dired-mode-hook 'org-download-enable) - #+END_SRC - -** Emacs Lisp - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Emacs_Lisp-59230f3c - :END: - Here will be stored my configuration directly related to Emacs Lisp, - including some functions or default modes. - -*** Enable ~eldoc-mode~ by default +*** Dired :PROPERTIES: - :CUSTOM_ID: User_Configuration-Emacs_Lisp-Enable_~eldoc-mode~_by_default-f131abde + :CUSTOM_ID: User_Configuration-Dired-ef8a7cac :END: - By default, if some Elisp code is opened, I want to enable ~eldoc-mode~ so I - can easily get some documentation on the symbols in the source code. This is - done via the use of hooks. + When it comes to dired, I chose do modify some elements on how things are + sorted and shown, but there isn’t much configuration. First, I want to always + copy folders in a recursive way, no questions asked. #+BEGIN_SRC emacs-lisp - (add-hook 'prog-mode-hook 'eldoc-mode) + (setq dired-recursive-copies 'always) #+END_SRC -*** ~phundrak/write-to-buffer~ + Also, when I have two Dired buffers opened side by side, I generally want + them to interact, for example if I want to move something around. So, let’s + tell Emacs that: + #+BEGIN_SRC emacs-lisp + (setq dired-dwim-target t) + #+END_SRC + + Finally, let’s tell Dired how to sort the elements to be displayed: + directories first, non-hidden first. + #+BEGIN_SRC emacs-lisp + (setq dired-listing-switches "-ahl --group-directories-first") + #+END_SRC + + By the way, let’s enable ~org-download~ when we are in a Dired buffer: + #+BEGIN_SRC emacs-lisp + (add-hook 'dired-mode-hook 'org-download-enable) + #+END_SRC + +*** Eshell :PROPERTIES: - :CUSTOM_ID: User_Configuration-Emacs_Lisp-~phundrak-write-to-buffer~-2f192dd3 + :CUSTOM_ID: User_Configuration-Eshell-3012e67e :END: - I was very surprised when I discovered no such function exists in Elisp. - This function basically writes a string into a buffer, and optionally - switches the user to the buffer. Here is the code for that function: - #+BEGIN_SRC elisp :results silent - (defun write-to-buffer (input-string outputbuf &optional switchbuf) - "Writes `input-string' to the specified `output-buffer'. If - `switch-buffer' is non-nil, the active buffer will switch to the - output buffer; otherwise, it will take the user back to their - initial buffer. Works with `input-string' as a string or a list - of strings." - (let ((oldbuf (current-buffer))) - (switch-to-buffer outputbuf) - (cond ((char-or-string-p input-string) (insert input-string)) - ((listp input-string) (dolist (elem input-string) - (insert (format "%s\n" elem))))) - (if switchbuf - (switch-to-buffer oldbuf)))) - #+END_SRC + Eshell is a built-in shell available from Emacs which I use almost as often + as Fish. Some adjustments are necessary for making this shell usable for me. -** Eshell - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Eshell-3012e67e - :END: - Eshell is a built-in shell available from Emacs which I use almost as often - as Fish. Some adjustments are necessary for making this shell usable for me. - -*** Environment variables - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Eshell-Environment_variables-8dac73e0 - :END: - Some environment variables need to be correctly set so Eshell can correctly - work. The first environment variable to be set is the ~PATH~, as I have a - couple of directories where executables are located. Let’s add them to our - path. - #+BEGIN_SRC emacs-lisp - (setenv "PATH" - (concat - (getenv "HOME") "/.pub-cache/bin" - ":" (getenv "HOME") "/.local/bin" - ":" (getenv "HOME") "/go/bin" - ":" (getenv "HOME") "/.cargo/bin" - ":" (getenv "HOME") "/.gem/ruby/2.6.0/bin" - ":" (getenv "PATH"))) - #+END_SRC - - I would also like to set two environment variables related to Dart - development: the ~DART_SDK~ and ~ANDROID_HOME~ variables. - #+BEGIN_SRC emacs-lisp - (setenv "DART_SDK" "/opt/dart-sdk/bin") - (setenv "ANDROID_HOME" (concat (getenv "HOME") "/Android/Sdk/")) - #+END_SRC - - Finally, I’d like to add a custom directory to the ~PKG_CONFIG_PATH~: - #+BEGIN_SRC emacs-lisp - (setenv "PKG_CONFIG_PATH" (concat - "/usr/local/lib/pkgconfig/" ":" - (getenv "PKG_CONFIG_PATH"))) - #+END_SRC - - The ~EDITOR~ variable also needs to be set for git commands, especially the - ~yadm~ commands. - #+BEGIN_SRC emacs-lisp - (setenv "EDITOR" "emacsclient -c") - #+END_SRC - -*** Custom functions - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Eshell-Custom_functions-79d98245 - :END: - When I’m in Eshell, sometimes I wish to open multiple files at once in - Emacs. For this, when I have several arguments for ~find-file~, I want to be - able to open them all at once. Let’s modify ~find-file~ like so: - #+BEGIN_SRC emacs-lisp - (defadvice find-file (around find-files activate) - "Also find all files within a list of files. This even works recursively." - (if (listp filename) - (loop for f in filename do (find-file f wildcards)) - ad-do-it)) - #+END_SRC - - I also want to be able to have multiple instances of Eshell opened at once. - For that, I declared the function ~eshell-new~ that does exactly that. - #+BEGIN_SRC emacs-lisp - (defun eshell-new() - "Open a new instance of eshell." - (interactive) - (eshell 'N)) - #+END_SRC - -**** Redirect text editors to Emacs +**** Environment variables :PROPERTIES: - :CUSTOM_ID: User_Configuration-Eshell-Custom_functions-Redirect_text_editors_to_Emacs-dff362c6 + :CUSTOM_ID: User_Configuration-Eshell-Environment_variables-8dac73e0 :END: - I still have some muscle memory telling me to open nano, ed, or vim, and - sometimes I even try to type ~emacs~ in the terminal, which is stupid with - Eshell since I’m already inside Emacs. So, for each of these text editors, - let’s make the command open the files in Emacs. + Some environment variables need to be correctly set so Eshell can correctly + work. The first environment variable to be set is the ~PATH~, as I have a + couple of directories where executables are located. Let’s add them to our + path. #+BEGIN_SRC emacs-lisp - (defun eshell/emacs (&rest files) - "Open a file in a new buffer. Old habits die hard" - (if (null files) - (bury-buffer) - (mapc #'find-file - (mapcar #'expand-file-name - (eshell-flatten-list (reverse files)))))) - (defalias 'eshell/vi 'eshell/emacs) - (defalias 'eshell/vim 'eshell/emacs) - (defalias 'eshell/ed 'eshell/emacs) - (defalias 'eshell/nano 'eshell/emacs) + (setenv "PATH" + (concat + (getenv "HOME") "/.pub-cache/bin" + ":" (getenv "HOME") "/.local/bin" + ":" (getenv "HOME") "/go/bin" + ":" (getenv "HOME") "/.cargo/bin" + ":" (getenv "HOME") "/.gem/ruby/2.6.0/bin" + ":" (getenv "PATH"))) #+END_SRC -*** Aliases - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Eshell-Aliases-ef06615f - :END: - This function is a function that will come in very handy for Eshell - functions that call shell processes. It concatenates the initial string - ~command~ with all the arguments ~args~, each separated with a space. - #+BEGIN_SRC emacs-lisp - (defun phundrak/concatenate-shell-command (command &rest args) - (string-join (cons command args) " ")) - #+END_SRC + I would also like to set two environment variables related to Dart + development: the ~DART_SDK~ and ~ANDROID_HOME~ variables. + #+BEGIN_SRC emacs-lisp + (setenv "DART_SDK" "/opt/dart-sdk/bin") + (setenv "ANDROID_HOME" (concat (getenv "HOME") "/Android/Sdk/")) + #+END_SRC - Just like most shells, it is possible to declare in Eshell aliases. First, I - would like to be able to use ~open~ to open files in Emacs: - #+BEGIN_SRC emacs-lisp - (defalias 'open 'find-file) - #+END_SRC + Finally, I’d like to add a custom directory to the ~PKG_CONFIG_PATH~: + #+BEGIN_SRC emacs-lisp + (setenv "PKG_CONFIG_PATH" (concat + "/usr/local/lib/pkgconfig/" ":" + (getenv "PKG_CONFIG_PATH"))) + #+END_SRC - I also have ~openo~ which allows me to perform the same action, but in - another window: - #+BEGIN_SRC emacs-lisp - (defalias 'openo 'find-file-other-window) - #+END_SRC + The ~EDITOR~ variable also needs to be set for git commands, especially the + ~yadm~ commands. + #+BEGIN_SRC emacs-lisp + (setenv "EDITOR" "emacsclient -c") + #+END_SRC - The function ~yes-or-no-p~ is also aliased to ~y-or-n-p~ so I only have to - answer by ~y~ or ~n~ instead of typing ~yes~ or ~no~. - #+BEGIN_SRC emacs-lisp - (defalias 'yes-or-no-p 'y-or-n-p) - #+END_SRC - - For some ease of use, I’ll also declare ~list-buffers~ as an alias of - ~ibuffer~. - #+BEGIN_SRC emacs-lisp - (defalias 'list-buffers 'ibuffer) - #+END_SRC - - #+BEGIN_SRC emacs-lisp - (defun eshell/mkdir (directory) - (make-directory directory t)) - #+END_SRC - -**** System monitoring +**** Custom functions :PROPERTIES: - :CUSTOM_ID: User_Configuration-Eshell-Aliases-System_monitoring-ee01b070 + :CUSTOM_ID: User_Configuration-Eshell-Custom_functions-79d98245 :END: - Similar to ~meminfo~, we also have ~gpumeminfo~ so we can get a quick look - at the memory-related logs of our X session. + When I’m in Eshell, sometimes I wish to open multiple files at once in + Emacs. For this, when I have several arguments for ~find-file~, I want to be + able to open them all at once. Let’s modify ~find-file~ like so: #+BEGIN_SRC emacs-lisp - (defun eshell/gpumeminfo (&rest args) - (eshell/grep "-i" "--color" "memory" "/var/log/Xorg.0.log")) - (defun eshell/diskspace () - (shell-command "sudo df -h | grep -E \"sd|lv|Size\" | sort")) + (defadvice find-file (around find-files activate) + "Also find all files within a list of files. This even works recursively." + (if (listp filename) + (loop for f in filename do (find-file f wildcards)) + ad-do-it)) #+END_SRC - I also declared ~cpuinfo~ an alias of ~lscpu~ in order to keep consistent - with ~meminfo~. + I also want to be able to have multiple instances of Eshell opened at once. + For that, I declared the function ~eshell-new~ that does exactly that. #+BEGIN_SRC emacs-lisp - (defun eshell/meminfo () - (shell-command "free -m -l -t")) + (defun eshell-new() + "Open a new instance of eshell." + (interactive) + (eshell 'N)) #+END_SRC - ~pscpu~ gives us information on what the CPU is running right now, and - I also declared ~cpuinfo~ an alias of ~lscpu~ in order to keep consistent - with ~meminfo~. - #+BEGIN_SRC emacs-lisp - (defun eshell/cpuinfo () - (shell-command "lscpu")) - #+END_SRC +***** Redirect text editors to Emacs + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Eshell-Custom_functions-Redirect_text_editors_to_Emacs-dff362c6 + :END: + I still have some muscle memory telling me to open nano, ed, or vim, and + sometimes I even try to type ~emacs~ in the terminal, which is stupid with + Eshell since I’m already inside Emacs. So, for each of these text editors, + let’s make the command open the files in Emacs. + #+BEGIN_SRC emacs-lisp + (defun eshell/emacs (&rest $files) + "Open a file in a new buffer. Old habits die hard" + (if (null $files) + (bury-buffer) + (mapc #'find-file + (mapcar #'expand-file-name + (eshell-flatten-list (reverse $files)))))) + (defalias 'eshell/vi 'eshell/emacs) + (defalias 'eshell/vim 'eshell/emacs) + (defalias 'eshell/ed 'eshell/emacs) + (defalias 'eshell/nano 'eshell/emacs) + #+END_SRC - ~pscpu10~ limits that to the top 10 threads. - #+BEGIN_SRC emacs-lisp - (defun eshell/pscpu () - (shell-command "ps auxf | sort -nr -k 3")) - (defun eshell/pscpu10 () - (shell-command "ps auxf | sort -nr -k 3 | head -10")) - #+END_SRC - - Similarly, ~psmem~ gives us information on the memory usage of the current - threads, and ~psmem10~ only the ten most important threads in terms of - memory usage. - #+BEGIN_SRC emacs-lisp - (defun eshell/pscpu () - (shell-command "ps auxf | sort -nr -k 4")) - (defun eshell/pscpu10 () - (shell-command "ps auxf | sort -nr -k 4 | head -10")) - #+END_SRC - -**** System management (packages and services) +**** Aliases :PROPERTIES: - :CUSTOM_ID: User_Configuration-Eshell-Aliases-System_management_(packages_and_services)-afb6d9d3 + :CUSTOM_ID: User_Configuration-Eshell-Aliases-ef06615f :END: - The first command is ~remove~ which removes a package and its dependencies - from the system. + This function is a function that will come in very handy for Eshell + functions that call shell processes. It concatenates the initial string + ~command~ with all the arguments ~args~, each separated with a space. #+BEGIN_SRC emacs-lisp - (defun eshell/remove (&rest args) - (phundrak/concatenate-shell-command "sudo pacman -Rscnd" - args)) + (defun phundrak/concatenate-shell-command ($command &rest $args) + (string-join (cons $command $args) " ")) #+END_SRC - But if I just want to run ~pacman~ as sudo, then I could always just type - ~p~. + Just like most shells, it is possible to declare in Eshell aliases. First, I + would like to be able to use ~open~ to open files in Emacs: #+BEGIN_SRC emacs-lisp - (defun eshell/p (&rest args) - (phundrak/concatenate-shell-command "sudo pacman" args)) + (defalias 'open 'find-file) #+END_SRC - Sometimes, I just want to purge my package manager’s cache, be it - ~pacman~'s or ~yay~'s. This is why I simply type ~purge~. + I also have ~openo~ which allows me to perform the same action, but in + another window: #+BEGIN_SRC emacs-lisp - (defun eshell/purge () - (shell-command "yay -Sc")) + (defalias 'openo 'find-file-other-window) #+END_SRC - #+RESULTS: - : eshell/purge + The function ~yes-or-no-p~ is also aliased to ~y-or-n-p~ so I only have to + answer by ~y~ or ~n~ instead of typing ~yes~ or ~no~. + #+BEGIN_SRC emacs-lisp + (defalias 'yes-or-no-p 'y-or-n-p) + #+END_SRC -**** Other + For some ease of use, I’ll also declare ~list-buffers~ as an alias of + ~ibuffer~. + #+BEGIN_SRC emacs-lisp + (defalias 'list-buffers 'ibuffer) + #+END_SRC + + #+BEGIN_SRC emacs-lisp + (defun eshell/mkdir ($directory) + (make-directory $directory t)) + #+END_SRC + + #+BEGIN_SRC emacs-lisp + (defun eshell/ls (&optional $directory) + (shell-command (format "exa -halg@ --group-directories-first --git%s" + (if (string= "" $directory) + "" + (concat " " $directory))))) + #+END_SRC + +***** System monitoring + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Eshell-Aliases-System_monitoring-ee01b070 + :END: + Similar to ~meminfo~, we also have ~gpumeminfo~ so we can get a quick look + at the memory-related logs of our X session. + #+BEGIN_SRC emacs-lisp + (defun eshell/gpumeminfo (&rest $args) + (eshell/grep "-i" "--color" "memory" "/var/log/Xorg.0.log")) + (defun eshell/diskspace () + (shell-command "sudo df -h | grep -E \"sd|lv|Size\" | sort")) + #+END_SRC + + I also declared ~cpuinfo~ an alias of ~lscpu~ in order to keep consistent + with ~meminfo~. + #+BEGIN_SRC emacs-lisp + (defun eshell/meminfo () + (shell-command "free -m -l -t")) + #+END_SRC + + ~pscpu~ gives us information on what the CPU is running right now, and + I also declared ~cpuinfo~ an alias of ~lscpu~ in order to keep consistent + with ~meminfo~. + #+BEGIN_SRC emacs-lisp + (defun eshell/cpuinfo () + (shell-command "lscpu")) + #+END_SRC + + ~pscpu10~ limits that to the top 10 threads. + #+BEGIN_SRC emacs-lisp + (defun eshell/pscpu () + (shell-command "ps auxf | sort -nr -k 3")) + (defun eshell/pscpu10 () + (shell-command "ps auxf | sort -nr -k 3 | head -10")) + #+END_SRC + + Similarly, ~psmem~ gives us information on the memory usage of the current + threads, and ~psmem10~ only the ten most important threads in terms of + memory usage. + #+BEGIN_SRC emacs-lisp + (defun eshell/pscpu () + (shell-command "ps auxf | sort -nr -k 4")) + (defun eshell/pscpu10 () + (shell-command "ps auxf | sort -nr -k 4 | head -10")) + #+END_SRC + +***** System management (packages and services) + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Eshell-Aliases-System_management_(packages_and_services)-afb6d9d3 + :END: + The first command is ~remove~ which removes a package and its dependencies + from the system. + #+BEGIN_SRC emacs-lisp + (defun eshell/remove (&rest $args) + (phundrak/concatenate-shell-command "sudo pacman -Rscnd" + $args)) + #+END_SRC + + But if I just want to run ~pacman~ as sudo, then I could always just type + ~p~. + #+BEGIN_SRC emacs-lisp + (defun eshell/p (&rest $args) + (phundrak/concatenate-shell-command "sudo pacman" $args)) + #+END_SRC + + Sometimes, I just want to purge my package manager’s cache, be it + ~pacman~'s or ~yay~'s. This is why I simply type ~purge~. + #+BEGIN_SRC emacs-lisp + (defun eshell/purge () + (shell-command "yay -Sc")) + #+END_SRC + +***** Other + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Eshell-Aliases-Other-bd88ca97 + :END: + ~mkcd~ is a function that allows me to create a directory and ~cd~ into it + at the same time. + #+begin_src emacs-lisp + (defun eshell/mkcd ($directory) + (eshell/mkdir "-p" $directory) + (cd $directory)) + #+end_src + + #+BEGIN_SRC emacs-lisp + (defun eshell/lsl (&rest $args) + (eshell/ls "-aHl" $args)) + #+END_SRC + + #+BEGIN_SRC emacs-lisp + (defun eshell/ll (&rest $args) + (eshell/ls "-ahl" $args)) + #+END_SRC + + #+BEGIN_SRC emacs-lisp + (defun eshell/la (&rest $args) + (eshell/ls "-A" $args)) + #+END_SRC + +***** Typos + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Eshell-Aliases-Typos-c7bfe6eb + :END: + ~q~ is a shorthand for ~exit~. ~exti~ and ~exi~ are for typos when I type ~exit~. + #+BEGIN_SRC emacs-lisp + (defun eshell/q (&rest $args) + (eshell/exit $args)) + (defun eshell/exti (&rest $args) + (eshell/exit $args)) + (defun eshell/exi (&rest $args) + (eshell/exit $args)) + #+END_SRC + + ~clean~ is also a typo of ~clear~ I often make. Let’s fix this: + #+BEGIN_SRC emacs-lisp + (defun eshell/clean (&rest $args) + (eshell/clear $args)) + #+END_SRC + +**** Visual commands :PROPERTIES: - :CUSTOM_ID: User_Configuration-Eshell-Aliases-Other-bd88ca97 + :CUSTOM_ID: User_Configuration-Eshell-Visual_commands-2b15e0dc :END: - ~mkcd~ is a function that allows me to create a directory and ~cd~ into it - at the same time. - #+begin_src emacs-lisp - (defun eshell/mkcd (directory) - (eshell/mkdir "-p" directory) - (cd directory)) - #+end_src - + With Eshell, some commands don’t work very well, especially commands that + create a TUI. So, let’s declare them as visual commands or subcommands: #+BEGIN_SRC emacs-lisp - (defun eshell/lsl (&rest args) - (eshell/ls "-aHl" args)) + (setq eshell-visual-commands + '("fish" "zsh" "bash" "tmux" "htop" "top" "vim" "bat" "nano") + eshell-visual-subcommands + '("git" "log" "l" "diff" "show")) #+END_SRC - #+BEGIN_SRC emacs-lisp - (defun eshell/ll (&rest args) - (eshell/ls "-ahl" args)) - #+END_SRC - - #+BEGIN_SRC emacs-lisp - (defun eshell/la (&rest args) - (eshell/ls "-A" args)) - #+END_SRC - -**** Typos +**** Eshell theme :PROPERTIES: - :CUSTOM_ID: User_Configuration-Eshell-Aliases-Typos-c7bfe6eb + :CUSTOM_ID: User_Configuration-Eshell-Eshell_theme-a06715a9 :END: - ~q~ is a shorthand for ~exit~. ~exti~ and ~exi~ are for typos when I type ~exit~. + As with most shells, again, it is possible to customize the appearance of + the Eshell prompt. First, we need to declare a macro so we can set a face + with properties: #+BEGIN_SRC emacs-lisp - (defun eshell/q (&rest args) - (eshell/exit args)) - (defun eshell/exti (&rest args) - (eshell/exit args)) - (defun eshell/exi (&rest args) - (eshell/exit args)) + (defmacro with-face (str &rest properties) + `(propertize ,str 'face (list ,@properties))) #+END_SRC - ~clean~ is also a typo of ~clear~ I often make. Let’s fix this: + Now, let’s declare a function that will abbreviate the current ~pwd~ + fish-shell style. #+BEGIN_SRC emacs-lisp - (defun eshell/clean (&rest args) - (eshell/clear args)) + (defun eshell/abbr-pwd () + (let (($home (getenv "HOME")) + ($path (eshell/pwd))) + (cond + ((string-equal $home $path) "~") + ((f-ancestor-of? $home $path) (concat "~/" (f-relative $path $home))) + ($path)))) #+END_SRC -*** Visual commands + Now, let’s declare our prompt: + #+BEGIN_SRC emacs-lisp + (defun eshell/my-prompt () + (let ((header-bg "#161616")) + (concat + (with-face (eshell/abbr-pwd) :foreground "#008700") + "\n" + (if (= (user-uid) 0) + (with-face "➜" :foreground "red") + (with-face "➜" :foreground "#2345ba")) + " "))) + #+END_SRC + + Now, let’s declare our prompt regexp and our prompt functions: + #+BEGIN_SRC emacs-lisp + (setq eshell-prompt-regexp "^[^#$\n]*[#$] " + eshell-prompt-function 'eshell/my-prompt) + #+END_SRC + +*** Org-mode :PROPERTIES: - :CUSTOM_ID: User_Configuration-Eshell-Visual_commands-2b15e0dc + :CUSTOM_ID: User_Configuration-Org-mode-04ab8ad3 :END: - With Eshell, some commands don’t work very well, especially commands that - create a TUI. So, let’s declare them as visual commands or subcommands: - #+BEGIN_SRC emacs-lisp - (setq eshell-visual-commands - '("fish" "zsh" "bash" "tmux" "htop" "top" "vim" "bat" "nano") - eshell-visual-subcommands - '("git" "log" "l" "diff" "show")) + Org-mode is probably one of the best if not the best Emacs feature I have + ever discovered. It is awesome for writing documents, regardless of the + format you need it to be exported to, for agenda management, and for literary + programming, such as with this document. + #+BEGIN_SRC emacs-lisp :tangle no + (with-eval-after-load 'org + ;; configuration goes here + ) #+END_SRC -*** Eshell theme - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Eshell-Eshell_theme-a06715a9 - :END: - As with most shells, again, it is possible to customize the appearance of - the Eshell prompt. First, we need to declare a macro so we can set a face - with properties: - #+BEGIN_SRC emacs-lisp - (defmacro with-face (str &rest properties) - `(propertize ,str 'face (list ,@properties))) - #+END_SRC + # Don’t delete this, this code block is here to wrap the org configuration + #+BEGIN_SRC emacs-lisp :exports none + (with-eval-after-load 'org + #+END_SRC - Now, let’s declare a function that will abbreviate the current ~pwd~ - fish-shell style. - #+BEGIN_SRC emacs-lisp - (defun eshell/abbr-pwd () - (let ((home (getenv "HOME")) - (path (eshell/pwd))) - (cond - ((string-equal home path) "~") - ((f-ancestor-of? home path) (concat "~/" (f-relative path home))) - (path)))) - #+END_SRC +**** Custom org-mode functions + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Custom_org-mode_functions-f1726995 + :END: + We begin with a couple of custom functions that I use in my org-mode files. - Now, let’s declare our prompt: - #+BEGIN_SRC emacs-lisp - (defun eshell/my-prompt () - (let ((header-bg "#161616")) - (concat - (with-face (eshell/abbr-pwd) :foreground "#008700") - "\n" - (if (= (user-uid) 0) - (with-face "➜" :foreground "red") - (with-face "➜" :foreground "#2345ba")) - " "))) - #+END_SRC +***** Custom and unique headings ID + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Custom_org-mode_functions-Custom_and_unique_headings_ID-44d2beaf + :END: + The first ones are dedicated to provide org-mode headings a fixed and + unique ID that won’t change over time. This code was taken from + [[https://writequit.org/articles/emacs-org-mode-generate-ids.html][https://writequit.org/articles/emacs-org-mode-generate-ids.html]]. The first + function’s job is to create these unique IDs + #+BEGIN_SRC emacs-lisp + (defun eos/org-id-new (&optional prefix) + "Create a new globally unique ID. - Now, let’s declare our prompt regexp and our prompt functions: - #+BEGIN_SRC emacs-lisp - (setq eshell-prompt-regexp "^[^#$\n]*[#$] " - eshell-prompt-function 'eshell/my-prompt) - #+END_SRC + An ID consists of two parts separated by a colon: + - a prefix + - a unique part that will be created according to + `org-id-method'. -** File extensions + PREFIX can specify the prefix, the default is given by the + variable `org-id-prefix'. However, if PREFIX is the symbol + `none', don't use any prefix even if `org-id-prefix' specifies + one. + + So a typical ID could look like \"Org-4nd91V40HI\"." + (let* ((prefix (if (eq prefix 'none) + "" + (concat (or prefix org-id-prefix) + "-"))) unique) + (if (equal prefix "-") + (setq prefix "")) + (cond + ((memq org-id-method + '(uuidgen uuid)) + (setq unique (org-trim (shell-command-to-string org-id-uuid-program))) + (unless (org-uuidgen-p unique) + (setq unique (org-id-uuid)))) + ((eq org-id-method 'org) + (let* ((etime (org-reverse-string (org-id-time-to-b36))) + (postfix (if org-id-include-domain + (progn + (require 'message) + (concat "@" + (message-make-fqdn)))))) + (setq unique (concat etime postfix)))) + (t (error "Invalid `org-id-method'"))) + (concat prefix (car (split-string unique "-"))))) + #+END_SRC + + Now, let’s see the function that will be used to get the custom id of a + heading at point. If the function does not detect any custom ID, then one + should be created and inserted. + #+BEGIN_SRC emacs-lisp + (defun eos/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 `eos/org-id-new'. In any case, the + CUSTOM_ID of the entry is returned." + (interactive) + (org-with-point-at pom + (let* ((orgpath (mapconcat #'identity (org-get-outline-path) "-")) + (heading (replace-regexp-in-string + "/\\|~" "" + (replace-regexp-in-string + " " "_" (if (string= orgpath "") + (org-get-heading t t t t) + (concat orgpath "-" (org-get-heading t t t t)))))) + (id (org-entry-get nil "CUSTOM_ID"))) + (cond + ((and id + (stringp id) + (string-match "\\S-" id)) id) + (create (setq id (eos/org-id-new (concat prefix heading))) + (org-entry-put pom "CUSTOM_ID" id) + (org-id-add-location id + (buffer-file-name (buffer-base-buffer))) + id))))) + #+END_SRC + + Finally, this is the function that gets called on file saves. If the + function detects ~auto-id:t~ among the org options in the ~#+OPTIONS:~ + header, then the above function is called. + #+BEGIN_SRC emacs-lisp + (defun eos/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" + (point-max) + t) + (org-map-entries (lambda () + (eos/org-custom-id-get (point) + 'create)))))) + #+END_SRC + + Let’s add a hook to the above function so it is called automatically on + save, and only in read-write functions. + #+BEGIN_SRC emacs-lisp + (add-hook 'org-mode-hook + (lambda () + (add-hook 'before-save-hook + (lambda () + (when (and (eq major-mode 'org-mode) + (eq buffer-read-only nil)) + (eos/org-add-ids-to-headlines-in-file)))))) + #+END_SRC + +**** Org babel languages + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_babel_languages-c062fc16 + :END: + One of the amazing features of org-mode is its literary programming + capacities by running code blocks from within Org-mode itself. But for that, + only a couple of languages are supported directly by Org-mode itself, and + they need to be activated. Here are the languages I activated in my Org-mode + configuration: + #+BEGIN_SRC emacs-lisp + (org-babel-do-load-languages + 'org-babel-load-languages + '((C . t) + (dot . t) + (emacs-lisp . t) + (gnuplot . t) + (latex . t) + (makefile . t) + (python . t) + (R . t) + (sass . t) + (scheme . t) + (shell . t))) + #+END_SRC + + Scheme requires a default implementation for geiser: + #+BEGIN_SRC emacs-lisp + (setq geiser-default-implementation 'racket) + #+END_SRC + + By the way, I wish to see source code behave the same way in the source + blocks as in their own major mode. Let’s tell Emacs so: + #+BEGIN_SRC emacs-lisp + (setq org-src-tab-acts-natively t) + #+END_SRC + +**** Org variables + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_variables-97587637 + :END: +***** User information + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_variables-User_information-6c7d5e3f + :END: + Some variables about myself need to be set so Org-mode knows what + information to include in exported files. + #+BEGIN_SRC emacs-lisp + (setq user-full-name "Lucien Cartier-Tilet" + user-real-login-name "Lucien Cartier-Tilet" + user-login-name "phundrak" + user-mail-address "lucien@phundrak.com") + #+END_SRC + +***** Visual settings + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_variables-Visual_settings-5d02f4c0 + :END: + Visually, I prefer to hide the markers of macros, so let’s do that: + #+BEGIN_SRC emacs-lisp + (setq org-hide-macro-markers t) + #+END_SRC + + I also have an issue where small dots precede my org headers. Let’s fix that: + #+BEGIN_SRC emacs-lisp + (setq org-hide-leading-stars nil + org-superstar-leading-bullet ?\s) + #+END_SRC + +***** Org behavior + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_variables-Org_behavior-0319db38 + :END: + Here is one behavior that I really want to see modified: the ability to use + ~M-RET~ without slicing the text the marker is on. + #+BEGIN_SRC emacs-lisp + (setq org-M-RET-may-split-line nil) + #+END_SRC + + I also have added a couple of custom structure templates for Org mode (>= + 9.3), mainly for source code blocks. + #+begin_src emacs-lisp + (add-to-list 'org-structure-template-alist '("L" . "src emacs-lisp")) + #+end_src + + Since Org 9.3, Org no longer attempts to restore the window configuration + in the frame to which the user returns after editing a source block with + ~org-edit-src-code~. This means with the original value of + ~org-src-window-setup~ (~reorganize-frame~), the current frame will be + split in two between the original org window and the source window, and + once we quit the source window only the org window will remain. This is not + a desired behavior for me, so I chose to set this variable to + ~split-window-right~ in order to keep my windows organization and have a + similar behavior to the old one. + #+BEGIN_SRC emacs-lisp + (setq org-src-window-setup 'split-window-right) + ;; (setq org-src-window-setup 'split-window-below) + #+END_SRC + + However, it is not rare that I want to change that for an horizontal split, + which can be achieved with the value ~split-window-below~. Thus, I have + made this function that allows me to switch between the (default) vertical + split and the horizontal split. + #+BEGIN_SRC emacs-lisp + (defun phundrak/toggle-org-src-window-split () + "This function allows the user to toggle the behavior of + `org-edit-src-code'. If the variable `org-src-window-setup' has + the value `split-window-right', then it will be changed to + `split-window-below'. Otherwise, it will be set back to + `split-window-right'" + (interactive) + (if (equal org-src-window-setup 'split-window-right) + (setq org-src-window-setup 'split-window-below) + (setq org-src-window-setup 'split-window-right)) + (message "Org-src buffers will now split %s" + (if (equal org-src-window-setup 'split-window-right) + "vertically" + "horizontally"))) + #+END_SRC + + Lastly, I know this can be a terrible idea, but I want Emacs to just + evaluate Org code blocks without asking me. Of course, this could + represent some big security issue if not careful enough, but I generaly + just open my own org files. + #+BEGIN_SRC emacs-lisp + (setq org-confirm-babel-evaluate nil) + #+END_SRC + +***** Miscellaneous + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_variables-Miscellaneous-ddcb568a + :END: + When creating a link to an Org flie, I want to create an ID only if the + link is created interactively, and only if there is no custom ID already + created. + #+BEGIN_SRC emacs-lisp + (setq org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id) + #+END_SRC + +**** Org files exports + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_files_exports-1e194169 + :END: + When it comes to exports, I want the LaTeX and PDF exports to be done with + XeLaTeX only. This implies the modification of the following variable: + #+BEGIN_SRC emacs-lisp + (setq org-latex-compiler "xelatex") + #+END_SRC + + I also want to get by default ~minted~ for LaTeX listings so I can have + syntax highlights: + #+BEGIN_SRC emacs-lisp + (setq org-latex-listings 'minted) + #+END_SRC + + The default packages break my LaTeX exports: for some reasons, images are + not loaded and exported in PDFs, so I needed to redifine the default + packages excluding the one that broke my exports. I also added two default + packages, ~minted~ and ~xeCJK~ for syntax highlighting and Japanese (and + additionally Chinese and Korean) support. + #+BEGIN_SRC emacs-lisp + (setq org-latex-default-packages-alist '(("" "graphicx" t) + ("T1" "fontspec" t ("pdflatex")) + ("" "longtable" nil) + ("" "wrapfig" nil) + ("" "rotating" nil) + ("normalem" "ulem" t) + ("" "amsmath" t) + ("" "textcomp" t) + ("" "amssymb" t) + ("" "capt-of" nil) + ("" "minted" nil) + ("" "xeCJK" nil) + ("" "hyperref" nil))) + #+END_SRC + + By the way, reference links in LaTeX should be written in this format: + #+BEGIN_SRC emacs-lisp + (setq org-export-latex-hyperref-format "\\ref{%s}") + #+END_SRC + + When it comes to the export itself, the latex file needs to be processed + several times through XeLaTeX. + #+BEGIN_SRC emacs-lisp + (setq org-latex-pdf-process + '("xelatex -shell-escape -interaction nonstopmode -output-directory %o %f" + "xelatex -shell-escape -interaction nonstopmode -output-directory %o %f" + "xelatex -shell-escape -interaction nonstopmode -output-directory %o %f")) + #+END_SRC + + For Reveal.JS exports, I need to set where to find the framework by default: + #+BEGIN_SRC emacs-lisp + (setq org-reveal-root "file:///home/phundrak/fromGIT/reveal.js") + #+END_SRC + + I also want to disable by default behavior of ~^~ and ~_~ for only one + character, making it compulsory to use instead ~^{}~ and ~_{}~ respectively. + This is due to my frequent usage of the underscore in my org files as a + regular character and not a markup one. So, let’s disable it: + #+BEGIN_SRC emacs-lisp + (setq org-use-sub-superscripts (quote {})) + #+END_SRC + + On HTML exports, Org-mode tries to include a validation link for the + exported HTML. Let’s disable that since I never use it. + #+BEGIN_SRC emacs-lisp + (setq org-html-validation-link nil) + #+END_SRC + +**** Custom LaTeX formats + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Custom_LaTeX_formats-8e8dca1c + :END: + I currently have two custom formats for my Org-mode exports: one for general + use (initialy for my conlanging files, hence its ~conlang~ name), and one + for beamer exports. + + Below is the declaration of the ~conlang~ LaTeX class: + #+NAME: org-latex-class-conlang + #+BEGIN_SRC emacs-lisp :tangle no + '("conlang" + "\\documentclass{book}" + ("\\chapter{%s}" . "\\chapter*{%s}") + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}")) + #+END_SRC + + And here is the declaration of the ~beamer~ class: + #+NAME: org-latex-class-beamer + #+BEGIN_SRC emacs-lisp :tangle no + `("beamer" + ,(concat "\\documentclass[presentation]{beamer}\n" + "[DEFAULT-PACKAGES]" + "[PACKAGES]" + "[EXTRA]\n") + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}")) + #+END_SRC + + Both these classes have to be added to ~org-latex-classes~ like so: + #+BEGIN_SRC emacs-lisp :noweb yes + (eval-after-load "ox-latex" + '(progn + (add-to-list 'org-latex-classes + <> + ) + (add-to-list 'org-latex-classes + <> + ))) + #+END_SRC + +**** Org agenda + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_agenda-53f9d319 + :END: + One awesome feature of Org mode is the agenda. By default, my agendas are + stored in =~/org/agenda=. + #+BEGIN_SRC emacs-lisp + (setq org-agenda-files (list "~/org/agenda" "~/org/notes.org")) + #+END_SRC + + I also have a custom command in Org agenda to mark some tasks as daily + tasks with the =:DAILY:= tag,: + #+BEGIN_SRC emacs-lisp + (setq org-agenda-custom-commands + '(("h" "Daily habits" + ((agenda "")) + ((org-agenda-show-log t) + (org-agenda-ndays 7) + (org-agenda-log-mode-items '(state)) + (org-agenda-skip-function + '(org-agenda-skip-entry-if 'notregexp + ":DAILY:")))) + ("Y" "Yearly events" + ((agenda "")) + ((org-agenda-show-log t) + (org-agenda-ndays 365) + (org-agenda-log-mode-items '(state)) + (org-agenda-skip-entry-if 'notregexp + ":YEARLY:"))))) + #+END_SRC + +**** Org capture + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-f58979cf + :END: + Org-capture is an amazing feature of Org-mode which allows me to quickly + save links, resources, reminders, and notes in neatly organized org files. + Here they are described: + #+BEGIN_SRC emacs-lisp + (setq + org-conlanging-file "~/org/conlanging.org" + org-default-notes-file "~/org/notes.org" + org-journal-file "~/org/journal.org" + org-linguistics-notes-file "~/org/linguistics-notes.org" + org-novel-notes-file "~/org/novel-notes.org" + org-private-agenda-file "~/org/agenda/private.org" + org-school-agenda-file "~/org/agenda/school.org" + org-wordbuilding-file "~/org/worldbuilding.org") + #+END_SRC + + With Spacemacs, an Org capture can be invoked with the shortcut ~SPC a o c~. + It will then ask which template I wish to use. In the table below are + described the shortcuts that are available after ~SPC a o c~ is invoked. The + /name/ will be the one displayed in Org capture’s interface, the /title/ is + the headline where to save the capture (if it does not differ from the + capture’s name, the cell will be blank). The /insertion mode/ tells Emacs + how to add the capture to the /file/, using which /template/. A line with no + insertion mode, file, or template is just a category. All of the following + insert entries to their org files, that is a new org node with a headline + and some content. + #+NAME: org-capture-shortcuts-table + | Shortcut | Name | Title | Insertion mode | file | template | + |----------+---------------+----------+----------------+-------------------------+--------------------------| + | e | Email | | | | | + | ew | Write Email | Emails | file+headline | org-default-notes-file | emails.orgcaptmpl | + | j | Journal | | file+datetree | org-journal-file | journal.orgcaptmpl | + | l | Link | | | | | + | ll | General | | file+headline | org-default-notes-file | | + | ly | YouTube | | file+headline | org-default-notes-file | youtube.orgcaptmpl | + | L | Protocol Link | Link | file+headline | org-default-notes-file | protocol-link.orgcaptmpl | + | n | Notes | | | | | + | nc | Conlanging | Note | file+headline | org-conlanging-file | notes.orgcaptmpl | + | nn | General | | file+headline | org-default-notes-file | notes.orgcaptmpl | + | nN | Novel | Note | file+headline | org-novel-notes-file | notes.orgcaptmpl | + | nq | Quote | | file+headline | org-default-notes-file | notes-quote.orgcaptmpl | + | nw | Worldbuilding | Note | file+headline | org-wordbuilding-file | notes.orgcaptmpl | + | N | Novel | | | | | + | Ni | Ideas | | file+headline | org-novel-notes-file | notes.orgcaptmpl | + | p | Protocol | Link | file+headline | org-default-notes-file | protocol.orgcaptmpl | + | r | Resources | | | | | + | rc | Conlanging | Resource | file+headline | org-conlanging-file | resource.orgcaptmpl | + | re | Emacs | | file+headline | org-default-notes-file | resource.orgcaptmpl | + | ri | Informatique | | file+headline | org-default-notes-file | resource.orgcaptmpl | + | rl | Linguistics | | file+headline | org-default-notes-file | resource.orgcaptmpl | + | rw | Worldbuilding | Resource | file+headline | org-wordbuilding-file | resource.orgcaptmpl | + | t | Tasks | | | | | + | tb | Birthday | | file+headline | org-private-agenda-file | birthday.orgcaptmpl | + | te | Event | | file+headline | org-private-agenda-file | event.orgcaptmpl | + | th | Health | | file+headline | org-private-agenda-file | health.orgcaptmpl | + | ti | Informatique | | file+headline | org-private-agenda-file | informatique.orgcaptmpl | + + The following code snipped is not tangled into my configuration file, but + instead creates the equivalent to the table above into EmacsLisp code found + in the next code snippet. + #+NAME: org-capture-shortcut-gen + #+BEGIN_SRC emacs-lisp :tangle no :noweb yes :var table=org-capture-shortcuts-table :exports code :cache yes :results replace + (mapconcat (lambda (entry) + (let* ((shortcut (nth 0 entry)) + (name (nth 1 entry)) + (title (nth 2 entry)) + (insertmode (nth 3 entry)) + (fileinsert (nth 4 entry)) + (sourceorg (nth 5 entry))) + (if (string= "" insertmode) + (format "(\"%s\" \"%s\")" shortcut name) + (concat (format "(\"%s\" \"%s\" entry\n" shortcut name) + (format " (%s %s%s)\n" insertmode fileinsert + (if (string= "file+datetree" insertmode) "" + (format " \"%s\"" (if (string= "" title) name title)))) + (format " (file \"~/org/capture/%s\"))" sourceorg)))) ) + table "\n") + #+END_SRC + + #+RESULTS[5826faa0521c58664ddeedcf44b88910dbd344b6]: org-capture-shortcut-gen + #+begin_example + ("e" "Email") + ("ew" "Write Email" entry + (file+headline org-default-notes-file "Emails") + (file "~/org/capture/emails.orgcaptmpl")) + ("j" "Journal" entry + (file+datetree org-journal-file) + (file "~/org/capture/journal.orgcaptmpl")) + ("l" "Link") + ("ll" "General" entry + (file+headline org-default-notes-file "General") + (file "~/org/capture/")) + ("ly" "YouTube" entry + (file+headline org-default-notes-file "YouTube") + (file "~/org/capture/youtube.orgcaptmpl")) + ("L" "Protocol Link" entry + (file+headline org-default-notes-file "Link") + (file "~/org/capture/protocol-link.orgcaptmpl")) + ("n" "Notes") + ("nc" "Conlanging" entry + (file+headline org-conlanging-file "Note") + (file "~/org/capture/notes.orgcaptmpl")) + ("nn" "General" entry + (file+headline org-default-notes-file "General") + (file "~/org/capture/notes.orgcaptmpl")) + ("nN" "Novel" entry + (file+headline org-novel-notes-file "Note") + (file "~/org/capture/notes.orgcaptmpl")) + ("nq" "Quote" entry + (file+headline org-default-notes-file "Quote") + (file "~/org/capture/notes-quote.orgcaptmpl")) + ("nw" "Worldbuilding" entry + (file+headline org-wordbuilding-file "Note") + (file "~/org/capture/notes.orgcaptmpl")) + ("N" "Novel") + ("Ni" "Ideas" entry + (file+headline org-novel-notes-file "Ideas") + (file "~/org/capture/notes.orgcaptmpl")) + ("p" "Protocol" entry + (file+headline org-default-notes-file "Link") + (file "~/org/capture/protocol.orgcaptmpl")) + ("r" "Resources") + ("rc" "Conlanging" entry + (file+headline org-conlanging-file "Resource") + (file "~/org/capture/resource.orgcaptmpl")) + ("re" "Emacs" entry + (file+headline org-default-notes-file "Emacs") + (file "~/org/capture/resource.orgcaptmpl")) + ("ri" "Informatique" entry + (file+headline org-default-notes-file "Informatique") + (file "~/org/capture/resource.orgcaptmpl")) + ("rl" "Linguistics" entry + (file+headline org-default-notes-file "Linguistics") + (file "~/org/capture/resource.orgcaptmpl")) + ("rw" "Worldbuilding" entry + (file+headline org-wordbuilding-file "Resource") + (file "~/org/capture/resource.orgcaptmpl")) + ("t" "Tasks") + ("tb" "Birthday" entry + (file+headline org-private-agenda-file "Birthday") + (file "~/org/capture/birthday.orgcaptmpl")) + ("te" "Event" entry + (file+headline org-private-agenda-file "Event") + (file "~/org/capture/event.orgcaptmpl")) + ("th" "Health" entry + (file+headline org-private-agenda-file "Health") + (file "~/org/capture/health.orgcaptmpl")) + ("ti" "Informatique" entry + (file+headline org-private-agenda-file "Informatique") + (file "~/org/capture/informatique.orgcaptmpl")) + #+end_example + + Below you can find the equivalent code as described above. + #+BEGIN_SRC emacs-lisp :noweb yes + (setq + org-capture-templates + '( + <> + )) + #+END_SRC + + You may notice a capture entry for my journal, and this is due to the fact I + do not use ~org-journal~ anymore: it was too overpowered for me, and I + prefer to keep it simple with a single file. And as you can see, and unlike + a lot of other Emacs configurations, the content of the template is not set + in the variable, but in external files which can be modified freely as + actual Org buffers instead of trying to get a proper one with loads of ~\n~ + characters and such. All these templates are declared below. + + In the next sub-sections will be described my org capture templates. These + are not tangled into my Emacs configuration files, but into separate + ~.orgcaptmpl~ files stored into =~/org/capture/=. + +***** Emails + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Emails-d87336fe + :END: + This is my template for a new Email: + #+BEGIN_SRC org :mkdir yes :tangle ~/org/capture/email.orgcaptmpl + ,** TODO [#A] Write Email + SCHEDULED: %^t + :PROPERTIES: + :CAPTURED: %U + :END: + From: Lucien Cartier-Tilet + To: %^{Recipient} + Subject: %^{Object} + --text follows this line-- + %? + -- + Lucien “Phundrak” Cartier-Tilet + https://phundrak.com (Français) + https://en.phundrak.com (English) + + Sent from a Free and Open-Source Linux operating system with GNU/Emacs + #+END_SRC + + I use it in case my computer is not yet connected to the internet and I + need to already write the email so I can send it later. All I will need to + to afterwards will be to copy and paste my capture in a new message buffer + and send it once I am back online. This is exported to + =~/org/capture/email.orgcaptmpl=. + +***** Journal + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Journal-9916f9bf + :END: + This template is quite simple: it creates a new entry with the current + timestamp as its title, a brief title of my choosing, and then I can write + whatever I wish to write. This is exported to + =~/org/capture/journal.orgcaptmpl=. + #+BEGIN_SRC org :mkdir yes :tangle ~/org/capture/journal.orgcaptmpl + ,* %U %^{Title} + %? + #+END_SRC + +***** Notes + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Notes-4b4c10aa + :END: + This template is used for taking note about various subjects that can go + from conlanging to development. I wrote it so I can know from where this + capture was made and when, and it even supports text that was highlighted + in Emacs that will be inserted in a quote block. This is exported to + =~/org/capture/notes.orgcaptmpl=. + #+BEGIN_SRC org :mkdir yes :tangle ~/org/capture/notes.orgcaptmpl + ,* %^{Title} + :PROPERTIES: + :CAPTURED: %U + :END: + %? + #+END_SRC + + + #+BEGIN_SRC org :mkdir yes :tangle ~/org/capture/notes-quote.orgcaptmpl + ,* %^{Title} + :PROPERTIES: + :CAPTURED: %U + :END: + Possible inspiration: + ,#+begin_quote + %i + ,#+end_quote + + %? + #+END_SRC + +***** Protocol + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Protocol-ec45ec49 + :END: + This capture is used when received through org-protocol, with the + Org-protocol Extension for Firefox. It allows me to save in a quote block + what I’ve highlighted, as well as the link of the webpage on which my saved + content was highlighted. This file is exported to + =~/org/capture/protocol.orgcaptmpl=. + #+BEGIN_SRC org :mkdir yes :tangle ~/org/capture/protocol.orgcaptmpl + ,* TODO [#C] %^{Title} + :PROPERTIES: + :CAPTURED: %U + :LINK: %:link + :TITLE: %:description + :END: + ,#+begin_quote + %i + ,#+end_quote + + %? + #+END_SRC + + This next capture template is used only when a link is sent to Emacs and no + content was highlighted. + #+BEGIN_SRC org :mkdir yes :tangle ~/org/capture/protocol-link.orgcaptmpl + ,* TODO [#C] Link: %^{Title} + :PROPERTIES: + :CAPTURED: %U + :LINK: %:link + :TITLE: %:description + :END: + %? + #+END_SRC + +***** Resources + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Resources-b23bfbd0 + :END: + This is the default template for resources, which generally are located on + the Internet. By default, I give them the lowest priority, because although + this is something for me to remember later, it is not by default important. + You can see in the properties I record when the capture happened, and what + the link is. The title of the capture is a summary of what this is, while + the body of the capture is a more detailed explanation of what I capture, + why, and how it could be useful to me. + #+BEGIN_SRC org :mkdir yes :tangle ~/org/capture/resource.orgcaptmpl + ,* TODO [#C] %^{Title} + :PROPERTIES: + :CAPTURED: %U + :LINK: %^{Link} + :END: + %? + #+END_SRC + +***** Tasks + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Tasks-3fcf382a + :END: + +****** Computers and stuff + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Tasks-Computers_and_stuff-a4eef8e3 + :END: + One type of task I often capture is related to my servers or thing about + computers in general. With this, I can capture a task for which I will + either set a schedule or a deadline. + #+BEGIN_SRC org :mkdir yes :tangle ~/org/capture/informatique.orgcaptmpl + ,* TODO %^{Title} + %^{Scheduled or Deadline?||SCHEDULED||DEADLINE}: %^t + :PROPERTIES: + :CATEGORY: %^{Category} + :END: + %? + #+END_SRC + +****** Health + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Tasks-Health-74f8f338 + :END: + This capture is rarely used (I’m lucky to have a good health), but it can + be useful. + #+BEGIN_SRC org :mkdir yes :tangle ~/org/capture/health.orgcaptmpl + ,* %^{Title} + SCHEDULED: %^t + + %? + #+END_SRC + +****** Birthdays + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Tasks-Birthdays-ec3b27be + :END: + This capture is used to store new birthdays I have to remember. They are + set to be repeated yearly. + #+BEGIN_SRC org :mkdir yes :tangle ~/org/capture/birthday.orgcaptmpl + ,* %^{Name} + SCHEDULED: %^t + #+END_SRC + +****** Events + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Tasks-Events-7f0f8dee + :END: + #+BEGIN_SRC org :mkdir yes :tangle ~/org/capture/event.orgcaptmpl + ,* %^{Title} + %^{Scheduled or deadline?||SCHEDULED||DEADLINE}: %^t + %? + #+END_SRC + +***** Links + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Links-586a6b2a + :END: +****** General + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Links-General-1f0732db + :END: + #+BEGIN_SRC org :mkdir yes :tangle ~/org/capture/link.orgcaptmpl + ,* TODO [#C] %^{Title} + :PROPERTIES: + :CAPTURED: %U + :LINK: %^{Link} + :END: + %? + #+END_SRC + +****** YouTube + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Links-YouTube-b89fe20e + :END: + #+BEGIN_SRC org :mkdir yes :tangle ~/org/capture/youtube.orgcaptmpl + ,* TODO [#C] %^{Title} + :PROPERTIES: + :CAPTURED: %U + :AUTHOR: %^{Author} + :LINK: %^{Link} + :END: + %? + #+END_SRC + +**** Org projects + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_projects-5be088cd + :END: + Another great features of Org-mode is the Org projects that allow the user + to easily publish a bunch of org files to a remote location. Here is the + current declaration of my projects, which will be detailed later: + #+BEGIN_SRC emacs-lisp :noweb yes + (setq org-publish-project-alist + '( + <> + <> + <> + <> + <> + <> + <>)) + #+END_SRC + +***** Configuration website + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_projects-Configuration_website-79bd0468 + :END: + #+NAME: org-proj-config-html + #+BEGIN_SRC emacs-lisp :tangle no + ("config-website-org" + :base-directory "~/org/config/" + :base-extension "org" + :exclude "\\./\\(CONTRIB\\|head\\|temp\\|svg-ink\\).*" + :publishing-directory "/ssh:Tilo:~/www/phundrak.com/config" + :recursive t + :language "en" + :publishing-function org-html-publish-to-html + :headline-levels 5 + :auto-sitemap t + :auto-preamble t) + #+END_SRC + + And lastly, we have the component for all the static files needed to run + the website: + #+NAME: org-proj-config-static + #+BEGIN_SRC emacs-lisp :tangle no + ("config-website-static" + :base-directory "~/org/config/" + :base-extension "png\\|jpg\\|gif\\|webp\\|svg\\|jpeg\\|ttf\\|woff\\|txt\\|epub\\|md" + :publishing-directory "/ssh:Tilo:~/www/phundrak.com/config" + :recursive t + :language "en" + :publishing-function org-publish-attachment) + #+END_SRC + + The project is then defined like so: + #+NAME: org-proj-config + #+BEGIN_SRC emacs-lisp :tangle no + ("config-website" + :components ("config-website-org" + "config-website-static")) + #+END_SRC + +***** Linguistics website + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Org-mode-Org_projects-Linguistics_website-34b8d4e7 + :END: + In my case, I only have my linguistics website, made out of three projects. + The first component is the one generating the HTML files from the org + files. + #+NAME: org-proj-lang-html + #+BEGIN_SRC emacs-lisp :tangle no + ("langue-phundrak-com-org" + :base-directory "~/Documents/conlanging/content/" + :base-extension "org" + :exclude "\\./\\(CONTRIB\\|README\\|head\\|temp\\|svg-ink\\).*" + :publishing-directory "/ssh:Tilo:~/www/phundrak.com/langue/" + :recursive t + :language "fr" + :publishing-function org-html-publish-to-html + :headline-levels 5 + :auto-sitemap t + :auto-preamble t) + #+END_SRC + + We also have the component for the LaTeX and PDF part of the website: + #+NAME: org-proj-lang-pdf + #+BEGIN_SRC emacs-lisp :tangle no + ("langue-phundrak-com-pdf" + :base-directory "~/Documents/conlanging/content/" + :base-extension "org" + :exclude "\\./\\(CONTRIB\\|README\\|index\\|head\\|temp\\|svg-ink\\).*" + :publishing-directory "/ssh:Tilo:~/www/phundrak.com/langue/" + :recursive t + :language "fr" + :publishing-function org-latex-publish-to-pdf + :headline-levels 5 + :auto-preamble t) + #+END_SRC + + And lastly, we have the component for all the static files needed to run + the website: + #+NAME: org-proj-lang-static + #+BEGIN_SRC emacs-lisp :tangle no + ("langue-phundrak-com-static" + :base-directory "~/Documents/conlanging/content/" + :base-extension "png\\|jpg\\|gif\\|webp\\|svg\\|jpeg\\|ttf\\|woff\\|txt\\|epub" + :publishing-directory "/ssh:Tilo:~/www/phundrak.com/langue/" + :recursive t + :language "fr" + :publishing-function org-publish-attachment) + #+END_SRC + + The project is then defined like so: + #+NAME: org-proj-lang + #+BEGIN_SRC emacs-lisp :tangle no + ("langue-phundrak-com" + :components ("langue-phundrak-com-org" + "langue-phundrak-com-static" + "langue-phundrak-com-pdf")) + #+END_SRC + + # Don’t delete this, this code block is here to wrap the org configuration + #+BEGIN_SRC emacs-lisp :exports none + ) + #+END_SRC + +** Editing and modes :PROPERTIES: - :CUSTOM_ID: User_Configuration-File_extensions-f76fe752 + :CUSTOM_ID: User_Configuration-Editing_and_modes-7dbaf258 :END: - Sometimes, Emacs doesn’t recognize or misrecognizes some extensions, - resulting in a wrong mode set for said file. Let’s fix that by associating - the extension with the desired mode: - #+BEGIN_SRC emacs-lisp - (dolist (e '(("xml" . web-mode) - ("xinp" . web-mode) - ("aiml" . web-mode) - ("C" . c++-mode) - ("dconf" . conf-mode) - ("yy" . bison-mode) - ("ll" . flex-mode) - ("s" . asm-mode) - ("pl" . prolog-mode) - ("l" . scheme-mode) - ("vs" . glsl-mode) - ("fs" . glsl-mode))) - (push (cons (concat "\\." - (car e) - "\\'") (cdr e)) - auto-mode-alist)) - #+END_SRC - - We also have a couple of extensions which should all be in ~conf-unix-mode~, - let’s indicate that to Emacs: - #+BEGIN_SRC emacs-lisp - (dolist (e '("service" "timer" "target" "mount" "automount" - "slice" "socket" "path" "netdev" "network" - "link")) - (push (cons (concat "\\." e "\\'") 'conf-unix-mode) - auto-mode-alist)) - #+END_SRC - -** LSP - :PROPERTIES: - :CUSTOM_ID: User_Configuration-LSP-4f8aa691 - :END: - When it comes to the LSP layer, there are some options which are not enabled - by default that I want to use, especially some modes I want to take advantage - of. This is why I enable first the ~lsp-treemacs-sync-mode~ so treemacs is - LSP aware: - #+BEGIN_SRC emacs-lisp - (lsp-treemacs-sync-mode 1) - #+END_SRC - - I also enable some layers related to ~dap~, the Debug Adapter Protocol, which - works really nicely with LSP. Let’s enable Dap’s modes: - #+BEGIN_SRC emacs-lisp - (dap-mode 1) - (dap-ui-mode 1) - (dap-tooltip-mode 1) - #+END_SRC - - Finally, I also want the documentation tooltip to show up when the cursor is - above a documented piece of code or symbol. Let’s enable that too: - #+BEGIN_SRC emacs-lisp - (tooltip-mode 1) - #+END_SRC - -** Mu4e - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Mu4e-f3df8e9e - :END: - Mu4e is a frontend for mu, an email analyzer which sits on top of a Maildir - which gets updated with the ~mbsync~ command from ~isync~. It has a lot of - neat features, but I guess my favorite ones are: - 1. the search query feature - 2. being able to send an HTML email either to the browser - - Due to mu sitting on top of a Maildir, I need to tell mu4e where said maildir - is, and point it the trash, archive, and sent folders as well as the refresh - command and how frequently I want my emails to be refreshed. - #+BEGIN_SRC emacs-lisp - (setq mu4e-maildir "~/.mail" - mu4e-trash-folder "/Trash" - mu4e-refile-folder "/Archive" - mu4e-sent-folder "/Sent" - mu4e-drafts-folder "/Drafts" - mu4e-get-mail-command "mbsync -a" - mu4e-update-interval 60) - #+END_SRC - - The following also allows me to automatically include my signature in my - Emails, to view images in my Emacs buffers and to show me the address of my - contacts and not just their names. - #+BEGIN_SRC emacs-lisp - (setq mu4e-compose-signature-auto-include t - mu4e-view-show-images t - mu4e-view-prefer-html t - mu4e-view-show-addresses t) - #+END_SRC - - This source block is an example of the search queries in mu4e, and part of - the reason why I very much like mu4e: these bookmarks are actually defined by - search queries, but act as if they were just yet another type of custom inbox - you get with modern Email client (and often you don’t even get them). All - these bookmarks can be accessed through a shortcut on the main mu4e buffer, - prefixed by ~b~. So, for instance, my unread messages are accessed through - ~bu~. - #+BEGIN_SRC emacs-lisp - (setq mu4e-bookmarks - `(("maildir:/Inbox AND NOT flag:trashed" "Inbox" ?i) - ("maildir:/Sent" "Sent messages" ?s) - ("flag:unread AND NOT flag:trashed" "Unread messages" ?u) - ("date:today..now" "Today's messages" ?t) - ("date:7d..now" "Last 7 days" ?w) - ("date:1m..now" "Last month" ?m) - ("date:1y..now" "Last year" ?y) - ("flag:trashed" "Trash" ?T) - ("mime:image/*" "Messages with images" ?p))) - #+END_SRC - - In the header view, I’d like the name of my mailing lists to be clear. Mu4e - tries its best to provide them one, but it’s not always perfect, so let’s fix - that. - #+BEGIN_SRC emacs-lisp - (setq mu4e-user-mailing-lists - '(("ateliers-emacs.framalistes.org" . "EmacsFR") - ("CONLANG@LISTSERV.BROWN.EDU" . "Conlang") - ("AUXLANG@LISTSERV.BROWN.EDU" . "Auxlang"))) - #+END_SRC - - On new email arrival, Emacs can send the system a notification which will be - handled as any other notification received by the system and will display the - number of unread emails to the user; in my case, notifications are handled by - [[https://dunst-project.org/][dunst]] under i3, or AwesomeWM itself. - #+BEGIN_SRC emacs-lisp - (setq mu4e-enable-notifications t - mu4e-alert-email-notification-types '(count)) - (with-eval-after-load 'mu4e-alert - (mu4e-alert-set-default-style 'notifications)) - (add-hook 'mu4e-view-mode-hook 'visual-line-mode) - #+END_SRC - - Now this hook is added so I can get a maximal width for the text of my - emails, I really don’t like it when lines are kilometers long. I would like - instead to hook ~visual-line-mode~ and ~auto-fill-mode~, but for some reasons - Emacs throws an error when I add them, So I go with ~visual-fill-column-mode~ - instead. - #+BEGIN_SRC emacs-lisp - (add-hook 'mu4e-view-mode-hook 'visual-fill-column-mode) - #+END_SRC - - On modern-day computers, with wide screens almost everywhere, there is no - reason for the email buffer to open below the email directory and not on its - right, which is why I set the split view to be vertical instead of - horizontal. I also set the width the email directory should keep to 80 - characters (and I could go to 120, but that’s only good for my - ultra-widescreen), because 30 characters is way too f-ing low. - #+BEGIN_SRC emacs-lisp - (setq mu4e-split-view 'vertical - mu4e-headers-visible-columns 140) - #+END_SRC - - This is the setup I have for my SMTP mail server: I point Emacs’ SMTP - services to my private mail server on its SMTP port, which should be used - with a STARTTLS stream. And I tell Emacs this is the default way to send an - email. - #+BEGIN_SRC emacs-lisp - (setq smtpmail-smtp-server "mail.phundrak.com" - smtpmail-smtp-service 587 - smtpmail-stream-type 'starttls - message-send-mail-function 'smtpmail-send-it) - #+END_SRC - - I am unsure yet if this has any effect on mu4e, but this variable should - discourage mu4e from reading rich text emails and instead open them as plain - text. However, I do not wish to discourage opening HTML emails since I can - compile them to PDF or open them in the browser. - #+BEGIN_SRC emacs-lisp - (setq mm-discouraged-alternatives '("text/richtext")) - #+END_SRC - - I am still unsure about this variable and if it has an effect on mu4e, but I - wish to set a default web viewer for my HTML emails: w3m. This is not as - effective as sending the email in the browser or rendering it as a PDF file, - but it can be effective enough for some emails. - #+BEGIN_SRC emacs-lisp - (setq mm-text-html-renderer 'w3m) - #+END_SRC - -** Miscellaneous - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Miscellaneous-d230bc2f - :END: - I have a lot of variables that need to be set but don’t fall in any other - category, so I’ll collect them here. - - I have this regexp for detecting paragraphs. - #+BEGIN_SRC emacs-lisp - (setq paragraph-start "\f\\|[ \t]*$\\|[ \t]*[-+*] ") - #+END_SRC - - There is currently [[https://github.com/syl20bnr/evil-iedit-state/issues/27][an open issue]] with ~evil-iedit-state~ where exiting the - iedit state calls ~iedit-cleanup~ despite this function being renamed - ~iedit-lib-cleanup~. So, waiting for the fix to be pushed upstream, let’s - declare an alias so Spacemacs understands what I want to do when I hit ~ESC~ - while in iedit state. - #+BEGIN_SRC emacs-lisp - (defalias 'iedit-cleanup 'iedit-lib-cleanup) - #+END_SRC - -*** Evil - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Miscellaneous-Evil-ab8a36e3 - :END: - As a user of Evil, I’m sometimes pissed when I accidentally press ~C-u~ and - it gets me to the top of the document. So, let’s disable it: - #+BEGIN_SRC emacs-lisp - (setq evil-want-C-u-scroll nil) - #+END_SRC - *** Default modes :PROPERTIES: + :CUSTOM_ID: User_Configuration-Editing_and_modes-Default_modes-50d4e086 + :END: :CUSTOM_ID: User_Configuration-Miscellaneous-Default_modes-b9e1522c :END: Some buffers sometimes won’t have a default mode at all, such as the @@ -2056,6 +2701,54 @@ (setq edit-server-default-major-mode 'org-mode) #+END_SRC +*** Evil + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Editing_and_modes-Evil-3cedaaee + :END: + :CUSTOM_ID: User_Configuration-Miscellaneous-Evil-ab8a36e3 + :END: + As a user of Evil, I’m sometimes pissed when I accidentally press ~C-u~ and + it gets me to the top of the document. So, let’s disable it: + #+BEGIN_SRC emacs-lisp + (setq evil-want-C-u-scroll nil) + #+END_SRC + +*** File extensions + :PROPERTIES: + :CUSTOM_ID: User_Configuration-File_extensions-f76fe752 + :END: + Sometimes, Emacs doesn’t recognize or misrecognizes some extensions, + resulting in a wrong mode set for said file. Let’s fix that by associating + the extension with the desired mode: + #+BEGIN_SRC emacs-lisp + (dolist (e '(("xml" . web-mode) + ("xinp" . web-mode) + ("aiml" . web-mode) + ("C" . c++-mode) + ("dconf" . conf-mode) + ("yy" . bison-mode) + ("ll" . flex-mode) + ("s" . asm-mode) + ("pl" . prolog-mode) + ("l" . scheme-mode) + ("vs" . glsl-mode) + ("fs" . glsl-mode))) + (push (cons (concat "\\." + (car e) + "\\'") (cdr e)) + auto-mode-alist)) + #+END_SRC + + We also have a couple of extensions which should all be in ~conf-unix-mode~, + let’s indicate that to Emacs: + #+BEGIN_SRC emacs-lisp + (dolist (e '("service" "timer" "target" "mount" "automount" + "slice" "socket" "path" "netdev" "network" + "link")) + (push (cons (concat "\\." e "\\'") 'conf-unix-mode) + auto-mode-alist)) + #+END_SRC + *** Hooks :PROPERTIES: :CUSTOM_ID: User_Configuration-Miscellaneous-Hooks-86da2da0 @@ -2088,44 +2781,6 @@ markdown-mode-hook)) #+END_SRC -*** Pinentry - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Miscellaneous-Pinentry-95004d5a - :END: - Pinentry should use the ~loopback~ mode when communicating with GnuPG. Let’s - set it so: - #+BEGIN_SRC emacs-lisp - (setq epa-pinentry-mode 'loopback) - #+END_SRC - -*** Prettified symbols - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Miscellaneous-Prettified_symbols-da50f4a6 - :END: - Just because it is pleasing to the eye, some symbols in source code get - prettified into simpler symbols. Here is the list of symbols that are to be - prettified. You can see in the corresponding comment what symbol will be - displayed. - #+BEGIN_SRC emacs-lisp - (setq prettify-symbols-alist '(("lambda" . 955) ; λ - ("->" . 8594) ; → - ("<->" . 8596) ; ↔ - ("<-" . 8592) ; ← - ("=>" . 8658) ; ⇒ - ("<=>" . 8860) ; ⇔ - ("<=" . 8656) ; ⇐ - ("mapc" . 8614) ; ↦ - ("map" . 8614) ; ↦ - (">>" . 187) ; » - ("<<" . 171) ; « - )) - #+END_SRC - - Let’s enable this mode globally. - #+BEGIN_SRC emacs-lisp - (prettify-symbols-mode 1) - #+END_SRC - *** Twittering mode :PROPERTIES: :CUSTOM_ID: User_Configuration-Miscellaneous-Twittering_mode-b97d9327 @@ -2136,1065 +2791,41 @@ (setq twittering-use-master-password t) #+END_SRC -*** Wttr.in cities +*** Wrapping regions :PROPERTIES: - :CUSTOM_ID: User_Configuration-Miscellaneous-Wttr.in_cities-dd24f8c5 + :CUSTOM_ID: User_Configuration-Editing_and_modes-Wrapping_regions-2250281e :END: - Thanks to the wttrin package, I can get the weather forecast in Emacs for a - couple of cities. I just need to specify them to Emacs like so: + I really like the ~M-(~ keybinding for wrapping a selected region between + parenthesis. However, parenthesis are not everything (even in Lisp + dialects), and other wrappers could be nice. And they are! Here is how they + are declared: #+BEGIN_SRC emacs-lisp - (setq wttrin-default-cities '("Aubervilliers" "Paris" "Lyon" "Nonières" - "Saint Agrève")) + (global-set-key (kbd "M-[") 'insert-pair) + (global-set-key (kbd "M-{") 'insert-pair) + (global-set-key (kbd "M-<") 'insert-pair) + (global-set-key (kbd "M-'") 'insert-pair) + (global-set-key (kbd "M-`") 'insert-pair) + (global-set-key (kbd "M-\"") 'insert-pair) #+END_SRC -** Nov-mode - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Nov-mode-6f10765d - :END: - ~nov-mode~ is the mode used in the Epub reader. Here I will write a little - function that I will call through a hook each time I’m opening a new EPUB - file. - #+BEGIN_SRC emacs-lisp - (defun my-nov-font-setup () - (face-remap-add-relative 'variable-pitch :family "Charis SIL" - :size 16 - :height 1.0)) - #+END_SRC - Let’s bind this function to the ~nov-mode~ hook. By the way, we’ll also - enable the ~visual-line-mode~ here, just in case. - #+BEGIN_SRC emacs-lisp - (mapc (lambda (mode) - (add-hook 'nov-mode-hook mode)) - '('my-nov-font-setup 'visual-line-mode)) - #+END_SRC - Let’s also set the maximum length of the lines in ~nov-mode~: - #+BEGIN_SRC emacs-lisp - (setq nov-text-width 80) - #+END_SRC + For the record, this is from [[http://www.howardism.org/][Howard Abram]]’s [[https://github.com/howardabrams/dot-files][dotfiles]]. -** Projectile - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Projectile-06e580f0 - :END: - Projectile is an awesome utility which helps managing projects within Emacs. - It will automatically detect version controlled directories, and will by - default assume this is a project I can be working on. However, there are some - directories that are version controlled that I do not want to see in my list - of projects, namely all the cached AUR packages from my AUR helper, ~yay~. - They are all stored in the same parent directory, so let’s ignore that. I - will also make Emacs ignore all ~node_modules~ directories it could - encounter. And for some reason, =~/.config/emacs= is always in my projects - list (I now use XDG-compliant directories), so let’s also ignore that. - #+BEGIN_SRC emacs-lisp - (phundrak/add-all-to-list projectile-globally-ignored-directories - "~/.cache/yay/*" "node_modules" "~/.config/emacs") - #+END_SRC - -** Python - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Python-9cdd1b06 - :END: - Emacs throws me an error about the python interpreter, let’s silence it: - #+BEGIN_SRC emacs-lisp - (setq python-shell-completion-native-disabled-interpreters '("python")) - #+END_SRC - -** Org-mode - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-04ab8ad3 - :END: - Org-mode is probably one of the best if not the best Emacs feature I have - ever discovered. It is awesome for writing documents, regardless of the - format you need it to be exported to, for agenda management, and for literary - programming, such as with this document. - #+BEGIN_SRC emacs-lisp :tangle no - (with-eval-after-load 'org - ;; configuration goes here - ) - #+END_SRC - -# Don’t delete this, this code block is here to wrap the org configuration -#+BEGIN_SRC emacs-lisp :exports none - (with-eval-after-load 'org -#+END_SRC - -*** Custom org-mode functions - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Custom_org-mode_functions-f1726995 - :END: - We begin with a couple of custom functions that I use in my org-mode files. - -**** Custom and unique headings ID - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Custom_org-mode_functions-Custom_and_unique_headings_ID-44d2beaf - :END: - The first ones are dedicated to provide org-mode headings a fixed and - unique ID that won’t change over time. This code was taken from - [[https://writequit.org/articles/emacs-org-mode-generate-ids.html][https://writequit.org/articles/emacs-org-mode-generate-ids.html]]. The first - function’s job is to create these unique IDs - #+BEGIN_SRC emacs-lisp - (defun eos/org-id-new (&optional prefix) - "Create a new globally unique ID. - - An ID consists of two parts separated by a colon: - - a prefix - - a unique part that will be created according to - `org-id-method'. - - PREFIX can specify the prefix, the default is given by the - variable `org-id-prefix'. However, if PREFIX is the symbol - `none', don't use any prefix even if `org-id-prefix' specifies - one. - - So a typical ID could look like \"Org-4nd91V40HI\"." - (let* ((prefix (if (eq prefix 'none) - "" - (concat (or prefix org-id-prefix) - "-"))) unique) - (if (equal prefix "-") - (setq prefix "")) - (cond - ((memq org-id-method - '(uuidgen uuid)) - (setq unique (org-trim (shell-command-to-string org-id-uuid-program))) - (unless (org-uuidgen-p unique) - (setq unique (org-id-uuid)))) - ((eq org-id-method 'org) - (let* ((etime (org-reverse-string (org-id-time-to-b36))) - (postfix (if org-id-include-domain - (progn - (require 'message) - (concat "@" - (message-make-fqdn)))))) - (setq unique (concat etime postfix)))) - (t (error "Invalid `org-id-method'"))) - (concat prefix (car (split-string unique "-"))))) - #+END_SRC - - Now, let’s see the function that will be used to get the custom id of a - heading at point. If the function does not detect any custom ID, then one - should be created and inserted. - #+BEGIN_SRC emacs-lisp - (defun eos/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 `eos/org-id-new'. In any case, the - CUSTOM_ID of the entry is returned." - (interactive) - (org-with-point-at pom - (let* ((orgpath (mapconcat #'identity (org-get-outline-path) "-")) - (heading (replace-regexp-in-string - "/\\|~" "" - (replace-regexp-in-string - " " "_" (if (string= orgpath "") - (org-get-heading t t t t) - (concat orgpath "-" (org-get-heading t t t t)))))) - (id (org-entry-get nil "CUSTOM_ID"))) - (cond - ((and id - (stringp id) - (string-match "\\S-" id)) id) - (create (setq id (eos/org-id-new (concat prefix heading))) - (org-entry-put pom "CUSTOM_ID" id) - (org-id-add-location id - (buffer-file-name (buffer-base-buffer))) - id))))) - #+END_SRC - - Finally, this is the function that gets called on file saves. If the - function detects ~auto-id:t~ among the org options in the ~#+OPTIONS:~ - header, then the above function is called. - #+BEGIN_SRC emacs-lisp - (defun eos/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" - (point-max) - t) - (org-map-entries (lambda () - (eos/org-custom-id-get (point) - 'create)))))) - #+END_SRC - - Let’s add a hook to the above function so it is called automatically on - save, and only in read-write functions. - #+BEGIN_SRC emacs-lisp - (add-hook 'org-mode-hook - (lambda () - (add-hook 'before-save-hook - (lambda () - (when (and (eq major-mode 'org-mode) - (eq buffer-read-only nil)) - (eos/org-add-ids-to-headlines-in-file)))))) - #+END_SRC - -*** Org babel languages - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_babel_languages-c062fc16 - :END: - One of the amazing features of org-mode is its literary programming - capacities by running code blocks from within Org-mode itself. But for that, - only a couple of languages are supported directly by Org-mode itself, and - they need to be activated. Here are the languages I activated in my Org-mode - configuration: - #+BEGIN_SRC emacs-lisp - (org-babel-do-load-languages - 'org-babel-load-languages - '((C . t) - (dot . t) - (emacs-lisp . t) - (gnuplot . t) - (latex . t) - (makefile . t) - (python . t) - (R . t) - (sass . t) - (scheme . t) - (shell . t))) - #+END_SRC - - Scheme requires a default implementation for geiser: - #+BEGIN_SRC emacs-lisp - (setq geiser-default-implementation 'racket) - #+END_SRC - - By the way, I wish to see source code behave the same way in the source - blocks as in their own major mode. Let’s tell Emacs so: - #+BEGIN_SRC emacs-lisp - (setq org-src-tab-acts-natively t) - #+END_SRC - -*** Org variables - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_variables-97587637 - :END: -**** User information - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_variables-User_information-6c7d5e3f - :END: - Some variables about myself need to be set so Org-mode knows what - information to include in exported files. - #+BEGIN_SRC emacs-lisp - (setq user-full-name "Lucien Cartier-Tilet" - user-real-login-name "Lucien Cartier-Tilet" - user-login-name "phundrak" - user-mail-address "lucien@phundrak.com") - #+END_SRC - -**** Visual settings - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_variables-Visual_settings-5d02f4c0 - :END: - Visually, I prefer to hide the markers of macros, so let’s do that: - #+BEGIN_SRC emacs-lisp - (setq org-hide-macro-markers t) - #+END_SRC - - I also have an issue where small dots precede my org headers. Let’s fix that: - #+BEGIN_SRC emacs-lisp - (setq org-hide-leading-stars nil - org-superstar-leading-bullet ?\s) - #+END_SRC - -**** Org behavior - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_variables-Org_behavior-0319db38 - :END: - Here is one behavior that I really want to see modified: the ability to use - ~M-RET~ without slicing the text the marker is on. - #+BEGIN_SRC emacs-lisp - (setq org-M-RET-may-split-line nil) - #+END_SRC - - I also have added a couple of custom structure templates for Org mode (>= - 9.3), mainly for source code blocks. - #+begin_src emacs-lisp - (add-to-list 'org-structure-template-alist '("L" . "src emacs-lisp")) - #+end_src - - Since Org 9.3, Org no longer attempts to restore the window configuration - in the frame to which the user returns after editing a source block with - ~org-edit-src-code~. This means with the original value of - ~org-src-window-setup~ (~reorganize-frame~), the current frame will be - split in two between the original org window and the source window, and - once we quit the source window only the org window will remain. This is not - a desired behavior for me, so I chose to set this variable to - ~split-window-right~ in order to keep my windows organization and have a - similar behavior to the old one. - #+BEGIN_SRC emacs-lisp - (setq org-src-window-setup 'split-window-right) - ;; (setq org-src-window-setup 'split-window-below) - #+END_SRC - - However, it is not rare that I want to change that for an horizontal split, - which can be achieved with the value ~split-window-below~. Thus, I have - made this function that allows me to switch between the (default) vertical - split and the horizontal split. - #+BEGIN_SRC emacs-lisp - (defun phundrak/toggle-org-src-window-split () - "This function allows the user to toggle the behavior of - `org-edit-src-code'. If the variable `org-src-window-setup' has - the value `split-window-right', then it will be changed to - `split-window-below'. Otherwise, it will be set back to - `split-window-right'" - (interactive) - (if (equal org-src-window-setup 'split-window-right) - (setq org-src-window-setup 'split-window-below) - (setq org-src-window-setup 'split-window-right)) - (message "Org-src buffers will now split %s" - (if (equal org-src-window-setup 'split-window-right) - "vertically" - "horizontally"))) - #+END_SRC - -**** Miscellaneous - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_variables-Miscellaneous-ddcb568a - :END: - When creating a link to an Org flie, I want to create an ID only if the - link is created interactively, and only if there is no custom ID already - created. - #+BEGIN_SRC emacs-lisp - (setq org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id) - #+END_SRC - -*** Org files exports - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_files_exports-1e194169 - :END: - When it comes to exports, I want the LaTeX and PDF exports to be done with - XeLaTeX only. This implies the modification of the following variable: - #+BEGIN_SRC emacs-lisp - (setq org-latex-compiler "xelatex") - #+END_SRC - - I also want to get by default ~minted~ for LaTeX listings so I can have - syntax highlights: - #+BEGIN_SRC emacs-lisp - (setq org-latex-listings 'minted) - #+END_SRC - - The default packages break my LaTeX exports: for some reasons, images are - not loaded and exported in PDFs, so I needed to redifine the default - packages excluding the one that broke my exports. I also added two default - packages, ~minted~ and ~xeCJK~ for syntax highlighting and Japanese (and - additionally Chinese and Korean) support. - #+BEGIN_SRC emacs-lisp - (setq org-latex-default-packages-alist '(("" "graphicx" t) - ("T1" "fontspec" t ("pdflatex")) - ("" "longtable" nil) - ("" "wrapfig" nil) - ("" "rotating" nil) - ("normalem" "ulem" t) - ("" "amsmath" t) - ("" "textcomp" t) - ("" "amssymb" t) - ("" "capt-of" nil) - ("" "minted" nil) - ("" "xeCJK" nil) - ("" "hyperref" nil))) - #+END_SRC - - By the way, reference links in LaTeX should be written in this format: - #+BEGIN_SRC emacs-lisp - (setq org-export-latex-hyperref-format "\\ref{%s}") - #+END_SRC - - When it comes to the export itself, the latex file needs to be processed - several times through XeLaTeX. - #+BEGIN_SRC emacs-lisp - (setq org-latex-pdf-process - '("xelatex -shell-escape -interaction nonstopmode -output-directory %o %f" - "xelatex -shell-escape -interaction nonstopmode -output-directory %o %f" - "xelatex -shell-escape -interaction nonstopmode -output-directory %o %f")) - #+END_SRC - - For Reveal.JS exports, I need to set where to find the framework by default: - #+BEGIN_SRC emacs-lisp - (setq org-reveal-root "file:///home/phundrak/fromGIT/reveal.js") - #+END_SRC - - I also want to disable by default behavior of ~^~ and ~_~ for only one - character, making it compulsory to use instead ~^{}~ and ~_{}~ respectively. - This is due to my frequent usage of the underscore in my org files as a - regular character and not a markup one. So, let’s disable it: - #+BEGIN_SRC emacs-lisp - (setq org-use-sub-superscripts (quote {})) - #+END_SRC - - On HTML exports, Org-mode tries to include a validation link for the - exported HTML. Let’s disable that since I never use it. - #+BEGIN_SRC emacs-lisp - (setq org-html-validation-link nil) - #+END_SRC - -*** Custom LaTeX formats - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Custom_LaTeX_formats-8e8dca1c - :END: - I currently have two custom formats for my Org-mode exports: one for general - use (initialy for my conlanging files, hence its ~conlang~ name), and one - for beamer exports. - - Below is the declaration of the ~conlang~ LaTeX class: - #+NAME: org-latex-class-conlang - #+BEGIN_SRC emacs-lisp :tangle no - '("conlang" - "\\documentclass{book}" - ("\\chapter{%s}" . "\\chapter*{%s}") - ("\\section{%s}" . "\\section*{%s}") - ("\\subsection{%s}" . "\\subsection*{%s}") - ("\\subsubsection{%s}" . "\\subsubsection*{%s}")) - #+END_SRC - - And here is the declaration of the ~beamer~ class: - #+NAME: org-latex-class-beamer - #+BEGIN_SRC emacs-lisp :tangle no - `("beamer" - ,(concat "\\documentclass[presentation]{beamer}\n" - "[DEFAULT-PACKAGES]" - "[PACKAGES]" - "[EXTRA]\n") - ("\\section{%s}" . "\\section*{%s}") - ("\\subsection{%s}" . "\\subsection*{%s}") - ("\\subsubsection{%s}" . "\\subsubsection*{%s}")) - #+END_SRC - - Both these classes have to be added to ~org-latex-classes~ like so: - #+BEGIN_SRC emacs-lisp :noweb yes - (eval-after-load "ox-latex" - '(progn - (add-to-list 'org-latex-classes - <> - ) - (add-to-list 'org-latex-classes - <> - ))) - #+END_SRC - -*** Org agenda - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_agenda-53f9d319 - :END: - One awesome feature of Org mode is the agenda. By default, my agendas are - stored in =~/org/agenda=. - #+BEGIN_SRC emacs-lisp - (setq org-agenda-files (list "~/org/agenda" "~/org/notes.org")) - #+END_SRC - - I also have a custom command in Org agenda to mark some tasks as daily - tasks with the =:DAILY:= tag,: - #+BEGIN_SRC emacs-lisp - (setq org-agenda-custom-commands - '(("h" "Daily habits" - ((agenda "")) - ((org-agenda-show-log t) - (org-agenda-ndays 7) - (org-agenda-log-mode-items '(state)) - (org-agenda-skip-function - '(org-agenda-skip-entry-if 'notregexp - ":DAILY:")))) - ("Y" "Yearly events" - ((agenda "")) - ((org-agenda-show-log t) - (org-agenda-ndays 365) - (org-agenda-log-mode-items '(state)) - (org-agenda-skip-entry-if 'notregexp - ":YEARLY:"))))) - #+END_SRC - -*** Org capture - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-f58979cf - :END: - Org-capture is an amazing feature of Org-mode which allows me to quickly - save links, resources, reminders, and notes in neatly organized org files. - Here they are described: - #+BEGIN_SRC emacs-lisp - (setq - org-conlanging-file "~/org/conlanging.org" - org-default-notes-file "~/org/notes.org" - org-journal-file "~/org/journal.org" - org-linguistics-notes-file "~/org/linguistics-notes.org" - org-novel-notes-file "~/org/novel-notes.org" - org-private-agenda-file "~/org/agenda/private.org" - org-school-agenda-file "~/org/agenda/school.org" - org-wordbuilding-file "~/org/worldbuilding.org") - #+END_SRC - - With Spacemacs, an Org capture can be invoked with the shortcut ~SPC a o c~. - It will then ask which template I wish to use. In the table below are - described the shortcuts that are available after ~SPC a o c~ is invoked. The - /name/ will be the one displayed in Org capture’s interface, the /title/ is - the headline where to save the capture (if it does not differ from the - capture’s name, the cell will be blank). The /insertion mode/ tells Emacs - how to add the capture to the /file/, using which /template/. A line with no - insertion mode, file, or template is just a category. All of the following - insert entries to their org files, that is a new org node with a headline - and some content. - #+NAME: org-capture-shortcuts-table - | Shortcut | Name | Title | Insertion mode | file | template | - |----------+---------------+----------+----------------+-------------------------+--------------------------| - | e | Email | | | | | - | ew | Write Email | Emails | file+headline | org-default-notes-file | emails.orgcaptmpl | - | j | Journal | | file+datetree | org-journal-file | journal.orgcaptmpl | - | l | Link | | | | | - | ll | General | | file+headline | org-default-notes-file | | - | ly | YouTube | | file+headline | org-default-notes-file | youtube.orgcaptmpl | - | L | Protocol Link | Link | file+headline | org-default-notes-file | protocol-link.orgcaptmpl | - | n | Notes | | | | | - | nc | Conlanging | Note | file+headline | org-conlanging-file | notes.orgcaptmpl | - | nn | General | | file+headline | org-default-notes-file | notes.orgcaptmpl | - | nN | Novel | Note | file+headline | org-novel-notes-file | notes.orgcaptmpl | - | nq | Quote | | file+headline | org-default-notes-file | notes-quote.orgcaptmpl | - | nw | Worldbuilding | Note | file+headline | org-wordbuilding-file | notes.orgcaptmpl | - | N | Novel | | | | | - | Ni | Ideas | | file+headline | org-novel-notes-file | notes.orgcaptmpl | - | p | Protocol | Link | file+headline | org-default-notes-file | protocol.orgcaptmpl | - | r | Resources | | | | | - | rc | Conlanging | Resource | file+headline | org-conlanging-file | resource.orgcaptmpl | - | re | Emacs | | file+headline | org-default-notes-file | resource.orgcaptmpl | - | ri | Informatique | | file+headline | org-default-notes-file | resource.orgcaptmpl | - | rl | Linguistics | | file+headline | org-default-notes-file | resource.orgcaptmpl | - | rw | Worldbuilding | Resource | file+headline | org-wordbuilding-file | resource.orgcaptmpl | - | t | Tasks | | | | | - | tb | Birthday | | file+headline | org-private-agenda-file | birthday.orgcaptmpl | - | te | Event | | file+headline | org-private-agenda-file | event.orgcaptmpl | - | th | Health | | file+headline | org-private-agenda-file | health.orgcaptmpl | - | ti | Informatique | | file+headline | org-private-agenda-file | informatique.orgcaptmpl | - - The following code snipped is not tangled into my configuration file, but - instead creates the equivalent to the table above into EmacsLisp code found - in the next code snippet. - #+NAME: org-capture-shortcut-gen - #+BEGIN_SRC emacs-lisp :tangle no :noweb yes :var table=org-capture-shortcuts-table :exports code :cache yes :results replace - (mapconcat (lambda (entry) - (let* ((shortcut (nth 0 entry)) - (name (nth 1 entry)) - (title (nth 2 entry)) - (insertmode (nth 3 entry)) - (fileinsert (nth 4 entry)) - (sourceorg (nth 5 entry))) - (if (string= "" insertmode) - (format "(\"%s\" \"%s\")" shortcut name) - (concat (format "(\"%s\" \"%s\" entry\n" shortcut name) - (format " (%s %s%s)\n" insertmode fileinsert - (if (string= "file+datetree" insertmode) "" - (format " \"%s\"" (if (string= "" title) name title)))) - (format " (file \"~/org/capture/%s\"))" sourceorg)))) ) - table "\n") - #+END_SRC - - #+RESULTS[5826faa0521c58664ddeedcf44b88910dbd344b6]: org-capture-shortcut-gen - #+begin_example - ("e" "Email") - ("ew" "Write Email" entry - (file+headline org-default-notes-file "Emails") - (file "~/org/capture/emails.orgcaptmpl")) - ("j" "Journal" entry - (file+datetree org-journal-file) - (file "~/org/capture/journal.orgcaptmpl")) - ("l" "Link") - ("ll" "General" entry - (file+headline org-default-notes-file "General") - (file "~/org/capture/")) - ("ly" "YouTube" entry - (file+headline org-default-notes-file "YouTube") - (file "~/org/capture/youtube.orgcaptmpl")) - ("L" "Protocol Link" entry - (file+headline org-default-notes-file "Link") - (file "~/org/capture/protocol-link.orgcaptmpl")) - ("n" "Notes") - ("nc" "Conlanging" entry - (file+headline org-conlanging-file "Note") - (file "~/org/capture/notes.orgcaptmpl")) - ("nn" "General" entry - (file+headline org-default-notes-file "General") - (file "~/org/capture/notes.orgcaptmpl")) - ("nN" "Novel" entry - (file+headline org-novel-notes-file "Note") - (file "~/org/capture/notes.orgcaptmpl")) - ("nq" "Quote" entry - (file+headline org-default-notes-file "Quote") - (file "~/org/capture/notes-quote.orgcaptmpl")) - ("nw" "Worldbuilding" entry - (file+headline org-wordbuilding-file "Note") - (file "~/org/capture/notes.orgcaptmpl")) - ("N" "Novel") - ("Ni" "Ideas" entry - (file+headline org-novel-notes-file "Ideas") - (file "~/org/capture/notes.orgcaptmpl")) - ("p" "Protocol" entry - (file+headline org-default-notes-file "Link") - (file "~/org/capture/protocol.orgcaptmpl")) - ("r" "Resources") - ("rc" "Conlanging" entry - (file+headline org-conlanging-file "Resource") - (file "~/org/capture/resource.orgcaptmpl")) - ("re" "Emacs" entry - (file+headline org-default-notes-file "Emacs") - (file "~/org/capture/resource.orgcaptmpl")) - ("ri" "Informatique" entry - (file+headline org-default-notes-file "Informatique") - (file "~/org/capture/resource.orgcaptmpl")) - ("rl" "Linguistics" entry - (file+headline org-default-notes-file "Linguistics") - (file "~/org/capture/resource.orgcaptmpl")) - ("rw" "Worldbuilding" entry - (file+headline org-wordbuilding-file "Resource") - (file "~/org/capture/resource.orgcaptmpl")) - ("t" "Tasks") - ("tb" "Birthday" entry - (file+headline org-private-agenda-file "Birthday") - (file "~/org/capture/birthday.orgcaptmpl")) - ("te" "Event" entry - (file+headline org-private-agenda-file "Event") - (file "~/org/capture/event.orgcaptmpl")) - ("th" "Health" entry - (file+headline org-private-agenda-file "Health") - (file "~/org/capture/health.orgcaptmpl")) - ("ti" "Informatique" entry - (file+headline org-private-agenda-file "Informatique") - (file "~/org/capture/informatique.orgcaptmpl")) - #+end_example - - Below you can find the equivalent code as described above. - #+BEGIN_SRC emacs-lisp :noweb yes - (setq - org-capture-templates - '( - <> - )) - #+END_SRC - - You may notice a capture entry for my journal, and this is due to the fact I - do not use ~org-journal~ anymore: it was too overpowered for me, and I - prefer to keep it simple with a single file. And as you can see, and unlike - a lot of other Emacs configurations, the content of the template is not set - in the variable, but in external files which can be modified freely as - actual Org buffers instead of trying to get a proper one with loads of ~\n~ - characters and such. All these templates are declared below. - - In the next sub-sections will be described my org capture templates. These - are not tangled into my Emacs configuration files, but into separate - ~.orgcaptmpl~ files stored into =~/org/capture/=. - -**** Emails - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Emails-d87336fe - :END: - This is my template for a new Email: - #+BEGIN_SRC org :tangle ~/org/capture/email.orgcaptmpl - ,** TODO [#A] Write Email - SCHEDULED: %^t - :PROPERTIES: - :CAPTURED: %U - :END: - From: Lucien Cartier-Tilet - To: %^{Recipient} - Subject: %^{Object} - --text follows this line-- - %? - -- - Lucien “Phundrak” Cartier-Tilet - https://phundrak.com (Français) - https://en.phundrak.com (English) - - Sent from a Free and Open-Source Linux operating system with GNU/Emacs - #+END_SRC - - I use it in case my computer is not yet connected to the internet and I - need to already write the email so I can send it later. All I will need to - to afterwards will be to copy and paste my capture in a new message buffer - and send it once I am back online. This is exported to - =~/org/capture/email.orgcaptmpl=. - -**** Journal - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Journal-9916f9bf - :END: - This template is quite simple: it creates a new entry with the current - timestamp as its title, a brief title of my choosing, and then I can write - whatever I wish to write. This is exported to - =~/org/capture/journal.orgcaptmpl=. - #+BEGIN_SRC org :tangle ~/org/capture/journal.orgcaptmpl - ,* %U %^{Title} - %? - #+END_SRC - -**** Notes - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Notes-4b4c10aa - :END: - This template is used for taking note about various subjects that can go - from conlanging to development. I wrote it so I can know from where this - capture was made and when, and it even supports text that was highlighted - in Emacs that will be inserted in a quote block. This is exported to - =~/org/capture/notes.orgcaptmpl=. - #+BEGIN_SRC org :tangle ~/org/capture/notes.orgcaptmpl - ,* %^{Title} - :PROPERTIES: - :CAPTURED: %U - :END: - %? - #+END_SRC - - - #+BEGIN_SRC org :tangle ~/org/capture/notes-quote.orgcaptmpl - ,* %^{Title} - :PROPERTIES: - :CAPTURED: %U - :END: - Possible inspiration: - ,#+begin_quote - %i - ,#+end_quote - - %? - #+END_SRC - -**** Protocol - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Protocol-ec45ec49 - :END: - This capture is used when received through org-protocol, with the - Org-protocol Extension for Firefox. It allows me to save in a quote block - what I’ve highlighted, as well as the link of the webpage on which my saved - content was highlighted. This file is exported to - =~/org/capture/protocol.orgcaptmpl=. - #+BEGIN_SRC org :tangle ~/org/capture/protocol.orgcaptmpl - ,* TODO [#C] %^{Title} - :PROPERTIES: - :CAPTURED: %U - :LINK: %:link - :TITLE: %:description - :END: - ,#+begin_quote - %i - ,#+end_quote - - %? - #+END_SRC - - This next capture template is used only when a link is sent to Emacs and no - content was highlighted. - #+BEGIN_SRC org :tangle ~/org/capture/protocol-link.orgcaptmpl - ,* TODO [#C] Link: %^{Title} - :PROPERTIES: - :CAPTURED: %U - :LINK: %:link - :TITLE: %:description - :END: - %? - #+END_SRC - -**** Resources - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Resources-b23bfbd0 - :END: - This is the default template for resources, which generally are located on - the Internet. By default, I give them the lowest priority, because although - this is something for me to remember later, it is not by default important. - You can see in the properties I record when the capture happened, and what - the link is. The title of the capture is a summary of what this is, while - the body of the capture is a more detailed explanation of what I capture, - why, and how it could be useful to me. - #+BEGIN_SRC org :tangle ~/org/capture/resource.orgcaptmpl - ,* TODO [#C] %^{Title} - :PROPERTIES: - :CAPTURED: %U - :LINK: %^{Link} - :END: - %? - #+END_SRC - -**** Tasks - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Tasks-3fcf382a - :END: - -***** Computers and stuff - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Tasks-Computers_and_stuff-a4eef8e3 - :END: - One type of task I often capture is related to my servers or thing about - computers in general. With this, I can capture a task for which I will - either set a schedule or a deadline. - #+BEGIN_SRC org :tangle ~/org/capture/informatique.orgcaptmpl - ,* TODO %^{Title} - %^{Scheduled or Deadline?||SCHEDULED||DEADLINE}: %^t - :PROPERTIES: - :CATEGORY: %^{Category} - :END: - %? - #+END_SRC - -***** Health - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Tasks-Health-74f8f338 - :END: - This capture is rarely used (I’m lucky to have a good health), but it can - be useful. - #+BEGIN_SRC org :tangle ~/org/capture/health.orgcaptmpl - ,* %^{Title} - SCHEDULED: %^t - - %? - #+END_SRC - -***** Birthdays - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Tasks-Birthdays-ec3b27be - :END: - This capture is used to store new birthdays I have to remember. They are - set to be repeated yearly. - #+BEGIN_SRC org :tangle ~/org/capture/birthday.orgcaptmpl - ,* %^{Name} - SCHEDULED: %^t - #+END_SRC - -***** Events - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Tasks-Events-7f0f8dee - :END: - #+BEGIN_SRC org :tangle ~/org/capture/event.orgcaptmpl - ,* %^{Title} - %^{Scheduled or deadline?||SCHEDULED||DEADLINE}: %^t - %? - #+END_SRC - -**** Links - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Links-586a6b2a - :END: -***** General - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Links-General-1f0732db - :END: - #+BEGIN_SRC org :tangle ~/org/capture/link.orgcaptmpl - ,* TODO [#C] %^{Title} - :PROPERTIES: - :CAPTURED: %U - :LINK: %^{Link} - :END: - %? - #+END_SRC - -***** YouTube - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_capture-Links-YouTube-b89fe20e - :END: - #+BEGIN_SRC org :tangle ~/org/capture/youtube.orgcaptmpl - ,* TODO [#C] %^{Title} - :PROPERTIES: - :CAPTURED: %U - :AUTHOR: %^{Author} - :LINK: %^{Link} - :END: - %? - #+END_SRC - -*** Org projects - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_projects-5be088cd - :END: - Another great features of Org-mode is the Org projects that allow the user - to easily publish a bunch of org files to a remote location. Here is the - current declaration of my projects, which will be detailed later: - #+BEGIN_SRC emacs-lisp :noweb yes - (setq org-publish-project-alist - '( - <> - <> - <> - <> - <> - <> - <>)) - #+END_SRC - -**** Configuration website - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_projects-Configuration_website-79bd0468 - :END: - #+NAME: org-proj-config-html - #+BEGIN_SRC emacs-lisp :tangle no - ("config-website-org" - :base-directory "~/org/config/" - :base-extension "org" - :exclude "\\./\\(CONTRIB\\|head\\|temp\\|svg-ink\\).*" - :publishing-directory "/ssh:Tilo:~/www/phundrak.com/config" - :recursive t - :language "en" - :publishing-function org-html-publish-to-html - :headline-levels 5 - :auto-sitemap t - :auto-preamble t) - #+END_SRC - - And lastly, we have the component for all the static files needed to run - the website: - #+NAME: org-proj-config-static - #+BEGIN_SRC emacs-lisp :tangle no - ("config-website-static" - :base-directory "~/org/config/" - :base-extension "png\\|jpg\\|gif\\|webp\\|svg\\|jpeg\\|ttf\\|woff\\|txt\\|epub\\|md" - :publishing-directory "/ssh:Tilo:~/www/phundrak.com/config" - :recursive t - :language "en" - :publishing-function org-publish-attachment) - #+END_SRC - - The project is then defined like so: - #+NAME: org-proj-config - #+BEGIN_SRC emacs-lisp :tangle no - ("config-website" - :components ("config-website-org" - "config-website-static")) - #+END_SRC - -**** Linguistics website - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Org-mode-Org_projects-Linguistics_website-34b8d4e7 - :END: - In my case, I only have my linguistics website, made out of three projects. - The first component is the one generating the HTML files from the org - files. - #+NAME: org-proj-lang-html - #+BEGIN_SRC emacs-lisp :tangle no - ("langue-phundrak-com-org" - :base-directory "~/Documents/conlanging/content/" - :base-extension "org" - :exclude "\\./\\(CONTRIB\\|README\\|head\\|temp\\|svg-ink\\).*" - :publishing-directory "/ssh:Tilo:~/www/phundrak.com/langue/" - :recursive t - :language "fr" - :publishing-function org-html-publish-to-html - :headline-levels 5 - :auto-sitemap t - :auto-preamble t) - #+END_SRC - - We also have the component for the LaTeX and PDF part of the website: - #+NAME: org-proj-lang-pdf - #+BEGIN_SRC emacs-lisp :tangle no - ("langue-phundrak-com-pdf" - :base-directory "~/Documents/conlanging/content/" - :base-extension "org" - :exclude "\\./\\(CONTRIB\\|README\\|index\\|head\\|temp\\|svg-ink\\).*" - :publishing-directory "/ssh:Tilo:~/www/phundrak.com/langue/" - :recursive t - :language "fr" - :publishing-function org-latex-publish-to-pdf - :headline-levels 5 - :auto-preamble t) - #+END_SRC - - And lastly, we have the component for all the static files needed to run - the website: - #+NAME: org-proj-lang-static - #+BEGIN_SRC emacs-lisp :tangle no - ("langue-phundrak-com-static" - :base-directory "~/Documents/conlanging/content/" - :base-extension "png\\|jpg\\|gif\\|webp\\|svg\\|jpeg\\|ttf\\|woff\\|txt\\|epub" - :publishing-directory "/ssh:Tilo:~/www/phundrak.com/langue/" - :recursive t - :language "fr" - :publishing-function org-publish-attachment) - #+END_SRC - - The project is then defined like so: - #+NAME: org-proj-lang - #+BEGIN_SRC emacs-lisp :tangle no - ("langue-phundrak-com" - :components ("langue-phundrak-com-org" - "langue-phundrak-com-static" - "langue-phundrak-com-pdf")) - #+END_SRC - - # Don’t delete this, this code block is here to wrap the org configuration - #+BEGIN_SRC emacs-lisp :exports none - ) - #+END_SRC - -** Rust - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Rust-ba633575 - :END: - I need to point to racer where the source code of Rust is located so I can - get some documentation. This is installed with the ~rust-src~ component you - can get through ~rustup~. To install it, simply run - #+BEGIN_SRC shell :tangle no :exports code - $ rustup component add rust-src - #+END_SRC - - Now, the source code for Rust should be included in your installation. I - personally prefer to develop with Rust stable, so let’s indicate to Emacs to - search for documentation in the stable sources: - #+BEGIN_SRC emacs-lisp - (setq racer-rust-src-path - "~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src") - #+END_SRC - - Rust’s default ~cargo check~ command is already very good, however I also - enjoy getting some more hints while developping, and ~clippy~ does a very - good job at it. To get clippy, I need to run the following to install it: - #+BEGIN_SRC shell - $ rustup compontent add clippy - #+END_SRC - - And this will get it installed with all of my Rust toolchain, and it will be - updated with it. Now, let’s indicate LSP that I want to use that instead of - ~check~: - #+BEGIN_SRC emacs-lisp - (setq lsp-rust-analyzer-cargo-watch-command "clippy") - #+END_SRC - - Finally, I wish to enable ~electric-pair-mode~ and ~indent-guide-mode~ for - Rust files, so let’s enable that through the use of a hook: - #+BEGIN_SRC emacs-lisp - (add-hook 'rust-mode-hook - '(lambda () - (local-set-key (kbd "TAB") #'company-indent-or-complete-common) - (electric-pair-mode 1) - (indent-guide-mode 1))) - #+END_SRC - -** Scheme - :PROPERTIES: - :CUSTOM_ID: User_Configuration-Scheme-e35aa50a - :END: - The Scheme configuration will be very short, I just need to tell Emacs the - name of the interpreter since it is not the default one: - #+BEGIN_SRC emacs-lisp - (setq geiser-chicken-binary "chicken-csi") - #+END_SRC - -** Shortcuts +** Keybindings :PROPERTIES: :CUSTOM_ID: User_Configuration-Shortcuts-aef3f7a7 :END: - As you will see, I defined a LOT of custom shortcuts. All of them are - Spacemacs shortcuts, defined in a way they can be used seamlessly with Evil. - They all begin with ~o~, which is a prefix reserved for user-defined - shortcuts so they won’t conflict with any package. Let’s declare it like so. + As you will see, I defined a LOT of custom keybindings. All of them are + Spacemacs keybindings, defined in a way they can be used seamlessly with + Evil. They all begin with ~o~, which is a prefix reserved for user-defined + keybindings so they won’t conflict with any package. Let’s declare it like + so. #+BEGIN_SRC emacs-lisp (spacemacs/declare-prefix "o" "custom") #+END_SRC - Now, all shortcuts that will be defined can be invoked in Normal-mode with + Now, all keybindings that will be defined can be invoked in Normal-mode with the src_emacs-lisp[:exports results]{(princ dotspacemacs-leader-key)} key - followed by the sequence assigned to each shortcut. + followed by the sequence assigned to each keybinding. Before some more specialized categories, I have two commands which don’t fit into any other category that I sometime use: @@ -3221,7 +2852,9 @@ (spacemacs/declare-prefix "oa" "applications") #+END_SRC - Now, let’s also declare the shortcuts in this category: + Now, let’s also declare the keybindings in this category. ~oac~ will invoke + Emacs’ calculator, while ~oac~ invokes the calendar, ~oae~ invokes the Eww + navigator and ~oaw~ invokes the weather forecast. #+BEGIN_SRC emacs-lisp (spacemacs/set-leader-keys "oac" 'calc @@ -3230,20 +2863,52 @@ "oaw" 'wttrin) #+END_SRC - ~oac~ will invoke Emacs’ calculator, while ~oac~ invokes the calendar, ~oae~ - invokes the Eww navigator and ~oaw~ invokes the weather forecast. +**** Org tree slide + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Keybindings-Applications-Org_tree_slide-29545c5e + :END: + Finally, here we have the keybindings for ~org-tree-slide~, a presentation + mode with orgmode. Since I want the keys to be directly accessible without + any prefix from Spacemacs, I’ll have to declare them the vanilla way. First + we have keybindings that will launch the presentation: + #+BEGIN_SRC emacs-lisp + (define-key org-mode-map (kbd "") 'org-tree-slide-mode) + (define-key org-mode-map (kbd "s-") 'org-tree-slide-skip-done-toggle) + #+END_SRC + + Next, we have some additional keybindings that will only be active when in + ~org-tree-slide-mode~. The first one will allow us to exit this mode, while + the second one will toggle the display of headers marked as ~DONE~. Next, + we have ~F9~ and ~F10~ which are bound to movement in the slide, while + ~F11~ changes the way the content is displayed. We also set + ~org-tree-slide-skip-outline-level~ to set the maximum depth we will + display as an individual heading during the presentation. + #+BEGIN_SRC emacs-lisp + (when (require 'org-tree-slide nil t) + (global-set-key (kbd "") 'org-tree-slide-mode) + (global-set-key (kbd "S-") 'org-tree-slide-skip-done-toggle) + (define-key org-tree-slide-mode-map (kbd "") + 'org-tree-slide-move-previous-tree) + (define-key org-tree-slide-mode-map (kbd "") + 'org-tree-slide-move-next-tree) + (define-key org-tree-slide-mode-map (kbd "") + 'org-tree-slide-content) + (setq org-tree-slide-skip-outline-level 4) + (org-tree-slide-narrowing-control-profile) + (setq org-tree-slide-skip-done nil)) + #+END_SRC *** Comments :PROPERTIES: :CUSTOM_ID: User_Configuration-Shortcuts-Comments-508db33d :END: - Some shortcuts are also related to comment editing, in particular using + Some keybindings are also related to comment editing, in particular using outorg. Let’s first declare the dedicated prefix: #+BEGIN_SRC emacs-lisp (spacemacs/declare-prefix "oc" "comments") #+END_SRC - Now, let’s declare the following shortcuts: + Now, let’s declare the following keybindings: #+BEGIN_SRC emacs-lisp (spacemacs/set-leader-keys "occ" 'outorg-copy-edits-and-exit @@ -3260,7 +2925,7 @@ :CUSTOM_ID: User_Configuration-Shortcuts-Files-206c2126 :END: This category is mainly used for opening configuration files, but it is also - more generally for files-related commands. Let’s declare shortcuts related + more generally for files-related commands. Let’s declare keybindings related to my configuration files. Here is the list of them: - [[file:bin.org][bin.org]] :: contains the source code of my custom scripts in my ~$PATH~ - [[file:spacemacs.org][spacemacs.org]] :: this file, configuration of Emacs @@ -3270,66 +2935,64 @@ - [[file:polybar.org][polybar.org]] :: configuration for polybar - [[file:picom.org][picom.org]] :: configuration for picom - [[https://labs.phundrak.com/phundrak/dotfiles][README.org]] :: README of the yadm repo - I also have a shortcut for the following files: + I also have a keybinding for the following files: - conlanging.org :: collection of ideas and references for conlanging - elfeed.org :: where I store all the RSS sources for Elfeed - journal.org :: my journal (which I don’t really use often tbh) - notes.org :: to, well, take notes - worldbuilding.org :: same as ~conlanging.org~ above. - Each of these files are accessible through a simple shortcut, and each one - of them has a description so the shortcut doesn’t show up as ~lambda~ with - ~which-keys~. So, a custom name for ~which-keys~ is specified in the Name + Each of these files are accessible through a simple keybinding, and each one + of them has a description so the keybinding doesn’t show up as ~lambda~ with + ~which-keys~. So, a custom name for ~which-keys~ is specified in the Name column. If a file is not specified, that means it is just a declaration for - a shortcut prefix. + a keybinding prefix. - First, here are my shortcuts for opening my private files described above: + First, here are my keybindings for opening my private files described above: #+NAME: private-files-open-shortcuts - | Shortcut | Name | File | - |----------+-------------------+---------------------------------| - | of | files | | - | ofb | blog.org | ~/org/blog/content-org/blog.org | - | ofC | conlanging.org | ~/org/conlanging.org | - | ofe | elfeed.org | ~/org/elfeed.org | - | ofj | journal.org | ~/org/journal.org | - | ofn | notes.org | ~/org/notes.org | - | ofw | worldbuilding.org | ~/org/worldbuilding.org | + | Keybinding | Name | File | + |------------+-------------------+---------------------------------| + | of | files | | + | ofb | blog.org | ~/org/blog/content-org/blog.org | + | ofC | conlanging.org | ~/org/conlanging.org | + | ofe | elfeed.org | ~/org/elfeed.org | + | ofj | journal.org | ~/org/journal.org | + | ofn | notes.org | ~/org/notes.org | + | ofw | worldbuilding.org | ~/org/worldbuilding.org | - And here are my shortcuts for opening config files: + And here are my keybindings for opening config files: #+NAME: config-files-open-shortcuts - | Shortcut | Name | File | - |----------+------------------+-------------------------------| - | ofc | config files | | - | ofca | awesome.org | ~/org/config/awesome.org | - | ofcb | bin.org | ~/org/config/bin.org | - | ofce | spacemacs.org | ~/org/config/spacemacs.org | - | ofcf | fish.org | ~/org/config/fish.org | - | ofci | index.org | ~/org/config/index.org | - | ofcI | installation.org | ~/org/config/installation.org | - | ofcp | polybar.org | ~/org/config/polybar.org | - | ofcP | picom.org | ~/org/config/picom.org | - | ofcr | yadm README | ~/README.org | + | Keybinding | Name | File | + |------------+------------------+-------------------------------| + | ofc | config files | | + | ofca | awesome.org | ~/org/config/awesome.org | + | ofcb | bin.org | ~/org/config/bin.org | + | ofce | spacemacs.org | ~/org/config/spacemacs.org | + | ofcf | fish.org | ~/org/config/fish.org | + | ofci | index.org | ~/org/config/index.org | + | ofcI | installation.org | ~/org/config/installation.org | + | ofcp | polybar.org | ~/org/config/polybar.org | + | ofcP | picom.org | ~/org/config/picom.org | + | ofcr | yadm README | ~/README.org | #+NAME: shortcuts-gen #+BEGIN_SRC emacs-lisp :tangle no :noweb yes :var table=[] :exports none :results replace (concat (mapconcat (lambda (x) - (let* ((shortcut (nth 0 x)) + (let* ((keybinding (nth 0 x)) (name (nth 1 x))) - (if (string= "" name) - "" + (if (string= "" name) "" (format "(spacemacs/declare-prefix \"%s\"\t\"%s\")" - shortcut name)))) - table - "\n") + keybinding name)))) + table "\n") "\n" (format "(spacemacs/set-leader-keys\n%s)" (mapconcat (lambda (x) - (let* ((shortcut (nth 0 x)) + (let* ((keybinding (nth 0 x)) (name (nth 1 x)) (file (nth 2 x))) (if (string= "" file) (format "\t\;\; %s" name) (format "\t\"%s\" (lambda () (interactive) (find-file \"%s\"))" - shortcut file)))) + keybinding file)))) table "\n"))) #+END_SRC @@ -3478,11 +3141,505 @@ The only command for now is a command that allows the use of ~C-u M-q~ with the simple shortcut ~oxf~: #+BEGIN_SRC emacs-lisp - (spacemacs/set-leader-keys - "oxf" 'phundrak/fill-paragraph) + (spacemacs/set-leader-keys "oxf" 'phundrak/fill-paragraph) #+END_SRC - #+RESULTS: +** Mu4e + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Mu4e-f3df8e9e + :END: + Mu4e is a frontend for mu, an email analyzer which sits on top of a Maildir + which gets updated with the ~mbsync~ command from ~isync~. It has a lot of + neat features, but I guess my favorite ones are: + 1. the search query feature + 2. being able to send an HTML email either to the browser + + Due to mu sitting on top of a Maildir, I need to tell mu4e where said maildir + is, and point it the trash, archive, and sent folders as well as the refresh + command and how frequently I want my emails to be refreshed. + #+BEGIN_SRC emacs-lisp + (setq mu4e-maildir "~/.mail" + mu4e-trash-folder "/Trash" + mu4e-refile-folder "/Archive" + mu4e-sent-folder "/Sent" + mu4e-drafts-folder "/Drafts" + mu4e-get-mail-command "mbsync -a" + mu4e-update-interval 60) + #+END_SRC + + The following also allows me to automatically include my signature in my + Emails, to view images in my Emacs buffers and to show me the address of my + contacts and not just their names. + #+BEGIN_SRC emacs-lisp + (setq mu4e-compose-signature-auto-include t + mu4e-view-show-images t + mu4e-view-prefer-html t + mu4e-view-show-addresses t) + #+END_SRC + + This source block is an example of the search queries in mu4e, and part of + the reason why I very much like mu4e: these bookmarks are actually defined by + search queries, but act as if they were just yet another type of custom inbox + you get with modern Email client (and often you don’t even get them). All + these bookmarks can be accessed through a shortcut on the main mu4e buffer, + prefixed by ~b~. So, for instance, my unread messages are accessed through + ~bu~. + #+BEGIN_SRC emacs-lisp + (setq mu4e-bookmarks + `(("maildir:/Inbox AND NOT flag:trashed" "Inbox" ?i) + ("maildir:/Sent" "Sent messages" ?s) + ("flag:unread AND NOT flag:trashed" "Unread messages" ?u) + ("date:today..now" "Today's messages" ?t) + ("date:7d..now" "Last 7 days" ?w) + ("date:1m..now" "Last month" ?m) + ("date:1y..now" "Last year" ?y) + ("flag:trashed" "Trash" ?T) + ("mime:image/*" "Messages with images" ?p))) + #+END_SRC + + On new email arrival, Emacs can send the system a notification which will be + handled as any other notification received by the system and will display the + number of unread emails to the user; in my case, notifications are handled by + [[https://dunst-project.org/][dunst]] under i3, or AwesomeWM itself. + #+BEGIN_SRC emacs-lisp + (setq mu4e-enable-notifications t + mu4e-alert-email-notification-types '(count)) + (with-eval-after-load 'mu4e-alert + (mu4e-alert-set-default-style 'notifications)) + (add-hook 'mu4e-view-mode-hook 'visual-line-mode) + #+END_SRC + + Now this hook is added so I can get a maximal width for the text of my + emails, I really don’t like it when lines are kilometers long. I would like + instead to hook ~visual-line-mode~ and ~auto-fill-mode~, but for some reasons + Emacs throws an error when I add them, So I go with ~visual-fill-column-mode~ + instead. + #+BEGIN_SRC emacs-lisp + (add-hook 'mu4e-view-mode-hook 'visual-fill-column-mode) + #+END_SRC + + On modern-day computers, with wide screens almost everywhere, there is no + reason for the email buffer to open below the email directory and not on its + right, which is why I set the split view to be vertical instead of + horizontal. I also set the width the email directory should keep to 80 + characters (and I could go to 120, but that’s only good for my + ultra-widescreen), because 30 characters is way too f-ing low. + #+BEGIN_SRC emacs-lisp + (setq mu4e-split-view 'vertical + mu4e-headers-visible-columns 140) + #+END_SRC + + This is the setup I have for my SMTP mail server: I point Emacs’ SMTP + services to my private mail server on its SMTP port, which should be used + with a STARTTLS stream. And I tell Emacs this is the default way to send an + email. + #+BEGIN_SRC emacs-lisp + (setq smtpmail-smtp-server "mail.phundrak.com" + smtpmail-smtp-service 587 + smtpmail-stream-type 'starttls + message-send-mail-function 'smtpmail-send-it) + #+END_SRC + + I am unsure yet if this has any effect on mu4e, but this variable should + discourage mu4e from reading rich text emails and instead open them as plain + text. However, I do not wish to discourage opening HTML emails since I can + compile them to PDF or open them in the browser. + #+BEGIN_SRC emacs-lisp + (setq mm-discouraged-alternatives '("text/richtext")) + #+END_SRC + + I am still unsure about this variable and if it has an effect on mu4e, but I + wish to set a default web viewer for my HTML emails: w3m. This is not as + effective as sending the email in the browser or rendering it as a PDF file, + but it can be effective enough for some emails. + #+BEGIN_SRC emacs-lisp + (setq mm-text-html-renderer 'w3m) + #+END_SRC + +** Miscellaneous + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Miscellaneous-d230bc2f + :END: + I have a lot of variables that need to be set but don’t fall in any other + category, so I’ll collect them here. + + I have this regexp for detecting paragraphs. + #+BEGIN_SRC emacs-lisp + (setq paragraph-start "\f\\|[ \t]*$\\|[ \t]*[-+*] ") + #+END_SRC + + There is currently [[https://github.com/syl20bnr/evil-iedit-state/issues/27][an open issue]] with ~evil-iedit-state~ where exiting the + iedit state calls ~iedit-cleanup~ despite this function being renamed + ~iedit-lib-cleanup~. So, waiting for the fix to be pushed upstream, let’s + declare an alias so Spacemacs understands what I want to do when I hit ~ESC~ + while in iedit state. + #+BEGIN_SRC emacs-lisp + (defalias 'iedit-cleanup 'iedit-lib-cleanup) + #+END_SRC + +*** Pinentry + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Miscellaneous-Pinentry-95004d5a + :END: + Pinentry should use the ~loopback~ mode when communicating with GnuPG. Let’s + set it so: + #+BEGIN_SRC emacs-lisp + (setq epa-pinentry-mode 'loopback) + #+END_SRC + +*** Wttr.in cities + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Miscellaneous-Wttr.in_cities-dd24f8c5 + :END: + Thanks to the wttrin package, I can get the weather forecast in Emacs for a + couple of cities. I just need to specify them to Emacs like so: + #+BEGIN_SRC emacs-lisp + (setq wttrin-default-cities '("Aubervilliers" "Paris" "Lyon" "Nonières" + "Saint Agrève")) + #+END_SRC + + :PROPERTIES: + :PROPERTIES: +** Visual configuration + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Visual_configuration-78e6cafc + :END: +*** Battery mode line + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Editing_and_modes-Battery_mode_line-895e5e52 + :END: + I want to see by default how much battery my computer has, so let’s enable + it: + #+BEGIN_SRC emacs-lisp + (spacemacs/toggle-mode-line-battery-on) + #+END_SRC + +*** Helm icons + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Visual_configuration-Helm_icons-6475fb5f + :END: + With the package ~helm-icons~, it is possible to bring ~all-the-icons~ to + helm when going through files and buffers. Let’s enable it. + #+BEGIN_SRC emacs-lisp + (helm-icons-enable) + #+END_SRC + +*** Prettified symbols + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Miscellaneous-Prettified_symbols-da50f4a6 + :END: + Just because it is pleasing to the eye, some symbols in source code get + prettified into simpler symbols. Here is the list of symbols that are to be + prettified. You can see in the corresponding comment what symbol will be + displayed. + #+BEGIN_SRC emacs-lisp + (setq prettify-symbols-alist '(("lambda" . 955) ; λ + ("->" . 8594) ; → + ("<->" . 8596) ; ↔ + ("<-" . 8592) ; ← + ("=>" . 8658) ; ⇒ + ("<=>" . 8860) ; ⇔ + ("<=" . 8656) ; ⇐ + ("mapc" . 8614) ; ↦ + ("map" . 8614) ; ↦ + (">>" . 187) ; » + ("<<" . 171) ; « + )) + #+END_SRC + + Let’s enable this mode globally. + #+BEGIN_SRC emacs-lisp + (global-prettify-symbols-mode 1) + #+END_SRC + +*** ~which-key~ replacements + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Visual_configuration-which-key_replacements-cccc5202 + :END: + It is possible to customize a bit what the ~which-key~ package shows us when + invoked. For the record, most of this either comes from [[http://www.howardism.org/][Howard Abram]]’s + [[https://github.com/howardabrams/dot-files][config]] on Github. First of all, I’d like to have some elements replaced + alltogether, such as ~left~ or ~right~ being replaced with a more visual + indicator, while some keys are replaced with a more understandable name. + #+BEGIN_SRC emacs-lisp + (setq which-key-key-replacement-alist + '(("<\\([[:alnum:]-]+\\)>" . "\\1") + ("left" . "◀") + ("right" . "▶") + ("up" . "▲") + ("down" . "▼") + ("delete" . "DEL") ; delete key + ("\\`DEL\\'" . "BS") ; backspace key + ("next" . "PgDn") + ("prior" . "PgUp"))) + #+END_SRC + + Let’s also write some replacements for the function names. + #+BEGIN_SRC emacs-lisp + (setq which-key-description-replacement-alist + '(("Prefix Command" . "prefix") + ("\\`calc-" . "") + ("\\`projectile-" . "𝓟/") + ("\\`org-babel-" . "ob/") + ("\\`phundrak/" . ""))) + #+END_SRC + +** Nov-mode + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Nov-mode-6f10765d + :END: + ~nov-mode~ is the mode used in the Epub reader. Here I will write a little + function that I will call through a hook each time I’m opening a new EPUB + file. + #+BEGIN_SRC emacs-lisp + (defun my-nov-font-setup () + (face-remap-add-relative 'variable-pitch :family "Charis SIL" + :size 16 + :height 1.0)) + #+END_SRC + + Let’s bind this function to the ~nov-mode~ hook. By the way, we’ll also + enable the ~visual-line-mode~ here, just in case. + #+BEGIN_SRC emacs-lisp + (mapc (lambda (mode) + (add-hook 'nov-mode-hook mode)) + '('my-nov-font-setup 'visual-line-mode)) + #+END_SRC + + Let’s also set the maximum length of the lines in ~nov-mode~: + #+BEGIN_SRC emacs-lisp + (setq nov-text-width 80) + #+END_SRC + +** Programming + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Programming-b4b565ae + :END: +*** LSP + :PROPERTIES: + :CUSTOM_ID: User_Configuration-LSP-4f8aa691 + :END: + When it comes to the LSP layer, there are some options which are not enabled + by default that I want to use, especially some modes I want to take advantage + of. This is why I enable first the ~lsp-treemacs-sync-mode~ so treemacs is + LSP aware: + #+BEGIN_SRC emacs-lisp + (lsp-treemacs-sync-mode 1) + #+END_SRC + + I also enable some layers related to ~dap~, the Debug Adapter Protocol, which + works really nicely with LSP. Let’s enable Dap’s modes: + #+BEGIN_SRC emacs-lisp + (dap-mode 1) + (dap-ui-mode 1) + (dap-tooltip-mode 1) + #+END_SRC + + Finally, I also want the documentation tooltip to show up when the cursor is + above a documented piece of code or symbol. Let’s enable that too: + #+BEGIN_SRC emacs-lisp + (tooltip-mode 1) + #+END_SRC + +*** ASM configuration + :PROPERTIES: + :CUSTOM_ID: User_Configuration-ASM_configuration-f6dc7674 + :END: + The first thing I will set with my ASM configuration is where the reference + PDF is located. + #+BEGIN_SRC emacs-lisp + (setq x86-lookup-pdf "~/Documents/code/asm/Intelx86/325383-sdm-vol-2abcd.pdf") + #+END_SRC + I will also modify what the comment character is, from a ~;~ to a ~#~: + #+BEGIN_SRC emacs-lisp + (setq asm-comment-char ?\#) + #+END_SRC + +*** C/C++ + :PROPERTIES: + :CUSTOM_ID: User_Configuration-C-C++-76c3f997 + :END: + As the C/C++ syntax is checked by flycheck, let’s make sure we are using the + latest standard available, that is C++17 and C17, from Clang. + #+BEGIN_SRC emacs-lisp + (add-hook 'c-mode-hook + (lambda () + (setq flycheck-clang-language-standard "c17"))) + (add-hook 'c++-mode-hook + (lambda () + (setq flycheck-clang-language-standard "c++17"))) + #+END_SRC + +*** Dart configuration + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Dart_configuration-ecf24ebf + :END: + For Dart, I mainly declared some custom shortcuts bound to ~dart-mode~ + related to flutter, so nothing too exciting here. Some prefix are declared in + order to avoid the shortcuts in helm to show up as just ~custom~. + #+begin_src emacs-lisp + (spacemacs/declare-prefix-for-mode 'dart-mode "mo" "user-defined") + (spacemacs/declare-prefix-for-mode 'dart-mode "mof" "flutter") + (spacemacs/declare-prefix-for-mode 'dart-mode "mofr" "flutter-run") + #+end_src + + Now, for the shortcuts themselves: + #+BEGIN_SRC emacs-lisp + (spacemacs/set-leader-keys-for-major-mode 'dart-mode + "ofH" 'flutter-hot-restart + "ofh" 'flutter-hot-reload + "ofq" 'flutter-quit + "ofr" (lambda () (interactive) (flutter-run "-v")) + "ofs" 'flutter-screenshot) + #+END_SRC + +*** Emacs Lisp + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Emacs_Lisp-59230f3c + :END: + Here will be stored my configuration directly related to Emacs Lisp, + including some functions or default modes. + +**** Enable ~eldoc-mode~ by default + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Emacs_Lisp-Enable_~eldoc-mode~_by_default-f131abde + :END: + By default, if some Elisp code is opened, I want to enable ~eldoc-mode~ so I + can easily get some documentation on the symbols in the source code. This is + done via the use of hooks. + #+BEGIN_SRC emacs-lisp + (add-hook 'prog-mode-hook 'eldoc-mode) + #+END_SRC + +**** ~phundrak/write-to-buffer~ + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Emacs_Lisp-~phundrak-write-to-buffer~-2f192dd3 + :END: + I was very surprised when I discovered no such function exists in Elisp. + This function basically writes a string into a buffer, and optionally + switches the user to the buffer. Here is the code for that function: + #+BEGIN_SRC elisp :results silent + (defun write-to-buffer ($input-string $outputbuf &optional $switchbuf) + "Writes `$input-string' to the specified `output-buffer'. If + `switch-buffer' is non-nil, the active buffer will switch to the + output buffer; otherwise, it will take the user back to their + initial buffer. Works with `$input-string' as a string or a list + of strings." + (let ((oldbuf (current-buffer))) + (switch-to-buffer $outputbuf) + (cond ((char-or-string-p $input-string) (insert $input-string)) + ((listp $input-string) (dolist (elem $input-string) + (insert (format "%s\n" elem))))) + (if (not $switchbuf) + (switch-to-buffer oldbuf)))) + #+END_SRC + +*** Python + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Python-9cdd1b06 + :END: + Emacs throws me an error about the python interpreter, let’s silence it: + #+BEGIN_SRC emacs-lisp + (setq python-shell-completion-native-disabled-interpreters '("python")) + #+END_SRC + +*** Rust + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Rust-ba633575 + :END: + I need to point to racer where the source code of Rust is located so I can + get some documentation. This is installed with the ~rust-src~ component you + can get through ~rustup~. To install it, simply run + #+BEGIN_SRC shell :tangle no :exports code + $ rustup component add rust-src + #+END_SRC + + Now, the source code for Rust should be included in your installation. I + personally prefer to develop with Rust stable, so let’s indicate to Emacs to + search for documentation in the stable sources: + #+BEGIN_SRC emacs-lisp + (setq racer-rust-src-path + "~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src") + #+END_SRC + + Rust’s default ~cargo check~ command is already very good, however I also + enjoy getting some more hints while developping, and ~clippy~ does a very + good job at it. To get clippy, I need to run the following to install it: + #+BEGIN_SRC shell + $ rustup compontent add clippy + #+END_SRC + + And this will get it installed with all of my Rust toolchain, and it will be + updated with it. Now, let’s indicate LSP that I want to use that instead of + ~check~: + #+BEGIN_SRC emacs-lisp + (setq lsp-rust-analyzer-cargo-watch-command "clippy") + #+END_SRC + + Finally, I wish to enable ~electric-pair-mode~ and ~indent-guide-mode~ for + Rust files, so let’s enable that through the use of a hook: + #+BEGIN_SRC emacs-lisp + (add-hook 'rust-mode-hook + '(lambda () + (local-set-key (kbd "TAB") #'company-indent-or-complete-common) + (electric-pair-mode 1) + (indent-guide-mode 1))) + #+END_SRC + +*** Scheme + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Scheme-e35aa50a + :END: + The Scheme configuration will be very short, I just need to tell Emacs the + name of the interpreter since it is not the default one: + #+BEGIN_SRC emacs-lisp + (setq geiser-chicken-binary "chicken-csi") + #+END_SRC + +** Projectile + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Projectile-06e580f0 + :END: + Projectile is an awesome utility which helps managing projects within Emacs. + It will automatically detect version controlled directories, and will by + default assume this is a project I can be working on. However, there are some + directories that are version controlled that I do not want to see in my list + of projects, namely all the cached AUR packages from my AUR helper, ~yay~. + They are all stored in the same parent directory, so let’s ignore that. I + will also make Emacs ignore all ~node_modules~ directories it could + encounter. And for some reason, =~/.config/emacs= is always in my projects + list (I now use XDG-compliant directories), so let’s also ignore that. + #+BEGIN_SRC emacs-lisp + (phundrak/add-all-to-list projectile-globally-ignored-directories + "~/.cache/yay/*" "node_modules" "~/.config/emacs") + #+END_SRC + +** Snippets + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Snippets-67a32065 + :HEADER-ARGS:snippet: :padline no + :END: + Yasnippet’s snippets tool is extremely powerful and allows me to write very + quickly code. For now, we have snippets for two modes. The files you’ll see + below are exported to ~$HOME/.config/emacs/private/snippets/~ and to their + respective mode directory. For instance, my ~caption~ snippet for org-mode + will be exported to ~$HOME/.config/emacs/private/snippets/org-mode/caption~ + +*** org-mode snippets + :PROPERTIES: + :CUSTOM_ID: User_Configuration-Snippets-org-mode_snippets-f213e34d + :END: + The first two snippets are used to add HTML or LaTeX attributes to elements + in org-mode. + #+BEGIN_SRC snippet :mkdir yes :tangle ~/.config/emacs/private/snippets/org-mode/attr_html + # -*- mode: snippet -*- + # name: ATTR HTML + # key: