In this post, I want to briefly talk about how to set up liking to another note via
[[Title of the target note]] syntax.
This is related to official manual’s section on Completions.
See the outcome in this GIF animation.
It may not look much, but there are a couple of components working together.
When you type
[[, the closing brackets
]]gets automatically inserted
[[Title of a note]]establishes a link (and backlink) as it is. It does not automatically change to the normal file link when you save the note
You type two characters “in”; Emacs automatically suggests candidate notes’ titles, and the matching is case-insensitive
You select a candidate, and hit the
Tabkey; the candidates are narrowed down up to their common part “introduction_” ("_" indicates a space, discarding note entitled “Introduction”), and this partial completion is case-insensitive
You hit the
Enterkey to select a note; the cursor automatically goes out of the
]]bracket, so that you can keep typing
(Idea to tweak UX further) There is some development idea I have posed separately
[Added 30 Sept 2020] If you prefer auto-completion without “[[”, there is a way. Open the quote box just below here:
You can easily set up your Emacs configuration to do 1–3; I will show you how in a minute.
Point 4 turns out to require local change to code (add one line) in
company-capf.el. As far as I can see there is no easy way around it; let me know if you know a good way. I will sleep on it a couple of nights, and then will probably raise a PR in the Company project’s GitHub repo. I will show you the code change I have done to get it to work.
For Point 5, I raised a PR to the Org-roam project; Jethro and I had a brief exchange. It has turned out Jethro has been working on some changes in this area (
completion-at-point). What I am writing here might need some tweaking to align with the upcoming changes, but I believe you can still take away the principle from this brief post.
See the excerpt of configuration with my comments relevant for points 1–3.
This is for vanilla Emacs.
;; Smartparens ;; To automatically close "]]" brackets and other parentheses, ;; you need a package called "smartparens" Set it up globally. (smartparens-global-mode t) ;; Company ;; You need package called `company`. ;; I believe what these variables are meant to do is self-explanatory. ;; You type minimum 2 characters and wait for ¼ seconds for the candidates ;; to appear automatically. It uses a backend `company-capf` (part of ;; `company`; capf stands for "completion-at-point function"). I would ;; call it inline automatic completion. Org-roam has functions to work ;; with `company-capf`. (add-hook 'after-init-hook 'global-company-mode) (setq company-minimum-prefix-length 2) (setq company-idle-delay 0.25) (add-to-list 'company-backends 'company-capf) ;; This enables candidates matching to be case-insensitive (setq completion-ignore-case t) ;; You need this for your org-roam part of configuration ;; This prevents it from automatically replacing [[Title of a note]] ;; into [[file:path/to/note][Title of a note]]. ;;(setq org-roam-auto-replace-fuzzy-links nil) ;; Some keybindings for within Company mode ;; Use (with-eval-after-load) to defer the use of `company-active-map`. ;; Otherwise, Emacs will error when loading `init.el` as it does not ;; recognise any Company related variables and functions yet. ;; This delay is defined above as we load 'global-company-mode' with ;; `after-init-hook`. (with-eval-after-load 'company (define-key company-active-map (kbd "C-n") #'company-select-next) (define-key company-active-map (kbd "C-p") #'company-select-previous))
For Doom, it has modules for Company (in
company) and Smartparens (in
(default +smartparens)). Because these modules already set most of the variables above for you, I believe you just need to add these two variables.
;; This enables matching candidates case-insensitive (setq completion-ignore-case t) ;; You need this for your org-roam part of configuration ;; This prevents it from automatically replacing [[Title of a note]] ;; into [[file:path/to/note][Title of a note]]. ;;(setq org-roam-auto-replace-fuzzy-links nil)
Even the keybindings for Company mode seem to be done for you via the module.
Partial completion (
As far as I could check, you can’t do this with configuration alone. If your candidates contain different cases (via
completion-ignore-case set to
t), hitting a tab key does not do what the GIF animation shows you.
Your candidates are matched case-insensitive, but your partial completion works case-sensitive… I would like consistency in these two matching commands for my use case.
Long story short, you need to change the source of
company-capf.el to enable
ignore-case function – not part of the source. My sample implementation adds one line to add
ignore-case and uses
completion-ignore-case to keep consistency; it works as shown in the animated GIF in the beginning of this post.
This is it for this brief how-to tip.
I will probably come back to this post once Jethro’s new changes have been rolled into the master branch of Org-roam.
'til then, keep roaming