Configurare Emacs in Org-mode
Welcome to my Emacs configuration, written in Org-mode. Being this a literate configuration, most of the choices I made are extensively documented here.
Keep in mind that not evey part is translated in English. It happens to me writing stuff down in Italian, my mother language, so some sections are published as they are. It can take some time before I translate everyhting in English.
Emacs it§
Innanzitutto, cos'è Emacs?
Emacs is not a text editor, this is a common misnomer. It is far more apt to describe Emacs as a Lisp machine providing a generic user-centric text manipulation environment. That’s quite a mouthful. In simpler terms one can think of Emacs as a platform for text-related applications. It’s a vague and generic definition because Emacs itself is generic. (@tecosaur)
Se solitamente Emacs è conosciuto come editor di testo, in verità sotto la scocca si tratta di qualcosa di molto più complesso: Emacs è una lisp machine, ovvero un sistema integrato capace di interpretare ed eseguire codice lisp e, con esso, una miriade di programmi pure molto articolati, tipicamente legati alla manipolazione del testo. Considerata la versatilità della piattaforma, mi sarebbe impossibile descriverla senza disseminare avverbi come "solitamente" o "tipicamente".
Io, ad esempio, uso quotidianamente Emacs per:
- Scrivere codice
- Scrivere prosa (via Org-mode)
- Gestire i file (via Dired)
- Git (grazie a Magit, Emacs è probabilmente il miglior git client in circolazione)
- RSS (via Elfeed)
Per qualche tempo l'ho usato anche come emulatore di terminale, ora capita solo in circostanze particolari, ad esempio per compilare del codice che sto scrivendo nel buffer a fianco.
Distribuzioni Emacs it§
La barriera di ingresso, in verità, può essere parzialmente abbattuta per mezzo di distribuzioni Emacs pre-configurate, tra cui ne cito qualcuna, pescando tra le più famose:
- Spacemacs è stata la mia prima distribuzione: è particolarmente indicata per i neofiti in arrivo da vim, come ero io. Non solo è efficace nell'emulare vim (grazie ad Evil), ma dispone anche di miriadi di funzioni ausiliarie richiamabili con un semplice tocco sulla barra spaziatrice (space-emacs, non a caso).
- NANO Emacs: dipendenze minime, eccezionalmente elegante, funzionalmente molto vicina a Vanilla Emacs;
- Doom Emacs è la mia distribuzione attuale, e quindi quella con cui sto scrivendo questo documento; anche questa (come Spacemacs) è molto bene integrata con Evil e si presta bene alle esigenze di ogni ex-vimmer. Inoltre, l'impiego di svariate strategie di lazy-loading e, in generale, una meditata selezione dei pacchetti rendono questa distribuzione estremamente scattante.
La configurazione riportata in questo file può, potenzialmente, essere adattata anche ad altre distribuzioni Emacs, ma presa com'è funziona solo su Doom Emacs.
Emacs Lisp it§
Come dicevo, Emacs è un interpreter di lisp, ma per essere più corretti dovremmo fare riferimento ad Emacs Lisp, un dialetto della famiglia di linguaggi di programmazione che rientra sotto la denominazione "Lisp" (LISt Processor).
Come già detto altrove 1, "visto un dialetto di lisp, visti tutti":
if you've seen one lisp, you've seen them all
Non voglio dilungarmi in questa sede nella descrizione del linguaggio. Per un assaggio della sintassi e di qualche funzione base, piuttosto, rimando a questo post che ho scritto sul blog come breve introduzione.
In caso voleste spingervi lievemente oltre, rimando a questi altri post (in ordine di difficoltà):
- Come riproduco la mia musica Lo-fi;
- Come citare un tweet in emacs lisp;
- Come usare le API di twitter in Emacs Lisp.
Avendo iniziato solo da poco tempo a navigare nell'oceano di meraviglie e parentesi lispiane, non sono certo la fonte più autorevole per scendere più nel dettaglio. Per una guida rapida ad Emacs Lisp, consiglio di dare un'occhiata a questa repo. Per una guida meno rapida, ma più approfondita, fate riferimento a Learn elisp the hard way.
Literate configuration it§
Tradizionalmente, la configurazione di Doom Emacs è raccolta in 3 file fondamentali, a loro volta contenuti in una apposita directory nella home, .doom.d
.
Questi file sono:
config.el
;init.el
;packages.el
.
Altre distribuzioni hanno gerarchie più semplici (Vanilla Emacs prevede sia tutto in .emacs
) o più caotiche o più stratificate (es. layer in Spacemacs).
Doom, di suo, mantiene secondo me una piacevole via di mezzo.
Anziché intervenire su questi file direttamente, possiamo scrivere la nostra configurazione su un file .org
, da cui generare in seconda battuta i 3 file di configurazione principali.
Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.
The practitioner of literate programming can be regarded as an essayist, whose main concern is with exposition and excellence of style. Such an author, with thesaurus in hand, chooses the names of variables carefully and explains what each variable means. He or she strives for a program that is comprehensible because its concepts have been introduced in an order that is best for human understanding, using a mixture of formal and informal methods that reinforce each other. — Donald Knuth
Come accennavo in una parentesi sopra, questa prassi si rifa' ai principi della programmazione letteraria (literate programming), un paradigma proposto per la prima volta da Donald Knuth, che ne dimostrò le potenzialità scrivendo così il compilatore di TeX.
Per maggiori dettagli sul literate programming in org-mode vedi la documentazione ufficiale.
Diego Zamboni, nella propria configurazione scrive:
Emacs config is an art, and I have learned a lot by reading through other people’s config files, and from many other resources.
Insomma, l'arte di configurare Emacs (come tante altre) si affina studiando i trucchetti altrui. Tra le configurazioni org più illuminanti, segnalo anche la configurazione di tecosaur. Per entrambe trovate anche i mirrors su Github (che renderizza piacevolmente anche i file org).
Ci sono vari modi per consentire ad Emacs di leggere la configurazione attraverso un org file; come tanti altri, io qui mi limito a generare i file di configurazione a partire dal file org, per mezzo di una pratica che Donald Knuth ha chiamato "tangling" (aggrovigliare).
Frontmatters it§
Cominciamo dalla testa dei nostri file di configurazione, cioè da tutti i commenti che troviamo di norma nelle prime 10-20 righe. C'è solo una modifica che è il caso di fare in questo punto: aggiungere un piccolo commento che ricordi all'eventuale lettore che il file in uscita è un file generato e che non va modificato direttamente.
;; DO NOT EDIT THIS FILE DIRECTLY
;; This is a file generated from a literate programing source file located at
;; https://github.com/gicrisf/emacs-config
;; You should make any changes there and regenerate it from Emacs org-mode
;; using org-babel-tangle (C-c C-v t)
Frontespizio di init.el
.
;;; init.el -*- lexical-binding: t; -*-
<<do-not-edit>>
;; This file controls what Doom modules are enabled and what order they load
;; in. Remember to run 'doom sync' after modifying it!
;; NOTE Press 'SPC h d h' (or 'C-h d h' for non-vim users) to access Doom's
;; documentation. There you'll find a "Module Index" link where you'll find
;; a comprehensive list of Doom's modules and what flags they support.
;; NOTE Move your cursor over a module's name (or its flags) and press 'K' (or
;; 'C-c c k' for non-vim users) to view its documentation. This works on
;; flags as well (those symbols that start with a plus).
;;
;; Alternatively, press 'gd' (or 'C-c c d') on a module to browse its
;; directory (for easy access to its source code).
Frontespizio di packages.el
.
;; -*- no-byte-compile: t; -*-
;;; $DOOMDIR/packages.el
<<do-not-edit>>
;; To install a package with Doom you must declare them here and run 'doom sync'
;; on the command line, then restart Emacs for the changes to take effect -- or
;; use 'M-x doom/reload'.
;; To install SOME-PACKAGE from MELPA, ELPA or emacsmirror:
;(package! some-package)
Frontespizio di config.el
.
;;; $DOOMDIR/config.el -*- lexical-binding: t; -*-
<<do-not-edit>>
;; Place your private configuration here! Remember, you do not need to run 'doom
;; sync' after modifying this file!
;; Some functionality uses this to identify you, e.g. GPG configuration, email
;; clients, file templates and snippets.
Doom modules§
Every time Doom Emacs is started, the following code is evaluated for adding or deleting eventually edited packages.
;;; init.el -*- lexical-binding: t; -*-
;; This file controls what Doom modules are enabled and what order they load in.
;; Press 'K' on a module to view its documentation, and 'gd' to browse its directory.
(doom! :input
<<doom-input>>
:completion
<<doom-completion>>
:ui
<<doom-ui>>
:editor
<<doom-editor>>
:emacs
<<doom-emacs>>
:term
<<doom-term>>
:checkers
<<doom-checkers>>
:tools
<<doom-tools>>
:os
<<doom-os>>
:lang
<<doom-lang>>
:email
<<doom-email>>
:app
<<doom-app>>
:config
<<doom-config>>
)
As you can see, this part basically consists of a simple list of modules.
Input§
;;chinese
;;japanese
;;layout ; auie,ctsrnm is the superior home row
Completion§
company ; the ultimate code completion backend
;;helm ; the *other* search engine for love and life
;;ido ; the other *other* search engine...
ivy ; a search engine for love and life
UI§
;;deft ; notational velocity for Emacs
doom ; what makes DOOM look the way it does
doom-dashboard ; a nifty splash screen for Emacs
doom-quit ; DOOM quit-message prompts when you quit Emacs
(emoji +unicode) ; 🙂
hl-todo ; highlight TODO/FIXME/NOTE/DEPRECATED/HACK/REVIEW
;;hydra
;;indent-guides ; highlighted indent columns
;;ligatures ; ligatures and symbols to make your code pretty again
;;minimap ; show a map of the code on the side
modeline ; snazzy, Atom-inspired modeline, plus API
;;nav-flash ; blink cursor line after big motions
neotree ; a project drawer, like NERDTree for vim
ophints ; highlight the region an operation acts on
(popup +defaults) ; tame sudden yet inevitable temporary windows
;;tabs ; a tab bar for Emacs
;;treemacs ; a project drawer, like neotree but cooler
;;unicode ; extended unicode support for various languages
vc-gutter ; vcs diff in the fringe
vi-tilde-fringe ; fringe tildes to mark beyond EOB
;;window-select ; visually switch windows
workspaces ; tab emulation, persistence & separate workspaces
zen ; distraction-free coding or writing
Editor§
(evil +everywhere); come to the dark side, we have cookies
file-templates ; auto-snippets for empty files
fold ; (nigh) universal code folding
;;(format +onsave) ; automated prettiness
;;god ; run Emacs commands without modifier keys
;;lispy ; vim for lisp, for people who don't like vim
multiple-cursors ; editing in many places at once
;;objed ; text object editing for the innocent
;;parinfer ; turn lisp into python, sort of
;;rotate-text ; cycle region at point between text candidates
snippets ; my elves. They type so I don't have to
;;word-wrap ; soft wrapping with language-aware indent
About multiple cursors: just run the g z z
sequence to spawn a new cursor on place.
Emacs§
dired ; making dired pretty [functional]
electric ; smarter, keyword-based electric-indent
;;ibuffer ; interactive buffer management
undo ; persistent, smarter undo for your inevitable mistakes
vc ; version-control and Emacs, sitting in a tree
Term§
;;eshell ; the elisp shell that works everywhere
;;shell ; simple shell REPL for Emacs
;;term ; basic terminal emulator for Emacs
vterm ; the best terminal emulation in Emacs
Checkers§
syntax ; tasing you for every semicolon you forget
;;(spell +flyspell) ; tasing you for misspelling mispelling
;;grammar ; tasing grammar mistake every you make
Tools§
;;ansible
;;debugger ; FIXME stepping through code, to help you add bugs
;;direnv
;;docker
;;editorconfig ; let someone else argue about tabs vs spaces
;;ein ; tame Jupyter notebooks with emacs
(eval +overlay) ; run code, run (also, repls)
;;gist ; interacting with github gists
lookup ; navigate your code and its documentation
lsp ; M-x vscode
magit ; a git porcelain for Emacs
;;make ; run make tasks from Emacs
;;pass ; password manager for nerds
;;pdf ; pdf enhancements
;;prodigy ; FIXME managing external services & code builders
;;rgb ; creating color strings
;;taskrunner ; taskrunner for all your projects
;;terraform ; infrastructure as code
;;tmux ; an API for interacting with tmux
;;upload ; map local to remote projects via ssh/ftp
OS§
(:if IS-MAC macos) ; improve compatibility with macOS
;;tty ; improve the terminal Emacs experience
Lang§
;;agda ; types of types of types of types...
;;beancount ; mind the GAAP
;;cc ; C > C++ == 1
;;clojure ; java with a lisp
;;common-lisp ; if you've seen one lisp, you've seen them all
;;coq ; proofs-as-programs
;;crystal ; ruby at the speed of c
;;csharp ; unity, .NET, and mono shenanigans
;;data ; config/data formats
;;(dart +flutter) ; paint ui and not much else
;;elixir ; erlang done right
elm ; care for a cup of TEA?
emacs-lisp ; drown in parentheses
;;erlang ; an elegant language for a more civilized age
;;ess ; emacs speaks statistics
;;factor
;;faust ; dsp, but you get to keep your soul
;;fsharp ; ML stands for Microsoft's Language
;;fstar ; (dependent) types and (monadic) effects and Z3
;;gdscript ; the language you waited for
;;(go +lsp) ; the hipster dialect
;;(haskell +dante) ; a language that's lazier than I am
;;hy ; readability of scheme w/ speed of python
;;idris ; a language you can depend on
;;json ; At least it ain't XML
;;(java +meghanada) ; the poster child for carpal tunnel syndrome
javascript ; all(hope(abandon(ye(who(enter(here))))))
;;julia ; a better, faster MATLAB
;;kotlin ; a better, slicker Java(Script)
latex ; writing papers in Emacs has never been so fun
;;lean ; for folks with too much to prove
;;ledger ; be audit you can be
;;lua ; one-based indices? one-based indices
markdown ; writing docs for people to ignore
;;nim ; python + lisp at the speed of c
;;nix ; I hereby declare "nix geht mehr!"
;;ocaml ; an objective camel
org ; organize your plain life in plain text
;;php ; perl's insecure younger brother
;;plantuml ; diagrams for confusing people more
;;purescript ; javascript, but functional
python ; beautiful is better than ugly
;;qt ; the 'cutest' gui framework ever
;;racket ; a DSL for DSLs
;;raku ; the artist formerly known as perl6
;;rest ; Emacs as a REST client
;;rst ; ReST in peace
;;(ruby +rails) ; 1.step {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"}
(rust + lsp) ; Fe2O3.unwrap().unwrap().unwrap().unwrap()
;;scala ; java, but good
;;(scheme +guile) ; a fully conniving family of lisps
sh ; she sells {ba,z,fi}sh shells on the C xor
;;sml
;;solidity ; do you need a blockchain? No.
;;swift ; who asked for emoji variables?
;;terra ; Earth and Moon in alignment for performance.
web ; the tubes
yaml ; JSON, but readable
;;zig ; C, but simpler
Mail§
Per il momento, non uso Emacs per le mie email. Una volta ho provato a gestire tutto da CLI, anche con buoni risultati, ma a causa di problemi di vario genere alla fine ho deciso che era meglio tornare alla web-app. Non tanto perché sia una cattiva idea, quanto piuttosto perché è un inferno con tutto l'HTML pazzo che mettono in mezzo al testo, cosa che si può risolvere leggendo le mail con lynx o altri browser testuali, ma in fin dei conti dà l'impressione di stare sistematicamente forzando il mezzo. Usare il solito browser (coi dovuti accorgimenti) mi sembra la scelta più efficace. Ecco perché non uso mu4e, sebbene l'idea mi tenti di tanto in tanto.
;;(mu4e +gmail)
;;notmuch
;;(wanderlust +gmail)
Ed ecco che la tentazione ritorna: TODO, sincronizzare con protonmail.
App§
Uso Emacs come RSS reader.
;;calendar
;;emms
;;everywhere ; *leave* Emacs!? You must be joking
;;irc ; how neckbeards socialize
(rss +org) ; emacs as an RSS reader
;;twitter ; twitter client https://twitter.com/vnought
Config§
This is a literate configuration, so it looks reasonable to enable the relative module.
literate
(default +bindings +smartparens)
Package!§
Clearly, not every package in Emacs are molded as Doom Emacs modules: it would be crazy. Many of them are to be installed via MELPA or git repositories.
Like before, I keep original comments of packages.el
here, but the file will be populated in the next part, side by side with the relative package configuration.
Recipe§
;; To install a package directly from a remote git repo, you must specify a
;; `:recipe'. You'll find documentation on what `:recipe' accepts here:
;; https://github.com/raxod502/straight.el#the-recipe-format
;(package! another-package
; :recipe (:host github :repo "username/repo"))
Files§
;; If the package you are trying to install does not contain a PACKAGENAME.el
;; file, or is located in a subdirectory of the repo, you'll need to specify
;; `:files' in the `:recipe':
;(package! this-package
; :recipe (:host github :repo "username/repo"
; :files ("some-file.el" "src/lisp/*.el")))
Disable§
;; If you'd like to disable a package included with Doom, you can do so here
;; with the `:disable' property:
;(package! builtin-package :disable t)
Override§
;; You can override the recipe of a built in package without having to specify
;; all the properties for `:recipe'. These will inherit the rest of its recipe
;; from Doom or MELPA/ELPA/Emacsmirror:
;(package! builtin-package :recipe (:nonrecursive t))
;(package! builtin-package-2 :recipe (:repo "myfork/package"))
Branch§
;; Specify a `:branch' to install a package from a particular branch or tag.
;; This is required for some packages whose default branch isn't 'master' (which
;; our package manager can't deal with; see raxod502/straight.el#279)
;(package! builtin-package :recipe (:branch "develop"))
Pin§
;; Use `:pin' to specify a particular commit to install.
;(package! builtin-package :pin "1a2b3c4d5e")
Unpin§
;; Doom's packages are pinned to a specific commit and updated from release to
;; release. The `unpin!' macro allows you to unpin single packages...
;(unpin! pinned-package)
;; ...or multiple packages
;(unpin! pinned-package another-pinned-package)
;; ...Or *all* packages (NOT RECOMMENDED; will likely break things)
;(unpin! t)
Configuration§
In the end, we get to the actual configuration.
Who am I?§
;; Some functionality uses this to identify you, e.g. GPG configuration, email
;; clients, file templates and snippets.
(setq user-full-name "gicrisf"
user-mail-address "giovanni.crisalfi@protonmail.com")
Font§
;; Doom exposes five (optional) variables for controlling fonts in Doom. Here
;; are the three important ones:
;;
;; + `doom-font'
;; + `doom-variable-pitch-font'
;; + `doom-big-font' -- used for `doom-big-font-mode'; use this for
;; presentations or streaming.
;;
;; They all accept either a font-spec, font string ("Input Mono-12"), or xlfd
;; font string. You generally only need these two:
(setq doom-font (font-spec :family "Noto Sans Mono" :size 16 :weight 'semi-light)
doom-variable-pitch-font (font-spec :family "sans" :size 16))
Since I use Emacs both on a laptop and a desktop computer, I wish I could export the same configuration with simple variations to adjust it to the different hardware. In this case, just changing the font would be nice. I still hadn't work on this, but I have to.
Temi§
Default§
First of all, let's select a default theme.
;; There are two ways to load a theme. Both assume the theme is installed and
;; available. You can either set `doom-theme' or manually load a theme with the
;; `load-theme' function. This is the default:
(setq doom-theme 'doom-city-lights)
I'm loving City Lights right now and I realized a City Lights theme for qutebrowser too because I wanted to keep everything so uniform and polished. There's just one single thing that makes me annoyed: when I declare a task as DONE in org-mode, not only the "DONE" keyword gets grayed out, but the title too. I should work on this detail.
I leave those default comments here; they're pretty helpful and concise.
;; Here are some additional functions/macros that could help you configure Doom:
;;
;; - `load!' for loading external *.el files relative to this one
;; - `use-package!' for configuring packages
;; - `after!' for running code after a package has loaded
;; - `add-load-path!' for adding directories to the `load-path', relative to
;; this file. Emacs searches the `load-path' when you load packages with
;; `require' or `use-package'.
;; - `map!' for binding new keys
;;
;; To get information about any of these functions/macros, move the cursor over
;; the highlighted symbol at press 'K' (non-evil users must press 'C-c c k').
;; This will open documentation for it, including demos of how they are used.
;;
;; You can also try 'gd' (or 'C-c c d') to jump to their definition and see how
;; they are implemented.
Spacemacs§
I'm emotionally attached to the Spacemacs' themes. Sometimes I make use of spacemacs-light
, usually when the environment is brighter than usual (e.g. I'm trying to read outside on a sunny day).
(package! spacemacs-theme)
I would like to make use of Nano-Emacs' colors, but by the moment it does look harder then it seems. Henrik Lissner, Doom Emacs' creator, said he would have made a specific module for this integration, but of course it's not an immediate priority, so I think I'll wait with hope.
Catppuccin§
(package! catppuccin :recipe (:host github :repo "catppuccin/emacs"))
Theme ciclator§
Some day I will write what this is about, but I hope the point is pretty easy to grasp for any lisp enthysiast like you probably are.
;; Theme switcher functions
(defvar quick-switch-themes
(let ((themes-list (list 'doom-city-lights
'doom-one
'spacemacs-light
'doom-one-light)))
(nconc themes-list themes-list))
"A circular list of themes to keep switching between.
Make sure that the currently enabled theme is at the head of this
list always.
A nil value implies no custom theme should be enabled.")
;; Thanks to narendraj9, user of emacs.stackexchange.com
;; https://emacs.stackexchange.com/questions/24088/make-a-function-to-toggle-themes
;; I just tweaked his code.
(defun toggle-theme ()
(interactive)
(if-let* ((next-theme (cadr quick-switch-themes)))
(progn (when-let* ((current-theme (car quick-switch-themes)))
(disable-theme (car quick-switch-themes)))
(load-theme next-theme t)
(message "Loaded theme: %s" next-theme))
;; Always have the dark mode-line theme
(mapc #'disable-theme (delq 'smart-mode-line-dark custom-enabled-themes)))
(setq quick-switch-themes (cdr quick-switch-themes)))
(map! :leader
:desc "Quick toggle theme" "t t" #'toggle-theme)
UI§
Just generic UI settings.
;; This determines the style of line numbers in effect. If set to `nil', line
;; numbers are disabled. For relative line numbers, set this to `relative'.
(setq display-line-numbers-type t)
;; Maximize the window upon startup
;; TODO testing this one
(setq initial-frame-alist '((top . 1) (left . 1) (width . 114) (height . 32)))
;; Transparency
(set-frame-parameter (selected-frame)'alpha '(99 . 100))
(add-to-list 'default-frame-alist'(alpha . (99 . 100)))
Org-mode§
Your life in plain text
Org-mode is one of the most loved major mode on Emacs and one of the better piece of software I happened to met in my life.
At a first sight, it can seems like another markup language, like Markdown or reStructuredText; if it was, it would be a good one, considering the enjoyable syntax. In reality, though, org-mode is way more than that.
Just like Emacs, Org-mode needs a lot of working hours to be known and tamed for good. We can enumerate some common use here:
- simple notes
- literate programming
- planners
- zettelkasten
- scientific writing
- blogging
Now we declare in which directory we want most org files to be placed, in such way that Emacs can know where they should be searched for.
;; If you use `org' and don't want your org files in the default location below,
;; change `org-directory'. It must be set before org loads!
(setq org-directory "~/org/")
Org downloads§
Now we can start configuring Org-mode. I think org-download
is a killer feature of it, since it gives us a way to easily attach elements to the document without never leaving Emacs.
(package! org-download)
Org-download-clipboard is bound to
SPC m a p
in org-mode.
Flashcards§
Org drill§
I occasionally use this package, but I prefer writing my text here, then exporting my cards in Anki, so I mostly do that now.
(package! org-drill)
Anki§
anki-editor – Emacs minor mode for making Anki cards with Org
(package! anki-editor)
In order to make this work, you should install the anki-connect
Anki plugin too.
Org Journal§
Install the package.
(package! org-journal)
Configure the keybindings and some parameters.
;; org journal
;; in ~/.doom.d/+bindings.el
;; From: https://www.rousette.org.uk/archives/doom-emacs-tweaks-org-journal-and-org-super-agenda/
(map! :leader
(:prefix ("j" . "journal") ;; org-journal bindings
:desc "Create new journal entry" "j" #'org-journal-new-entry
:desc "Open previous entry" "p" #'org-journal-open-previous-entry
:desc "Open next entry" "n" #'org-journal-open-next-entry
:desc "Search journal" "s" #'org-journal-search-forever))
;; The built-in calendar mode mappings for org-journal
;; conflict with evil bindings
(map!
(:map calendar-mode-map
:n "o" #'org-journal-display-entry
:n "p" #'org-journal-previous-entry
:n "n" #'org-journal-next-entry
:n "O" #'org-journal-new-date-entry))
;; Local leader (<SPC m>) bindings for org-journal in calendar-mode
;; I was running out of bindings, and these are used less frequently
;; so it is convenient to have them under the local leader prefix
(map!
:map (calendar-mode-map)
:localleader
"w" #'org-journal-search-calendar-week
"m" #'org-journal-search-calendar-month
"y" #'org-journal-search-calendar-year)
(setq org-journal-dir "~/org/amalgam")
(setq org-journal-file-format "%Y-%m.org")
(setq org-journal-file-type 'monthly)
Wikinforg§
Get Wikipedia data directly on org-mode.
(package! wikinforg)
Italian wikipedia§
Spesso mi servono i contenuti in italiano. L'ideale sarebbe scegliere per ogni query.
;; (custom-set-variables '(wikinforg-wikipedia-edition-code "it"))
Purtroppo, i risultati che ottengo da questa versione sono poco accurati. Per il momento la disabiliterò.
Ricerca veloce§
I'm living without right now for similar reasons on why I disabled DEFT (see later); so, I leave the line commented.
;; (package! helm-org-rifle)
Org Web Tools§
Install the package.
(package! org-web-tools)
Zola on org-mode it§
L'exporter per Zola è un pacchetto che sto mantenendo io, quindi capita spesso che io debba testare delle modifiche in locale. package!
gestisce i download, quindi in teoria non dovrebbe essere impiegato per la gestione di file in locale, ma Henrik Lissner consiglia di usare comunque la macro perché è stata adattata anche a questo genere di situazioni.
Aggiunge:
Note: with
:no-byte-compile t
, you don't have to run doom sync every time you make a change to the package.
Così:
(package! ox-hugo :recipe (:local-repo "lisp/ox-zola"))
Peccato che a me dia "runtime error":
Details: ((:private . packages) "home/cromo.doom.d/packages.el" (wrong-type-argument listp (doom-package-error "ox-hugo" . "Keyword argument :no-byte-compile not one of (:local-repo :files :flavor :build :pre-build :post-build :includes :type :repo :host :branch :protocol :remote :nonrecursive :fork :depth :source :inherit)")))
Non ho ben capito perché (che sia questo il problema? non mi pare...), ma ho risolto più brutalmente. Innanzitutto installo il codice dalla mia repo.
(package! ox-hugo :recipe (:host github :repo "gicrisf/ox-zola"))
In secondo luogo, faccio le modifiche in locale e lancio emacs-lisp-byte-compile-and-load
tutte le volte che modifico qualcosa. Finché non riavvio Emacs, è possibile testare quanto si vuole. Forse un po' più scomodo, ma è un approccio che fa il suo sporco lavoro.
Esportare da org a Hugo/Zola Markdown richiede la scrittura di un :PROPERTIES:
frontmatter.
Ma io sono pigro e non mi va di riscrivere ogni volta lo scaffold del frontmatter, quindi ecco una funzione ausiliaria.
;; Generate ORG/Zola frontmatter
;; TODO Section management
;; MAYBE Add hook to org file IF hugo_base_dir or hugo_section is present at top
(defun org-zola-frontmatter (slug)
"Insert org-mode properties under a paragraph to setup ox-hugo/zola exports"
(interactive "sEnter slug: ")
(insert ":PROPERTIES:\n"
(concat ":EXPORT_HUGO_SECTION: 2022/" slug "\n")
":EXPORT_FILE_NAME: index\n"
":END:\n"))
Sempre al fine di automatizzare la produzione dei metadati, meglio automatizzare l'inserimento del timestamp con questa funzione org-mode:
;; add "CLOSED" when an item is set with DONE state
(setq org-log-done 'time)
Org-capture it§
Org capture torna comodo per appuntarsi in org-mode frammenti di pagine web.
Come manipolare l'HTML, però, è qualcosa che noi dobbiamo spiegare ad org-capture
, fornendo uno o più template.
;; org-capture
(setq org-capture-templates `(
("p" "Protocol" entry (file+headline ,(concat org-directory "notes.org") "Inbox")
"* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?")
("L" "Protocol Link" entry (file+headline ,(concat org-directory "notes.org") "Inbox")
"* %? [[%:link][%:description]] \nCaptured On: %U")
))
Al fine di usare Org capture extension (Firefox), dobbiamo anche impostare l'org-protocol.
The gist of it is to make your system recognize emacsclient as the handler of org-protocol:// links. In addition, one needs to set up emacs to load org-protocol and to set up capture templates.
Su linux, bisogna prima registrare questo handler:
[Desktop Entry]
Name=org-protocol
Exec=emacsclient %u
Type=Application
Terminal=false
Categories=System;
MimeType=x-scheme-handler/org-protocol;
A questo punto, su Gnome ed altri GTK-based Desktop Environments, è sufficiente lanciare questo comando:
$ update-desktop-database ~/.local/share/applications/
Citations§
Use CSL format files§
Export processor to use format files written in Citation Style Language (.csl
). This isn't latex-only, so I should be able to use it with Libre Office and HTML too, if needed.
(package! citeproc)
TODO Org Bibliography it§
Tentativo di literate bibliography con org-mode basato su org-bib-mode
, di Nicolas P. Rougier (il creatore di NANO Emacs).
Innanzitutto devo installare le dipendenze dal suo profilo Github.
(package! org-imenu :recipe (:host github :repo "rougier/org-imenu"))
(package! pdf-drop-mode :recipe (:host github :repo "rougier/pdf-drop-mode"))
(package! org-bib-mode :recipe (:host github :repo "rougier/org-bib-mode"))
Purtroppo, quando utilizzo require
su org-imenu
noto che qualcosa non va.
Mi chiedo se il problema sia risolvibile impiegando Nano Emacs, ma non ho tempo per verificare.
Anche se fosse, dubito che abbandonerei Doom Emacs, quindi per ora il tentativo mi pare evitabile.
Lo stesso NPR rimanda ad org-ref
(di John Kitchin) per chi volesse qualcosa di più elaborato.
Anziché aggrovigliare i due blocchi precedenti, aggroviglio i prossimi.
(package! org-ref :recipe (:host github :repo "jkitchin/org-ref"))
Ora configuriamo org-ref.
(setq bibtex-completion-bibliography '("~/org/papers/bibliography.bib"
"~/org/papers/dei.bib"
"~/org/papers/master.bib"
"~/org/papers/archive.bib")
bibtex-completion-library-path '("~/org/papers/bibtex-pdfs/")
bibtex-completion-notes-path "~/org/papers/notes/"
bibtex-completion-notes-template-multiple-files "* ${author-or-editor}, ${title}, ${journal}, (${year}) :${=type=}: \n\nSee [[cite:&${=key=}]]\n"
bibtex-completion-additional-search-fields '(keywords)
bibtex-completion-display-formats
'((article . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} ${journal:40}")
(inbook . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} Chapter ${chapter:32}")
(incollection . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} ${booktitle:40}")
(inproceedings . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} ${booktitle:40}")
(t . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*}"))
bibtex-completion-pdf-open-function
(lambda (fpath)
(call-process "open" nil 0 nil fpath)))
Su consiglio di Kitchin, aggiungo queste impostazioni per semplificarmi il lavoro:
(require 'bibtex)
(setq bibtex-autokey-year-length 4
bibtex-autokey-name-year-separator "-"
bibtex-autokey-year-title-separator "-"
bibtex-autokey-titleword-separator "-"
bibtex-autokey-titlewords 2
bibtex-autokey-titlewords-stretch 1
bibtex-autokey-titleword-length 5)
(define-key bibtex-mode-map (kbd "H-b") 'org-ref-bibtex-hydra/body)
Now require it:
(require 'org-ref)
Vista la complessità della libreria, ho deciso per il momento di non aggrovigliare nulla e aspettare un momento che mi consenta di studiare meglio ogni impostazione.
Org LaTeX export§
We add other extensions to logfiles, to let Emacs delete them after exporting the actual tex file; therefore, we have tidier directories.
(setq org-latex-logfiles-extensions (quote ("lof" "lot" "tex~" "aux" "idx" "log" "out" "toc" "nav" "snm" "vrb" "dvi" "fdb_latexmk" "blg" "brf" "fls" "entoc" "ps" "spl" "bbl" "xmpi" "run.xml" "bcf")))
Org D2 diagrams§
I want to generate D2 diagrams without leaving my org-mode files. Apparently, that's why ob-d2 (an org-babel exporter for D2) was written. It's not on MELPA yet, so I'll get it from its GitHub repo.
(package! ob-d2 :recipe (:host github :repo "dmacvicar/ob-d2"))
Add d2 to org-babel-load-languages
.
(org-babel-do-load-languages
'org-babel-load-languages
'((d2 . t)))
Add d2 to exec-path.
(add-to-list 'exec-path "~/.local/bin/")
Test D2 (d2 requires a ":file" header argument):
{{< figure src="/ox-hugo/test.png" >}}
Org export to JSON§
(package! ox-json)
(require 'ox-json)
Org ref§
(package! org-ref)
Backtab§
I should find an alternative way, because this one doesn't work, so I'm de-tangling it.
;; Source: [[https://stackoverflow.com/questions/23692879/emacs24-backtab-is-undefined-how-to-define-this-shortcut-key]]
(global-set-key (kbd "<backtab>") 'un-indent-by-removing-4-spaces)
(defun un-indent-by-removing-4-spaces ()
"remove 4 spaces from beginning of of line"
(interactive)
(save-excursion
(save-match-data
(beginning-of-line)
;; get rid of tabs at beginning of line
(when (looking-s "^\\at-+")
(untabify (match-beginning 0) (match-end 0)))
(when (looking-at "^ ")
(replace-match "")))))
Emacs Feed Configuration§
Elfeed is an extensible web feed reader for Emacs, supporting both Atom and RSS.
By default, adding feed URLs in this list is enough to let Elfeed work.
(setq elfeed-feeds (quote
(("https://www.zwitterio.it/rss.xml" stem)
("https://materiaimpersonale.wordpress.com/feed/" lit))))
I don't use this method anymore, because I find more comfortable keeping my feeds in a specific org file.
To make elfeed prettier, we add elfeed-goodies
to the packages.
Particularly, this adds a cool powerline and changes the layout (panels are splitten vertically, not horizontally).
(package! elfeed-goodies)
(require 'elfeed-goodies)
(elfeed-goodies/setup)
(setq elfeed-goodies/entry-pane-size 0.5)
You can make a lot of different uses of elfeed: if you just follow some blogs, you probably have no problem with it as it out of the box. Let's say you follow 20, 30, 50 blogs and you love them all. You want to see every news, but every blog posts once a week, if they are active. In this case, elfeed is already perfect, because it shows every result in chronological order.
But, what if you follow sources that publish a lot of content day by day? For example, you follow feeds of governative agencies or scientific publishers, that publish a lot of content day by day. In this case, you better filter out the posts you don't want to see and prioritize the most important ones.
It would be an approach similar to what a lot of social media platforms are doing in this very moment: they let you see the posts of accounts you interact most before any other, then they proceed with others. It doesn't matter that the other are more recent: the point is to maximize the probability you see the stuff you're more interested to, in order to make you interact and stay on the platform as long as you can.
Going back to Emacs, here we're facing an analogo problem: since we all know you're never going to see every single post in your feed, it's fundamental to establish priorities. We will not implement a machine learning model to learn our preference like social media do, but there's a package that keep things simple, and let you score the posts by keywords: not surprisingly, it's called elfeed-score
.
You can see it in action in this interesting Emacs talk, published in 2021. Like said by Ahmed Khaled, the author,
Elfeed-score enables me to assign a numerical score [...] This numerical score is very simple. It's just based on matching things.
We're now fully convinced that we need elfeed-score
, so we install it:
(package! elfeed-score)
Arxiv or ChemRxiv feeds are manipulated in the org file like any other feed.
Now, we have to configure it elfeed-score
. From the docs:
The rules for scoring are written down in the score file, a plain-text file containing a single Lisp form. The location of the score file is defined in
elfeed-score-serde-score-file
.
By default, the configuration is written in a file named elfeed.score
in the .emacs.d
directory:
;;; Elfeed score file -*- lisp -*-
(("title")
("content")
("title-or-content"
(:text "spectroscopy" :title-value 50 :content-value 10 :type s)
(:text "Alzheimer" :title-value 50 :content-value 10 :type s)
(:text "small molecule" :title-value 50 :content-value 10 :type s)
(:text "Peptide" :title-value 50 :content-value 10 :type s)
(:text "Molecular Dynamics" :title-value 50 :content-value 10 :type s)
(:text "infrared" :title-value 100 :content-value 10 :type s))
("tag")
("authors")
("feed")
(mark -600)
("adjust-tags"))
About using regex in the text
field and title-or-content
as a field, I suggest to see at this Chris Cundy's blog post:
So the field (".*[- ]ODE[- s].*" 100 20 R 1596818708.18127) is a case-sensitive (specified by the R) regexp matching against any of " ODEs”, " ODE “, " ODE-", etc. If a match occurs in the title it adds 100 to the score of the entry. If a match occurs in the content field (for us, this is the abstract of the paper) it will add 20 to the score of the entry. The scale is arbitrary, but I’m aiming for a score of 0 for papers I may want to read, 100 for papers I will probably want to read, 200 for papers I will very likely want to read, and 300 for papers I will certainly want to read. I generally put the content matches with a lower score since they may occur multiply times and e.g. I don’t want to miss an interesting paper just because one of the applications was an area I’m not interested in.
With the authors
field, you can push up specific authors' work.
Finally, we activate elfeed-score
by adding these lines in the init file:
(require 'elfeed-score)
(elfeed-score-enable)
(define-key elfeed-search-mode-map "=" elfeed-score-map)
Linguaggi it§
Typescript/React§
Innanzitutto, bisogna avere aggiunto alcuni moduli: web
e javascript
, in particolare.
Per farlo, basta togliere ;;
nel file di configurazione .doom.d/init.el
, come fatto nel paragrafo sopra.
A questo punto, è possibile che uno voglia lavorare con file in formato .tsx
. Il supporto per questo caso d'uso potrebbe arrivare presto, ma per il momento ci viene in soccorso una semplice riga di lisp nel file di configurazione, secondo il suggerimento di hlissner:
;; Support for Typescript/React
(add-to-list 'auto-mode-alist '("\\.tsx\\'" . typescript-mode))
-
Vanilla Emacs
In caso foste in cerca di una soluzione per Vanilla Emacs o Spacemacs, quest'altra soluzione potrebbe fare al caso vostro:
(use-package typescript-mode :mode (rx ".ts" string-end) :init (define-derived-mode typescript-tsx-mode typescript-mode "typescript-tsx") (add-to-list 'auto-mode-alist (cons (rx ".tsx" string-end) #'typescript-tsx-mode)))
Praticamente dichiariamo una modalità derivata dalla
typescript-mode
e le assegniamo anche i file con estensione.tsx
. Per maggiori dettagli, fate riferimento a questo issue su Github.
Vala§
Il supporto per Vala è largamente ereditato dalla mode per C#.
(package! vala-mode)
Python§
Supporto per virtualenv.
(package! pyvenv)
Dired§
Drag and drop to dired:
(add-hook 'dired-mode-hook 'org-download-enable)
Markdown it§
Funzioni ausiliarie che ho scritto per facilitarmi il lavoro quando scrivevo in Markdown per Zola. Come già spiegato sopra, ora esporto da org-mode, quindi l'utilità di queste funzioni è venuta meno, ma occasionalmente mi capita di impiegarle, quindi le lascio comunque.
TOML frontmatter (Zola)§
Immaginate di voler generare un nuovo file Markdown per il vostro sito web. In base al tipo di generatore, questo potrà avere bisogno di un frontespizio in TOML o in YAML, magari. Si tratta di pochi caratteri, ma scriverli di volta in volta può risultare un po' frustrante, soprattutto se si scrivono molti pezzi.
Allora perché non lasciare che sia Emacs a fare il lavoro per noi? Siccome non sono il primo ad essermi posto questa domanda, ho semplicemente riformulato una soluzione largamente adottata. La forza del programmatore, d'altronde, è la sua pigrizia.
Iniziamo scrivendo una funzione che generi il blocco di testo di cui abbiamo bisogno. Io utilizzo Zola per generare il mio blog, quindi potrei scrivere il frontespizio anche in YAML, ma TOML è il formato di riferimento (ed è anche quello che preferisco, senza alcun dubbio).
Vogliamo quindi ottenere qualcosa del genere:
+++
title=""
date=
[taxonomies]
categories=[""]
tags=[""]
[extra]
+++
Traduciamo in lisp:
;; Generate TOML frontmatter
(defun new-toml-frontmatter ()
"Insert a TOML frontmatter for Markdown files"
(interactive)
(insert "+++\n"
"title=\"\"\n"
"date=\n"
"\n"
"[taxonomies]\n"
"categories=[\"\"]\n"
"tags=[\"\"]\n"
"\n"
"[extra]\n"
"+++"))
Da EmacsWiki:
A Lisp function becomes a command when its body contains, at top level, a form that calls the special form `(interactive...)’. This special form does nothing when executed, but its presence in the function definition indicates that interactive calling is permitted. Its argument controls the reading of the function arguments in an interactive call.
Il resto penso sia fin troppo comprensibile perché meriti spiegazione.
Aggiungiamo questa nuova funzione a .doom.d/config.el
(o .emacs
in Vanilla Emacs).
Poiché le funzioni nel config vengono rese disponibili al lancio di Emacs, è necessario un doom/reload
(SPC-h-r
).
Già invocare questa funzione nel momento della creazionee del file è ben più comodo della situazione di partenza, in cui dovevamo di volta in volta scrivere l'intero frontespizio. MA non è sufficiente: noi vogliamo che il frontespizio sia automaticamente generato su ogni file markdown nuovo di zecca.
Con la funzione add-hook
possiamo agganciare il lancio della nostra funzione ad una modalità. Nel nostro caso, la markdown-mode
:
(add-hook 'markdown-mode-hook
(lambda ()
(if (= (buffer-size) 0)
(new-toml-frontmatter))
(message "markdown hook")))
Da ora in avanti, basterà aprire un file Markdown vuoto perché Emacs inserisca automaticamente il frontespizio.
Shortcode (Zola)§
Con lo stesso approccio, si possono anche ottenere delle funzioni per aggiungere degli shortcode molto usati nel corpo del testo e persino associare delle combinazioni di tasti ad esse!
;; Generate Zola Shortcodes
(defun new-social-shortcode ()
"Generate new twitter shortcode"
(interactive)
(insert "{% social\(\n"
"social=\"tw\",\n"
"url=\"\",\n"
"author=\"\",\n"
"date=\"\"\n"
"\) %}"
"\n"
"{% end %}"))
Uniamoci, confratelli, nell'amore per Emacs.
Twitter it§
Questo piccolo pacchetto (che conto di estendere presto) nasce per assolvere ad una funzione molto semplice: citare i tweet nel mio blog. Ne racconto qui:
(package! eltweet :recipe (:host github :repo "gicrisf/eltweet"))
Mastodon it§
Prima di tutto, installiamo mastodon.el:
(package! mastodon)
Io sono su "@gicrisf@fosstodon.org", quindi:
(setq mastodon-instance-url "https://fosstodon.org"
mastodon-active-user "gicrisf")
Sono meravigliato da quanto facile sia stato arrivare alla propria TL da Emacs grazie a mastodon.el, ma il layout di default è veramente insostenibile. Fortunatamente, Nicolas Rougier ha già pubblicato un gist in cui rielabora il layout per adeguarlo alla propria configurazione. Io non uso NANO, quindi servirà qualche ritocco sicuramente.
Music§
The following lines are widely commented in a specific post.
;; Play Lo-Fi
;; Implementation of the knuth shuffle
;; TODO Start amberol or other music player
(defun nshuffle (sequence)
(cl-loop for i from (length sequence) downto 2
do (cl-rotatef (elt sequence (random i))
(elt sequence (1- i))))
sequence)
(setq lofi-links '("https://www.youtube.com/watch?v=8nXqcugV2Y4" ;; 3:30 music session
"https://www.youtube.com/watch?v=FVue6P2VoTc"
"https://www.youtube.com/watch?v=NrJiXKwUjPI" ;; Music to put you in a better mood
"https://www.youtube.com/watch?v=kgx4WGK0oNU"
"https://www.youtube.com/watch?v=5qap5aO4i9A"))
(setq vaporwave-links '("https://www.youtube.com/watch?v=nVCs83gSYD0" ;; architecture in tokyo - Summer Paradise
))
(defun play-lofi ()
"Play random lofi music on your browser"
(interactive)
(shell-command (concat "python -mwebbrowser " (car (nshuffle lofi-links)))))
(defun play-vaporwave ()
"Play random lofi music on your browser"
(interactive)
(shell-command (concat "python -mwebbrowser " (car (nshuffle vaporwave-links)))))
Pretty print§
I usually use this one for pretty printing HTML, but it runs fine on any XML chunk.
(defun bf-pretty-print-xml-region (begin end)
"Pretty format XML markup in region. You need to have nxml-mode
http://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do
this. The function inserts linebreaks to separate tags that have
nothing but whitespace between them. It then indents the markup
by using nxml's indentation rules."
(interactive "r")
(save-excursion
(nxml-mode)
(goto-char begin)
(while (search-forward-regexp "\>[ \\t]*\<" nil t)
(backward-char) (insert "\n") (setq end (1+ end)))
(indent-region begin end)
(normal-mode))
(message "Ah, much better!"))
Which key§
Let’s make this popup a bit faster
From From tecosaur's configuration:
(setq which-key-idle-delay 0.5) ;; I need the help, I really do
Semantic analysis it§
Rust (Racer)§
Racer used to be the best option for getting IDE features (code navigation etc) into Emacs. It is a non-LSP solution which is still faster than RLS and rust-analyzer. However, the number of features especially around code completion are not up to par with rust-analyzer anymore.
Il consiglio, quindi, è quello di passare direttamente al paragrafo successivo, ma chi proprio desiderasse Racer (che era piacevole), lascio qui tutte le istruzioni del caso.
Dopo avere abilitato rust
in init.el
, Doom Emacs lamentava l'introvabilità del binario di Racer:
Please set ‘racer-rust-src-path’ or ‘RUST_SRC_PATH’
Il primo problema derivava non tanto dal fatto che fosse scorretta la variabile racer-rust-src-path
, ma che proprio non esistesse alcuna src-path
perché bisognava prima che installarla:
rustup component add rust-src
Ma si ottiene un altro errore:
eldoc error: (user-error ....cargo/bin/racer exited with 127. ‘M-x racer-debug’ for more info)
Questo perché manca racer, che va installato a parte. Siccome Racer risiede nella nightly toolchain, installiamo prima quella:
rustup toolchain install nightly
Poi aggiungiamo gli strumenti da sviluppatore rustc-dev
:
rustup component add rustc-dev --toolchain=nightly
Assicuriamoci che anche Cargo sia già installato e lanciamo:
cargo +nightly install racer
La compilazione potrebbe fallire, ma bisogna tenere a mente è che Racer non è al momento mantenuto:
Racer is not actively developped now. Please consider using newer software such as rust-analyzer.
Emacs potrebbe non individuare subito Racer, nonostante l'installazione.
"~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library"
Quick fix per consentire ad Emacs di trovare i binari di Racer:
;; (setq racer-rust-src-path <<racer-path>>)
Io non uso più Racer, ma eldoc si ostina a farlo, dando sempre questo fastidiosissimo errore:
eldoc error: (user-error home/cromo.cargo/bin/racer exited with 127. ‘M-x racer-debug’ for more info)
The
:lang rust
module doesn't userust-mode
, it uses rustic-mode, a fork ofrust-mode
.When
+lsp
is not enabled, the module usesracer
to provide code completion, type info in the minibuffer (eldoc) and other features, but the racer package depends onrust-mode
, so it must be installed (but doom still doesn't use it directly).
Bisogna perciò evitare che Racer sia avviato tutte le volte che LSP non è attivo. Come ricordato da @subderisorious, per fortuna Doom ci consente di disabilitare un pacchetto della configurazione di default semplicemente richiamando la macro package!
in packages.el
.
(package! racer :disable t)
Rust (rust-analyzer)§
Circa sei mesi dopo, è tempo di dare un'occhiata a rust-analyzer. Dal manuale:
At its core, rust-analyzer is a library for semantic analysis of Rust code as it changes over time. This manual focuses on a specific usage of the library — running it as part of a server that implements the Language Server Protocol (LSP). The LSP allows various code editors, like VS Code, Emacs or Vim, to implement semantic features like completion or goto definition by talking to an external language server process.
Anche questa volta, possiamo usare rustup
:
rustup component add rust-src
Io sto su Arch, quindi installo con pacman:
sudo pacman -S rust-analyzer
È il caso di specificare quale server intendiamo utilizzare, altrimenti Rustic potrebbe fraintendere o optare per Racer:
(setq rustic-lsp-server 'rust-analyzer)
Questo dovrebbe essere sufficiente, ma per essere proprio sicuri:
(after! lsp-rust
(setq lsp-rust-server 'rust-analyzer))
Lanciamo lsp
in un buffer con Rust ed assistiamo al compiersi della magia.
Curriculum Vitae it§
Trovandomi costretto, ancora una volta, a scrivere un CV, mi sono detto, ancora una volta, quanto fosse necessario trovare un modo perché fosse l'ultima. Eppure, non importa quanto tempo si passi ad ideare degli automatismi, il CV è qualcosa di intrinsecamente in via di definzione, quindi sempre soggetto a cambiamenti. Non si può fare altro che rimaneggiarlo continuamente. Bisogna quindi focalizzarsi sulla via che garantisca l'attrito minore, così da rendere la pratica degli aggiornamenti non troppo detestabile. Il generato più importante di un CV, ad oggi, è sempre il formato stampabile, cioè un PDF. Ad un buon PDF si può arrivare principalmente per queste vie:
- LaTeX
- LibreOffice, Microsoft Office o altre suite d'ufficio WYSIWYG
- Immagini (SVG e vettoriali in genere)
A me piacerebbe, però, anche avere una pagina web sempre aggiornata, quindi gestire un file esportabile sia in PDF (più o meno direttamente) che in HTML. LaTeX è scomodo per esportare in formati web ed io vorrei mantenere una matrice utile ad esportare da ambo i lati con anche piccole differenze (senza mantenere due file o due branch paralleli su git). C'è chi ottiene questo risultato esportando a partire da un JSON, ma figurarsi se mi metto a scrivere un JSON a mano. Si potrebbe mantenere un YAML/TOML da esportare in JSON che poi esporti nei vari formati, ma comunque mi sembra una strategia poco flessibile.
Sulla base di queste premesse, ho da poco cominciato a mantenere il mio CV in org-mode; poiché l'esportazione avviene attraverso LaTeX (via template AltaCV), torna comoda qualche funzione che tenga in ordine la directory di output ad ogni modifica.
(after! org
;; Import ox-latex to get org-latex-classes and other funcitonality
;; for exporting to LaTeX from org
(use-package! ox-latex
:init
;; code here will run immediately
:config
;; code here will run after the package is loaded
(setq org-latex-pdf-process
'("pdflatex -interaction nonstopmode -output-directory %o %f"
"bibtex %b"
"pdflatex -interaction nonstopmode -output-directory %o %f"
"pdflatex -interaction nonstopmode -output-directory %o %f"))
(setq org-latex-with-hyperref nil) ;; stop org adding hypersetup{author..} to latex export
;; (setq org-latex-prefer-user-labels t)
;; deleted unwanted file extensions after latexMK
;; (setq org-latex-logfiles-extensions
;; (quote ("lof" "lot" "tex~" "aux" "idx" "log" "out" "toc" "nav" "snm" "vrb" "dvi" "fdb_latexmk" "blg" "brf" "fls" "entoc" "ps" "spl" "bbl" "xmpi" "run.xml" "bcf" "acn" "acr" "alg" "glg" "gls" "ist")))
(unless (boundp 'org-latex-classes)
(setq org-latex-classes nil))))
(after! org
(use-package! ox-extra
:config
(ox-extras-activate '(latex-header-blocks ignore-headlines))))
Manuali it§
Le pagine dei manuali su Emacs mancano spesso di colore, cosa che le rende più difficili da leggere delle loro controparti web. Il seguente pacchetto corregge questa mancanza:
(package! info-colors)
Come illustrato nel README, per abilitarlo bisogna aggiungere un hook in config.el
.
(add-hook 'Info-selection-hook 'info-colors-fontify-node)
Deft§
Set directory, extension to search for and explicitly say you want to search recursively in the subfolders.
;; Not using deft rn
(setq deft-directory "~/org"
deft-extensions '("org" "txt"))
(setq deft-recursive t)
The main function is too heavy and I don't really need using all deft features.
I'm detangling this block because I prefer simply using SPC n s
for the moment (notes/search note).
Dashboard it§
Open org configuration (SPC o c)§
Al posto di aprire la cartella .doom.d
per configurare Emacs, da ora in avanti vogliamo aprire questo file direttamente, quindi la funzione nella dashboard va modificata.
Per riuscirci, innanzitutto dobbiamo creare una funzione che apra questo file.
Ci servono due elementi, che possono variare di caso in caso:
- Il nome del file
- La directory in cui cercarlo
(setq config-org-file-name "config.org"
config-org-directory "~/.doom.d")
Scriviamo una funzione dedicata all'apertura del file preselezionato.
(defun open-config-org ()
"Open your private config.org file."
(interactive)
(find-file (expand-file-name config-org-file-name config-org-directory)))
Assegniamo una scorciatoia da tastiera dedicata, sulle orme di SPC+f+P
(file > Private).
In your
config.el
file add a map declaration using the:leader
attribute and whatever prefix key you would like to use. Then after you have added the necessary prefix keys add a:desc "Description of the command"
"key" #'elisp-command-to-execute
for each shortcut you wish to add.
Con map!
:
(map! :leader
(:prefix-map ("o" . "open")
:desc "Open your private config.org file." "c" #'open-config-org))
Per intervenire sul menù, prima diamo un'occhiata alle sezioni della dashboard.
(cl-subseq +doom-dashboard-menu-sections 0)
Otteniamo una lista, da cui estrapoliamo la funzione che vogliamo sostituire (questa):
("Open private configuration" :icon (all-the-icons-octicon "tools" :face 'doom-dashboard-menu-title) :when (file-directory-p doom-private-dir) :action doom/open-private-config)
Come intendiamo modificarla? Così:
("Open org configuration" :icon (all-the-icons-octicon "tools" :face 'doom-dashboard-menu-title) :action open-config-org)
Ora sostituiamola al menù con la funzione setf
.
(setf (nth 5 +doom-dashboard-menu-sections) '("Open org configuration" :icon (all-the-icons-octicon "tools" :face 'doom-dashboard-menu-title) :action open-config-org))
Enter Elfeed (SPC e e)§
Ripercorro i passi fatti prima, ma stavolta senza dilungarmi in chiacchiere.
Prima assegno una scorciatoia da tastiera:
(map! :leader
(:prefix-map ("e" . "elfeed")
:desc "Enter elfeed." "e" #'elfeed))
Voglio questo elemento sulla dashboard:
("Open elfeed" :icon (all-the-icons-octicon "rss" :face 'doom-dashboard-menu-title) :action elfeed)
Stavolta vado a sostituire il terzo elemento, che raramente uso (Recently opened files
).
(setf (nth 2 +doom-dashboard-menu-sections) '("Open elfeed" :icon (all-the-icons-octicon "rss" :face 'doom-dashboard-menu-title) :action elfeed))
Già che ci siamo, aggiungiamo una shortcut per aggiornare elfeed:
(map! :leader
(:prefix-map ("e" . "elfeed")
:desc "Update all the feeds in elfeed." "u" #'elfeed-update))
Quit and go Home (SPC q h)§
Una semplice scorciatoia da tastiera per tornare alla dashboard:
(map! :leader
(:prefix-map ("q" . "quit/session")
:desc "Switch to the dashboard in the current window, of the current FRAME." "h" #'+doom-dashboard/open))
Org Manual (SPC o i)§
Move "Open project" section of the dashboard and make space for the documentation.
Anche stavolta andiamo spediti.
Voglio questo elemento sulla dashboard:
("Open info" :icon (all-the-icons-octicon "info" :face 'doom-dashboard-menu-title) :action info)
Stavolta vado a sostituire il terzo elemento, che raramente uso (Recently opened files
).
(setf (nth 3 +doom-dashboard-menu-sections) '("Open info" :icon (all-the-icons-octicon "info" :face 'doom-dashboard-menu-title) :action info))
Riprendiamo l'elemento rimosso...
("Open project" :icon (all-the-icons-octicon "briefcase" :face 'doom-dashboard-menu-title) :action projectile-switch-project)
... e sistemiamolo in prima posizione:
(setf (nth 0 +doom-dashboard-menu-sections) '<<switch-project-menu-section>>)
Aggiungiamo una scorciatoia per org-mode, che è una delle documentazioni più consultate dal sottoscritto.
(map! :leader
(:prefix-map ("o" . "open")
:desc "Open org manual." "i" #'org-info))
Doom documentation (SPC h d h)§
Just changing the name.
("Doom documentation" :icon (all-the-icons-octicon "book" :face 'doom-dashboard-menu-title) :action doom/help)
Lasciamo che resti in sesta posizione:
(setf (nth 6 +doom-dashboard-menu-sections) '<<open-doom-docs-menu-section>>)
Banner§
Experimental. Just trying stuff out, but I stick with the regular banner for the moment.
See this discourse post.
A weebish example (not tangled code):
(defun my-weebery-is-always-greater ()
(let* ((banner '("⢸⣿⣿⣿⣿⠃⠄⢀⣴⡾⠃⠄⠄⠄⠄⠄⠈⠺⠟⠛⠛⠛⠛⠻⢿⣿⣿⣿⣿⣶⣤⡀⠄"
"⢸⣿⣿⣿⡟⢀⣴⣿⡿⠁⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⣸⣿⣿⣿⣿⣿⣿⣿⣷"
"⢸⣿⣿⠟⣴⣿⡿⡟⡼⢹⣷⢲⡶⣖⣾⣶⢄⠄⠄⠄⠄⠄⢀⣼⣿⢿⣿⣿⣿⣿⣿⣿⣿"
"⢸⣿⢫⣾⣿⡟⣾⡸⢠⡿⢳⡿⠍⣼⣿⢏⣿⣷⢄⡀⠄⢠⣾⢻⣿⣸⣿⣿⣿⣿⣿⣿⣿"
"⡿⣡⣿⣿⡟⡼⡁⠁⣰⠂⡾⠉⢨⣿⠃⣿⡿⠍⣾⣟⢤⣿⢇⣿⢇⣿⣿⢿⣿⣿⣿⣿⣿"
"⣱⣿⣿⡟⡐⣰⣧⡷⣿⣴⣧⣤⣼⣯⢸⡿⠁⣰⠟⢀⣼⠏⣲⠏⢸⣿⡟⣿⣿⣿⣿⣿⣿"
"⣿⣿⡟⠁⠄⠟⣁⠄⢡⣿⣿⣿⣿⣿⣿⣦⣼⢟⢀⡼⠃⡹⠃⡀⢸⡿⢸⣿⣿⣿⣿⣿⡟"
"⣿⣿⠃⠄⢀⣾⠋⠓⢰⣿⣿⣿⣿⣿⣿⠿⣿⣿⣾⣅⢔⣕⡇⡇⡼⢁⣿⣿⣿⣿⣿⣿⢣"
"⣿⡟⠄⠄⣾⣇⠷⣢⣿⣿⣿⣿⣿⣿⣿⣭⣀⡈⠙⢿⣿⣿⡇⡧⢁⣾⣿⣿⣿⣿⣿⢏⣾"
"⣿⡇⠄⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⢻⠇⠄⠄⢿⣿⡇⢡⣾⣿⣿⣿⣿⣿⣏⣼⣿"
"⣿⣷⢰⣿⣿⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⢰⣧⣀⡄⢀⠘⡿⣰⣿⣿⣿⣿⣿⣿⠟⣼⣿⣿"
"⢹⣿⢸⣿⣿⠟⠻⢿⣿⣿⣿⣿⣿⣿⣿⣶⣭⣉⣤⣿⢈⣼⣿⣿⣿⣿⣿⣿⠏⣾⣹⣿⣿"
"⢸⠇⡜⣿⡟⠄⠄⠄⠈⠙⣿⣿⣿⣿⣿⣿⣿⣿⠟⣱⣻⣿⣿⣿⣿⣿⠟⠁⢳⠃⣿⣿⣿"
"⠄⣰⡗⠹⣿⣄⠄⠄⠄⢀⣿⣿⣿⣿⣿⣿⠟⣅⣥⣿⣿⣿⣿⠿⠋⠄⠄⣾⡌⢠⣿⡿⠃"
"⠜⠋⢠⣷⢻⣿⣿⣶⣾⣿⣿⣿⣿⠿⣛⣥⣾⣿⠿⠟⠛⠉⠄⠄ "))
(longest-line (apply #'max (mapcar #'length banner))))
(put-text-property
(point)
(dolist (line banner (point))
(insert (+doom-dashboard--center
+doom-dashboard--width
(concat line (make-string (max 0 (- longest-line (length line))) 32)))
"\n"))
'face 'doom-dashboard-banner)))
(setq +doom-dashboard-ascii-banner-fn #'my-weebery-is-always-greater)
Zen mode§
Serif§
Using a serif font for Zen mode:
(defvar +zen-serif-p t
"Whether to use a serifed font with `mixed-pitch-mode'.")
Detangled because I don't like this anymore. Maybe I should look for a totally different font with Zen mode.
Weather it§
Esiste già un frontend per Emacs, ma è da almeno cinque anni che non dà segni di manutenzione. Quindi lavorerò sul mio fork (tanto avevo comunque intenzione di aggiungere funzioni supplementari, avrei probabilmente forkato a prescindere).
Innanzitutto aggiungiamo questo pacchetto:
(package! wttrin :recipe (:host github :repo "gicrisf/emacs-wttrin"))
Qui lo configuro secondo le mie necessità:
(setq wttrin-default-cities '("Caltagirone" "Bologna" "Ferrara" "Catania"))
(setq wttrin-default-accept-language '("Accept-Language" . "it-IT"))
Daemon§
Si tratta di una possibilità introdotta con Emacs 23.1 per ridurre i (già bassi) tempi di avvio di ogni finestra. Ottimo se, come me, utilizzate Emacs anche per modificare piccoli file di testo per cui andrebbe benissimo vim o nano.
Per lanciare il daemon da terminale, basta scrivere:
emacs --daemon
Facile, no? Per lanciarlo all'avvio, si può aggiungere il comando qui sopra nella sezione opportuna fornita dal DE o, meglio ancora, perdere mezzo minuto per impostare systemd (utile soprattutto per chi usa un tiling manager anziché un DE "fatto e finito").
[Unit]
Description=Emacs text editor
Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/
[Service]
Type=forking
ExecStart=/usr/bin/emacs --daemon
ExecStop=/usr/bin/emacsclient --eval "(kill-emacs)"
Environment=SSH_AUTH_SOCK=%t/keyring/ssh
Restart=on-failure
[Install]
WantedBy=default.target
Per abilitare, lanciare due comandi:
systemctl enable --user emacs
systemctl start --user emacs
Ovviamente non mi sono inventato nulla, sto solo riprendendo la documentazione. L'approccio qui sopra non funziona se usate CentOS o, chiaramente, se non usate systemd. Ma, solitamente, chi non usa systemd non ha bisogno che glielo dica io, perché se l'è andata a cercare.
Fatto ciò, non è sufficiente avviare Emacs con il consueto comando emacs
, perché quello continuerebbe ad avviare un'istanza per ogni finestra.
È necessario specificare che vogliamo solo lanciare un client.
Al posto di emacs
, scriveremo:
emacsclient --create-frame --alternate-editor=""
Chiaramente, scrivere di volta in volta questo comando è a dir poco noioso, quindi ci conviene aggiungere degli alias su .bashrc
o lanciarlo con una scorciatoia da tastiera, a seconda del nostro ambiente.
Intendo pubblicare a breve i miei bash dots, stay tuned.
Conclusions§
This is file is in constant change: more like a partially molded amorphous substance than like a liquid, but still in constant change.
TODOs:
- Riportare sotto org tutte le funzioni relative (per ora mantenuto quanto più vicino possibile all'originale per evitare casini)
- Write a decent conclusion
- Translate everything in english and export the translated file to the blog.
da init file di Doom Emacs
Questo post ti è stato utile?
Tieni a mente che questo sito è privo di tracker, analytics e pubblicità, quindi tutela la tua privacy ma non guadagna dalle visite (inoltre, è progettato per avere un impatto ambientale minimo).
Se ti piace questo blog, sostieni le mie riserve di caffeina