Running staticcheck with eglot and gopls

Posted on 17th of March 2023 | 188 words

Another neat finding in Go’s language server. Basically, I wanted to include some sort of way to run some static analyser with my language server. I remember golanci-lint was long the “de facto” tool for this, but seems that staticcheck has grown a lot in popularity. So I wanted to integrate that with my gopls.

Naturally, the first step was installing the tool itself. Fortunately, that can be done super easily with just:

$ go install honnef.co/go/tools/cmd/staticcheck@latest

Next I needed to enable this somehow with gopls. Again fortunately, all the possible settings for gopls can be found here. Including the simple variable for staticcheck. To pass in this setting to eglot, I need to configure variable eglot-workspace-configuration, which basically allows you to configure LSP servers specifically for a given project and given LSP.

To pass in the setting to the gopls, we need to pass in a plist with the configurations we want:

(use-package eglot
  :custom
  (eglot-workspace-configuration '((:gopls . ((staticcheck . t))))))

;; OR

(setq-default eglot-workspace-configuration '((:gopls . ((staticcheck . t)))))

Naturally, you can pass any setting you desire that is available for the language server this way.

What I Read in February 2023

Posted on 6th of March 2023 | 597 words

Purely Functional Data Structures by Okasaki, Chris (reread)

I read this book when I was in my deep-deep functional programming phase couple of years back. Coming from imperative and OOP world, I already had a pretty good understanding of algorithms and data structures, but that knowledge was very much grounded in the imperative world. This book got recommended to me on how similarly useful data structures can be implemented in a purely functional way. I wanted to reread due to having some discussions with friends of mine about this same topic, so I wanted to refresh some memory about it.

Overall, I feel that it’s a very fun book to read and, compared to many other data structure books, it’s also quite fun to work with. It’s definitely niche on not so widely usable book compared to many other algorithm and data structure book, but definitely something that can give you a new view on certain problems.

The Buddha’s Teachings and Refuge by Thanissaro Bhikkhu

I have had long fascination towards Thai Forest Buddhism for many years now. Work of Thanissaro Bhikkhu was familiar to me in the form of his translations of numerous suttas. Quite recently I found out that he has also written many books on Buddha’s teaching, varying from fundamentals to interpreting Pali canon. So I wanted to wrap my head around those. Definitely recommend for anyone that cares about either Buddhist practice or just mindfulness in general.

All of his writing and talks are available at https://www.dhammatalks.org/index.html .

Insomniac City by Hayes, Bill

Every once in a while, I have some irregularities in my sleeping schedule. I got recommend this book due to its running theme of insomnia in it, so I during one of many of my sleepless nights, I decided to pick this up and start reading it. Book is about the authors, insomniacs himself, own life in New York and also the event what led to him moving there. Book covers many sleepless nights in New York City and how the author wanders around it finding stories. One of the main focal points in the book is also the author’s relation ship with the late Oliver Sacks . Very heartwarming story, definitely recommended.

Ten Arguments for Deleting Your Social Media Accounts Right Now by Lanier, Jaron and Digital Minimalism by Newport, Cal (both reread)

I decided to bundle both of these books here since they’re mainly about the same topic. Main reason on why I wanted to reread these was the recent events happening on Twitter. Despite I’m not part of any social medias (outside LinkedIn and that is also mainly due to requirements), I’m always quite interested on what’s happening around it. I thinks it’s mainly just hate towards those platforms so I just want to see them burn. Another big reason why I wanted to reread these was the fact that the popularity of Mastodon really started to get some traction. But I think this requires it’s own long form blog post about. So stay tuned on it.

No Longer Human by Dazai, Ozamu

For some reason, I’ve always had a weird fascination towards tragic human lives. Ozamu Dazai’s semi-autobiographical novel No Longer Human definitely tells the story of one. Very dark, grim and heavy book about mental illness and its effects on human nature. Don’t know if I can recommend this book for too many people. While it was very well written, the topics that it explores can be definitely be too much for many. But if you’re up to it, I think it’s worth a read

Generics-aware gopls in Emacs

Posted on 3rd of March 2023 | 473 words

I needed to write some funky Go code using relatively new Go generics in it, just to quickly notice that my LSP client in Emacs didn’t recognise those like you would expect. Fixing gopls was relatively straight-forward, since my issue seemed to be just an old version. So I just installed gopls while having Go 1.18+ installed. In my case, I had already generics-aware Go version installed but seemed like that I had installed my gopls version before the generics update, so I had to just reinstall it with:

$ go install golang.org/x/tools/gopls@latest

After that gopls was pleased, or at least my eglot didn’t complain about syntactical errors in my code. Pretty much immediately I realised that now my goimports was broken, so it didn’t organise my imports accordingly. I knew that gopls was able to do this stuff instead of using goimports, but I just never was eager to fix something that was already working. But since now it was broken, I decided to find a way to fix it.

What I did was just uninstall goimports from my machine and started relying on gopls for organising my imports. Previously, I had set my Emacs so that when I saved my files, it always ran goimports (when working on Go files, of course). Setting my eglot to do that was relatively simple, but then I noticed that it only formats my code, it doesn’t automatically import the libraries like how goimports does.

Like I mentioned earlier, gopls should be able to work exactly like goimports in this case, so I had to start digging on how I can make my eglot to do this. Basically, how gopls does this, is it uses source.organizeImports action for it. So I needed to run that somehow on save.

Fortunately, eglot exports all these code actions that the LSP can do with a neat function called eglot-code-actions. After some tinkering, I was able to call that before the save:

(use-package go-mode
  :ensure t
  :preface
  (defun tok/gofmt-before-save ()
    (interactive)
    (gofmt-before-save)
    ;; Run `eglot-code-actions' only in buffers where `eglot' is active.
    (when (functionp 'eglot-code-actions)
      (eglot-code-actions nil nil "source.organizeImports" t)))
  :hook (go-mode . (lambda ()
                     ;; Using depth -10 will put this before eglot's
                     ;; willSave notification so that the notification
                     ;; reports the actual contents that will be
                     ;; saved.
                     (add-hook 'before-save-hook 'tok/gofmt-before-save -10 t))))

I decided to use gofmt-before-save, which comes from go-mode here since I noticed that if you would just run eglot-format-buffer formatting doesn’t open a new buffer where it lists all the errors and instead prints them in the LSPs messages. You can probably dig them somehow from there and print in a new buffer, but I liked already the existing behaviour of running gofmt with go-mode so I decided to use that one.

Small fix, but a really good one. Happy generics-aware hacking.

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.