config.org 9.3 KB

#+TITLE:Doomed Chicken

Preface

This is another attempt at making a decent Emacs configuration for the chicken I am. Having multiple files with a poor consistence or a directed goal always bit me in the back relatively quickly. So this time, I'll try to write something documenting my process to warn my future me about my current configuration mishaps.

The first steps in the look&feel

The colors

Lately, I have been partial towards Gruvbox, for multiple reasons, the first being that I was tired of all those blue themes. It's a warm colorscheme, it has a good contrast in most of the situations and I built my whole's old laptop UI based on Gruvbox. Good thing Doom Emacs has a preset for this specific colorscheme.

(setq doom-theme 'doom-gruvbox)

The fonts

The other basic configuration I usually do first too is setting a font. PragmataPro has been my newest typographic friend as it's really good for what it's made for: displaying text in a flexible yet consistent way. I really like the small touches like the ligatures

(let ((base-size 12))
  (setq doom-font (font-spec
                   :family "PragmataPro Mono Liga"
                   :size base-size)
        doom-variable-pitch-font (font-spec
                                  :family "PragmataPro Liga"
                                  :size base-size)
        doom-unicode-font (font-spec
                           :family "PragmataPro Liga"
                           :size base-size)
        doom-big-font (font-spec
                       :family "PragmataPro Liga"
                       :size (* base-size 2))))

PragmataPro's ligatures have been toggled within init.el though the pretty-code layer and it's optional specialization for this font. No more setting is to be done for this font.

Tweaks

Window borders

Nothing really fancy yet, I'm content with how Doom looks right now. In the future I might add something to change the windows' border colors. Window dividers (located in the window-divider group) are inheriting from the vertical-border face, so editing the later allows me to quickly change the border color if needed.

;; (set-face-attribute 'vertical-border nil :foreground "red")

Blog writing

I have a blog. I want to use emacs as my platform to type bits and bobs on it.

Org mode is awesome, that's a fact. Minus the fact that I have to deal with a few weirds things around the UI, I love each instant I handle notes or todos with that mode. I tried to look into making org my blog framework/builder but I couldn't do the jump for many reasons, the most important ones were about having to do the templates for org, another one being having to convert Markdown blog posts. I switched to Hugo and extracted my blog files from the v3's database into markdown files.

Now I'll just enjoy the blog writing from a Hugo-powered blog git repo. The v4 is out for a few weeks now and I feel content with the workflow I'm having with it right now. But we can do better.

Draft jump list

Hugo has a few utilities, notably listing draft posts. I wrote a while ago a function to list drafts and feed them to helm. Doom Emacs seems to use ivy as file browser, so I had to rewrite one to feed Ivy with my draft list. Here's how it works. First we have a function that calls Hugo's draft listing based on the project's directory.

(defun chicken/list-hugo-drafts ()
  "Fetches the current drafts in a hugo project when available.
Assumes the current project is a Hugo one."
  (let
      ((root (projectile-project-root)))
    (counsel--split-string
     (counsel--call
      (list "hugo" "-s" root "list" "drafts")))))

Then I have an interactive function I can call that will process the list given by list-hugo-drafts and either opens the file or does nothing if the user cancels the search. Something to note here is how I have to rebuild the whole path based on the project's root. If the user was in another folder, which can happen for instance when opening another file, the action callback would have tried to open the selected file relatively to the current folder instead of the project folder. There is also a check to detect first the presence of a config file before attmepting to invoke hugo to give a sensible message.

;;;###autoload
(defun chicken/hugo-goto-draft ()
  "Opens an ivy-powered search helper to quickly jump on a draft
if the current project is the root of a Hugo-powered site."
  (interactive)
  (if (file-exists-p! "config.toml" (projectile-project-root))
      (ivy-read "Open a draft: " (chicken/list-hugo-drafts)
                :require-match t
                :history 'chicken/hugo-goto-history
                :action (lambda (file)
                          (with-ivy-window
                            (when file
                              (let*
                                  ((root (projectile-project-root))
                                   (full-file (concat root file)))
                                (find-file full-file)))))
                :unwind #'counsel-delete-process
                :caller 'chicken/hugo-goto-draft)
    (message "The current project doesn't have a config.toml in the root directory.")))

TODO Convert GIF to videos

I like GIFs, that's a fact. But neither your bandwidth nor your CPU will appreciate them. It's soon 2020 and GIFs are one of the most known ways to share a small video but it is one of the heaviest way one could do on the internet. Why keep continuing using it, except for pixel perfect (256) colors when most of the time a little encoding will lose little details but a lot of filesize?

I have a recipe to convert GIFs (and anything video related) into webm or mp4 with the help of FFMPEG, here it is.

# base
ffmpeg -i input-file.mp4 -c:v libvpx -crf 10 -b:v 1M -c:a libvorbis output-file.webm
# This worked not so bad on voxathrone gif
# ---
# auto-alt-ref is needed because the webm format will throw a tantrum due to
# transparency in the gif.
ffmpeg -i .\collision_benchmark.gif -c:v libvpx -crf 10 -auto-alt-ref 0 -b:v 1M -an .\collision_benchmark.webm

It might be nice to have some functions in emacs to convert a picture when working on a post. I'm still randomly trying to figure what I need, but here what I have for now:

  • Codec selection (vpx, mp4)
  • Sane quality presets
  • Customizable variables (crf quality for MP4, crf quality and video bandwidth for webm)
  • Detect when working on a post to automatically filter the compatible pictures

    • I'm usually working with an "images" folder. That could be a thing to detect.
    • I don't know how it works, but I could detect the `{{< video >}}` template so I can extract the link to the file and locate the file.
  • GPU codec selection?

Of course, an automatic script could help too, but I think this is kind of situation where I prefer handling myself the conversion as I might still need GIFs in some situations.

Unsorted Functions

Search Everything with Everything

Everything is a very useful tool for Windows that indexes all the available in the system and provides a insanely fast search popup to directly find the file you want based on either globbing or regexes. On Windows, I just can't live without it. It also provides a command line utility designed to search on a console but also works very well as part of a scripting toolbox.

Inspired by a friend's desire to use it on his own Emacs setup, I wrote a small function based on Ivy to let me jump on any file with the command line version. First, the function that will feed ivy-read. It assumes es.exe is in your PATH.

;;;###autoload
(defun chicken/counsel-es-function (str)
  (or
   (ivy-more-chars)
   (progn
     (counsel--async-command
      (format "es.exe %s" str))
     '("" "working..."))))

Then the search function. It is defined when the executable es.exe can be found in your PATH environment variable. The function is largely inspired by Ivy's own examples.

;;;###autoload
(when (and
       (executable-find "es.exe")
       (featurep! :completion ivy))
  (defun chicken/search-everything ()
    "Call the \"es\" shell command.
INITIAL-INPUT can be given as the initial minibuffer input."
    (interactive)
    (ivy-read "Everything: " #'chicken/counsel-es-function
              :dynamic-collection t
              :require-match t
              :history 'chicken/search-everything-history
              :action (lambda (file)
                        (with-ivy-window
                          (when file
                            (find-file file))))
              :unwind #'counsel-delete-process
              :caller 'chicken/search-everything )))

Finally, let's set up a shortcut to directly search a file globally with that tool. I'm going to map it on [LEADER]-s-E, as I hope it won't be used in the near future by Doom Emacs' default configuration. The mapping makes sure that you have the executable available by checking if the function to be called is available.

(map! (:when
        (functionp 'chicken/search-everything))
      :leader
      :desc "Everything" "sE" #'chicken/search-everything)