Finally Got My Emacs Setup Just How I Like It

Posted on 24th of February 2023 | 745 words

So in recent days, I have stumbled upon some REALLY NICE (at least in my own standards) Emacs tweaks, which I wanted to share with you.

First, something very trivial, I knew that Emacs had some sort of jump to previous location etc., type of feature available, but I never got into using it. Turns out there’s is a built-in keybinding for that or a couple. First, one was C-x C-x, which jumps to the last position and selects the text from your current position. So, e.g. you jump to the beginning of a file and press that combination, it selects the text from the beginning to the last position. Which was cool for me, but I rarely need something like that.

That was enough for me for some time, but I wanted to tweak it slightly. I didn’t care about selection and wanted to centre the screen after the jump. Thankfully, this is relatively trivial to implement in Emacs with a single function:

(defun jump-to-mark-and-center (arg)
  (interactive "*p")
  (goto-char (mark))
  (recenter))

(global-set-key (kbd "C-x C-x") 'jump-to-mark-and-center)

So I bound the old keybinding to that new function, which does exactly what I want. Lovely!

To the second lovely new configuration! I had longed for a feature in Emacs, where I could find a file based on the format of FILENAME:LINENUMBER. So, if I would have a file, let’s say file.cc and I would immediately jump to the line number 14 in that file, I would want to open that file with file.cc:14 like most of the Unix tools print these file locations, but I just couldn’t do it in Emacs.

Thankfully, after some searching throughout the interwebs, I found some nice defadvice that fixes this for me:

(defadvice find-file (around find-file-line-number
                             (filename &optional wildcards)
                             activate)
  (save-match-data
    (let* ((matched (string-match "^\\(.*\\):\\([0-9]+\\):?$" filename))
           (line-number (and matched
                             (match-string 2 filename)
                             (string-to-number (match-string 2 filename))))
           (filename (if matched (match-string 1 filename) filename)))
      ad-do-it
      (when line-number
        ;; goto-line is for interactive use
        (goto-char (point-min))
        (forward-line (1- line-number))))))

And BAM! It works just like that!

And the last lovely new feature! I use mainly vterm inside my Emacs for my terminal needs. I always wanted to use it so that when I’m inside a certain directory in the terminal, I could just open some file in that directory, but unfortunately, by default, vterm only knows the directory where it was opened at.

Thankfully, after reading some documentation about vterm, it turns out you’re able to send certain character codes to emacs from your vterm session. So you’re able to make it so that when you open vterm in directory x and proceed to change the directory inside the vterm with many different cd commands etc. to something like x/many/different/subdirs, when I run something like C-x C-f in that vterm buffer, the minibuffer inside Emacs, would know that I want to file directory in the directory where vterm currently is, instead of the directory where it was initially opened.

This can be done by doing some shell tweaking. I use zsh myself, if you use something else, refer to vterm README .

# Enable the shell to send information to vterm via properly escaped
# sequences.
vterm_printf() {
  printf "\e]%s\e\\" "$1"
}

vterm_prompt_end() {
  vterm_printf "51;A$(whoami)@$(hostname):$(pwd)"
}

 Let vterm know what dir I'm in
setopt PROMPT_SUBST
PROMPT=$PROMPT'%{$(vterm_prompt_end)%}'

If you happen to use screen or tmux, you might need to do some other tweaks in there, but these are mentioned in the vterm README.

In any case, when you define those to your .zshrc, vterm sends the information of the current directory straight to Emacs, so it knows where you’re currently at. Which is great!

To make that even better, I often noticed that I wanted to open files straight from the command line instead of running some Emacs command to open the files. Fortunately, vterm covers this also:

vterm_cmd() {
  local vterm_elisp
  vterm_elisp=""
  while [ $# -gt 0 ]; do
    vterm_elisp="$vterm_elisp""$(printf '"%s" ' "$(printf "%s" "$1" | sed -e 's|\\|\\\\|g' -e 's|"|\\"|g')")"
    shift
  done
  vterm_printf "51;E$vterm_elisp"
}

find_file() {
  vterm_cmd find-file "$(realpath "${@:-.}")"
}

alias e="find_file"

With these functions inside your .zshrc, I can run find_file inside vterm, and it opens the file in your current Emacs session. I just use short alias to run e somefile inside the terminal; it opens a new buffer for the file.

I have used Emacs for a long time, but these recent additions made it so much nicer. Hopefully, these are helpful for you too.

Machine Learning Would Have Advanced Faster With Lisp

Posted on 22nd of February 2023 | 97 words Lisp cycles (c) xkcd

Turing Award winner Yann LeCun dropping some much needed wisdom about ML advancements :

Hotter take: ML would have advanced faster if another front-end language had been available and widely adopted instead of Python.

One that is interactive yet fast & compilable, multithreaded (no GIL), isn’t bloated, doesn’t care about white spaces,…

E.g. Julia or some Lisp.

Hot take: Machine Learning would not have been nearly as advanced now were it not for Python. Python’s two main virtues in the context of ML:

  1. Lowering barriers to entry.

  2. As a scripting language, it encourages and enables experimental workflow.

Best Description of AI

Posted on 21st of February 2023 | 64 words

Recently stumbled upon this great quote about the description of AI:

AI is magic.

  1. You see a magic trick. You are amazed by the magic.

  2. You are shown how the trick works. You are impressed by the technique.

  3. You learn how to perform the trick. Now it’s not magic, it’s sleight-of-hand, or mirrors, or misdirection.

– Unknown

Nice way of saying AI is bullshit.

Adding Lunar Phases to Emacs' Org Agenda

Posted on 19th of February 2023 | 911 words

As some of you may know, I’ve been a practising Buddhist for some time, focusing mainly on the teachings of Early Buddhism and Theravada. One aspect of this practice is keeping up with Uposatha, which is also present in other schools of Buddhism. Wikipedia describes Uposatha as follows :

The Uposatha (Sanskrit: Upavasatha) is a Buddhist day of observance, in existence from the Buddha’s time (600 BCE), and still being kept today by Buddhist practitioners. The Buddha taught that the Uposatha day is for “the cleansing of the defiled mind,” resulting in inner calm and joy. On this day, both lay and ordained members of the sangha intensify their practice, deepen their knowledge and express communal commitment through millennia-old acts of lay-monastic reciprocity. On these days, the lay followers make a conscious effort to keep the Five Precepts or (as the tradition suggests) the ten precepts. It is a day for practicing the Buddha’s teachings and meditation.

Uposatha days change from lunar month to lunar month, so there are no set days for those. But generally speaking, Uposatha is observed about once a week in accordance to the lunar phases. Which lunar phases are observed depends on the culture, but there are four phases to this: the new moon, the full moon and two quarter moons between those. Theravada cultures generally observe all four, but for example, in Sri Lanka, they tend to only observe the new and the full moon.

How these Uposatha days are calculated is quite interesting, and there is a paper published on GitHub by Gambhiro Bhikkhu about that.

Personally, I have followed these moon days by adding those to my Apple Calendar via the iCal link provided in the repository above, and I’ve been quite happy with that. Lately, though, I noticed that I tend to easily miss these days since I don’t often have notifications on or my calendar open when these days happen, which made me easily miss those. That got me thinking that it would be pretty cool to have those lunar phases on my emacs since that is most likely always open for me and I’m already mainly doing my time management in org-mode.

So I started digging around on how these could be easily added to my org-agenda, and then I found a built-in command from emacs that is at least the first step there called M-x lunar-phases, which basically prints lunar phases of the last, current and next month. So I started hacking around to try to get these to my Agenda view.

Not long after starting my hacking in this, I found a nice doc piece about some ad-hoc tweaks to be made to the agenda from org-mode, which actually made exactly what I wanted. What it involves is that I need to build an agenda file with these lunar phases so that the Agenda view in emacs picks those up.

So first, I needed to add some arbitrary file to my org-agenda-files. With use-package:

(use-package org
  :custom
  (org-agenda-files '(<your other agenda files> "/path/to/lunar.org")))

Or normally:

(setq org-agenda-files '(<your other agenda files> "/path/to/lunar.org"))

I happen to have all my agenda files in my Documents folder on my macOS, so they just get synced across my devices, but naturally, you can use any path you want.

The lunar.org file itself is pretty simple. Basically, we add a header to it with a single diary sexp calling a function, org-lunar-phases, which we soon define:

* Lunar phase
+CATEGORY: Lunar
%%(org-lunar-phases)

The org-lunar-phases itself either isn’t too complicated. It involves that we pass in the current day to it, which gets passed in in a relatively odd way via the diary sexp we used above, and after that we just parse the lunar-phase-list with the current day, or month and year in this case, since lunar-phase-list returns a list of lunar phases for the next three months.

(require 'cl-lib)

;; Pass current day to `org-lunar-phases', which is annoyingly in a stupid
:: format, (MM DD YYYY).
(with-no-warnings (defvar date))
(defun org-lunar-phases ()
  "Show lunar phase in Agenda buffer."
  (require 'lunar)
  (let* ((phase-list (lunar-phase-list (nth 0 date) (nth 2 date)))
         (phase (cl-find-if (lambda (phase) (equal (car phase) date))
                            phase-list))
         (lunar-phase-names '("● New Moon"
                              "☽ First Quarter Moon"
                              "○ Full Moon"
                              "☾ Last Quarter Moon")))
    (when phase
      ;; Return the phase to the agenda file.
      (setq ret (concat (lunar-phase-name (nth 2 phase)))))))

Naturally, you can get all fancy with those lunar-phase-names. Maybe adding emojis and whatnot if you’re into it. But in all simplicity, that is how you can add lunar phases to your agenda, and it shows as following in there:

10 days-agenda (W08-W09):
Monday     20 February 2023 W08
  Lunar:      ● New Moon
Tuesday    21 February 2023
Wednesday  22 February 2023
Thursday   23 February 2023
Friday     24 February 2023
Saturday   25 February 2023
Sunday     26 February 2023
Monday     27 February 2023 W09
  Lunar:      ☽ First Quarter Moon
Tuesday    28 February 2023
Wednesday   1 March 2023

One thing that I noticed from this was the fact the GitHub link above that I mentioned. That happens to produce a little bit different results for these phases. Every once in a while, some phases differ just a tiny bit. There is a mention that the calculation method used in that paper was related to how these days are calculated in Mahānikāya in Thailand, so there might be some variance compared to the M-x lunar-phases. But personally, I feel it’s close enough and quite beneficial to me.

Telemetry in Go

Posted on 15th of February 2023 | 614 words

Update: Go decided to go with opt-in telemetry, which at leastpersonally speaking I’m very happy with. [https://research.swtch.com/telemetry-opt-in](Read more about it from here.)

Last week, Russ Cox from Go team started a discussion about the possibility of starting to collect telemetry from Go usage .

How do software developers understand which parts of their software are being used and whether they are performing as expected? The modern answer is telemetry, which means software sending data to answer those questions back to a collection server.

I believe that open-source software projects need to explore new telemetry designs that help developers get the information they need to work efficiently and effectively, without collecting invasive traces of detailed user activity.

I have written a short series of blog posts about one such design, which I call transparent telemetry, because it collects as little as possible (kilobytes per year from each installation) and then publishes every bit that it collects, for public inspection and analysis.

I’d like to explore using transparent telemetry, or a system like it, in the Go toolchain, which I hope will help Go project developers and users alike. To be clear, I am only suggesting that the instrumentation be added to the Go command-line tools written and distributed by the Go team, such as the go command, the Go compiler, gopls, and govulncheck. I am not suggesting that instrumentation be added by the Go compiler to all Go programs in the world: that’s clearly inappropriate.

Cox also published three part introductory blog post about “transparent telemetry” that is worth a read:

So this whole discussion got me thinking about my feelings towards Go and, possibly, its future. First, I enjoy working with Go. As a language, it’s delightful to work with. It’s safe and fast, and I feel productive in it. But if the Go developers would introduce something like telemetry collecting your Go usage, I would have to re-evaluate the need/desire to use Go in current/new projects. There aren’t many developers that enjoy something like this in their toolchains. Or that would willingly allow something like that.

Sure, collecting telemetry in Visual Studio Code hasn’t affected too much in its popularity. But then again VSCodium is also quite popular, so clearly, some people hate this kind of telemetry, even in their favourite tool. Of course, I’m not yet even talking about the legality of collecting something like that. Because if something like this would be on by default, even if opt-out is offered, looking at GDPR, this can be considered illegal.

Of course, Go has had some “trust issues” for many due to it being language primarily developed, or at least funded, by Google. So naturally, people tend to have certain ideas and feelings about it even without touching it. Understandably so. Many people have already raised criticism in Go, for example, in their usage of Google run closed source Go module proxy mirror (proxy.golang.org), which is set on by default. This is also odd since Go’s import system was made to be decentralized from the get-go. Still, they decided to introduce something like this to increase reliability when importing libraries.

Considering all this, personally, I feel that if they were to introduce something like this to the Go toolchain, especially if it’s set on by default, it’d be a horrible thing for Go making the language to start fighting a big uphill battle, which may never end. I would still like to continue working in it, but if something like this were to happen, I feel that I couldn’t continue working in it if I had a choice.