December 28, 2024

KittyKitty

2024 Review

The Major Changes

Two major changes happened over 2024. The introduction of the ZSA Moonlander Next-gen Ergonomics zsa.io to the hardware stack, and the other was GNU Emacs - GNU Project.

ZSA Moonlander

I had been using the Planck from ZSA. It is a great keyboard but I wanted to try out a split keyboard and had been drooling over the Moonlander for a while. I acquired it in July.

Took me a few weeks to get comfortable in it. Having used the Planck for about two years, I am used to the ortholinear setup. The Moonlander has so many extra keys, that it took some getting used to. Of course, that process was also accompanied by a ton of tweaks to the keyboard. The Moonlander is completely programmable through Oryx The ZSA Keyboard Configurator.

Programmable means choices. I had to answer basic questions like:

  • Where do I put the space bar?
  • What about the modifier keys? Do I need a right ⌘ key? Or a right ⌃ key?

Choices which had to be tried out for a while before I could make an informed one. Took a while and it is still an ongoing process.

I love the keyboard. Just absolutely love it. It has made my pain in my fingers and wrists go away. I am usually on the keyboard for more than 14 hours a day. Yeah, I know, I need a life. This is the best investment I have made on my health in a long while. Feels fantastic.

Things which make this keyboard perfect:

  • No Shift key required. Auto-shift is a god-send. A little longer press on a key and it types the character with the shift key held down. The downside? I can’t use any other keyboard. Using the keyboard on the Air, I find myself holding on to a key expecting the Auto-shift behavior and nothing happens. Deeply frustrating.
  • The ability to get the extra keys to do the usual things which I do on a regular basis is a killer feature. One key for Alfred - Productivity App for macOS. One key for Keyboard Maestro 11.0.3 Work Faster with Macros for macOS.
  • The Hyper key and the Meh key.
  • For the Emacs user, multiple Esc keys, and a dedicated C-g key.

If you are interested in improving your input device, I would recommend the Moonlander with glowing praise.

This is an interesting article on Your first month with a ZSA Keyboard.

If you want to check out my configuration, here it is.

Emacs

If you follow my blog, you know this story. I am all-in on Emacs at this stage. I wish I had made this move earlier on in life. But I am making up. Took a deep-dive into it for it to stick.

I will tell you a story.

I had just posted the article Part Five of My Battles with Emacs - Bicycle For Your Mind when I got email from someone I did not know. He recommended the Consult-notes package and gave me a bit of code:

#+begin_src emacs-lisp
(defun lookup-word-at-point ()
  "Lookup word at point in OSX Dictionary"
  (interactive)
  (call-process-shell-command (format "open dict:///%s/" (word-at-point))))
#+end_src

Out of the blue, one of the OG’s of the Emacs world, Mr. Howard Melman sent me email. Encouraging me and giving me advice. How cool is that? I was floored. There are a whole bunch of people who are Emacs-gurus and they help unknown newbies get comfortable with Emacs. I am so thankful to these folks. They make the journey rewarding. Thank you Mr. Melman.

Thank you Mr. Protesilaos Stavrou.
Thank you Mr. Dave Wilson.
Thank you Mr. Mike Zamansky.
Thank you Ms. Sasha Chua.
Thank you Mr. Rainer Konig.

Thank you all for teaching me stuff.

This list can be a lot longer. In fact, I will make this a recurring part of the Much Ado About Emacs series. There are a lot of people to thank.

Anyway, I am enjoying my time in Emacs. Learning new things, trying out new things. Loving the act of writing. An unexpected by-product? Emacs makes me write more. The environment is created by me (with a lot of help from other folks). There is no friction. It is perfectly designed for me and my writing. I love it here.

The Others

These are the ones which get used everyday.

I have a ton of other software installed but they get sporadic use.

macOS is blessed with a vibrant eco-system of software and I am thankful to the developers. They make my life better.

macosxguru at the gmail thingie.

Thanks: to Photo by Ludvig Hedenborg: https://www.pexels.com/photo/close-up-of-hands-holding-cute-kitten-16191918/

macOS
December 27, 2024

EmacsEmacs

Much Ado About Emacs 005

Tangling and Packages

In the last edition I had posted about a problem that I was facing. In short, when I deleted a package from my init file, the package was not deleted from the elpa directory where Emacs stores packages. I found that annoying. Having used Doom Emacs, a long time ago, I seem to remember that I didn’t do much else but delete the reference to the package in package.el. That got rid of the package, or at least I think it did. In my plain vanilla-setup, that was not happening.

There are two steps to the solution: Firstly you have to remove the use-package command from init.el. Secondly, M-x and type the command package-delete, select the package that you don’t want to use anymore and delete it by hitting ↵ (return). One good thing about this list, packages are listed as obsolete, dependencies or installed.

This two step process works out fine.

Notes and Note-taking

My note-taking needs are simple. They are:

  • I want to create and find notes quickly.
  • I would like to link between notes.
  • Tagging would be nice.

I am not looking for a graphical representation of my notes and the links between them. I don’t care to adhere to some knowledge management schema and its rules. In other words, I don’t care about atomic notes, fleeting notes, PARA, zettlekasten and all the other associated madness.

I don’t need denote, org-roam or howm. They are all great solutions. Not for me. Basic org-mode is all I need to create and access my notes. There are two things I added:

  1. An automatic Unique ID for all newly created org-files. I will talk about this in the next section.
  2. I brought back consult-notes. It is a nice interface to search for notes and gives me a preview of the note when selected. I like that.

Unique ID

I wanted an unique ID added to any org file I created. With help from Claude, I got this code for the unique ID:

#+begin_src emacs-lisp
;; First ensure org-id is loaded
(require 'org-id)

;; Configure org-id to create IDs using timestamps by default
(setq org-id-method 'ts)

;; Function to automatically add ID to new org files
(defun my/org-add-file-id ()
  "Add an ID property to the file if it doesn't have one."
  (interactive)
  (when (and (eq major-mode 'org-mode)
             (not (org-id-get-create)))
    (org-id-get-create)
    (save-buffer)))

;; Add hook to run when creating new org files
(add-hook 'org-mode-hook #'my/org-add-file-id)

;; Optional: Also ensure IDs are created for all headings
(defun my/org-add-ids-to-all-headings ()
  "Add IDs to all headings in current file that don't have one."
  (interactive)
  (org-map-entries 'org-id-get-create))

;; Optional: Add this to org-mode-hook if you want IDs on all headings
;; (add-hook 'org-mode-hook #'my/org-add-ids-to-all-headings)
#+end_src

This works great for newly created org files. Doesn’t work well with the capture templates that I have set up.

#+begin_src emacs-lisp
            ("b" "Bookmark" entry
           (file+headline "~/Dropbox/org/bookmark.org" "Bookmark")
            ,(concat "* %^{Title}\n"
                      ":CAPTURED: %U\n"
                      ":END:\n\n"
                      "%a\n%i%?")
           :empty-lines-after 1)
#+end_src

The capture template bails with an error-message which points out that org-id-get-create expects a specified buffer. I am working on trying to fix that, in the meantime, org-id-create is a manual process.

Multiple Cursor

I had this installed for two weeks and never used it once. Deleted it.

Try Package

Included Try in the configuration. Seems like a good way of trying out packages without fully committing to them.

Move the Scroll in Emacs Without Moving the Position Cursor.

Added Move the scroll in Emacs without moving the position cursor. to the configuration.

#+begin_src emacs-lisp
  (use-package scroll-page-without-moving-point
    :straight (:host github :repo "tanrax/scroll-page-without-moving-point.el" :files ("scroll-page-without-moving-point.el"))
    :ensure t)
(global-set-key "\C-n" 'scroll-page-without-moving-point-down)
(global-set-key "\C-p" 'scroll-page-without-moving-point-up)
#+end_src

That is all I have for this week. You can see I am having fun.

macosxguru at the gmail thingie.

emacs
December 9, 2024

EmacsEmacs

Much Ado About Emacs 004

When I started building my Emacs configuration, I copied bits and pieces of code from a whole host of other people’s configurations. It made it possible for me to get started and be productive. I am grateful for the help I got from them. However, I ran out into some problems. One particular area of friction is keybindings. All of the individuals whose configuration I copied had their own logic behind the assignment of their keybindings. When you mix them together, the logic disappears and it all becomes a plethora of decisions which do not make sense. When it doesn’t make sense, it becomes more difficult to remember them. I needed to change that.

My Own Keymap

I came across, captainflasmr/Emacs-core: A stripped-down version of my primary Emacs configuration, it is designed to leverage only the default built-in features of Emacs. It is an attempt to replicate the features of packages in vanilla emacs through some clever code snippets. I learned a lot from it. It also taught me the benefit of designing my own keymap and making sense of what you assign to them. This is my first attempt at just that:

#+begin_src emacs-lisp
(defvar my-misc-keymap (make-sparse-keymap))
(global-set-key (kbd "M-o") my-misc-keymap)
    (define-key my-misc-keymap (kbd "+") #'tab-bar-new-tab)
    (define-key my-misc-keymap (kbd "-") #'tab-close)
    (define-key my-misc-keymap (kbd "b j") #'bookmark-jump)
    (define-key my-misc-keymap (kbd "b o") #'consult-bookmark)
    (define-key my-misc-keymap (kbd "b u") #'consult-buffer)
    (define-key my-misc-keymap (kbd "d") #'consult-dir)
    (define-key my-misc-keymap (kbd "g") #'consult-grep)
    (define-key my-misc-keymap (kbd "o h") #'consult-org-heading)
    (define-key my-misc-keymap (kbd "o a") #'consult-org-agenda)
    (define-key my-misc-keymap (kbd "o o") #'consult-outline)
    (define-key my-misc-keymap (kbd "r e") #'er/expand-region)
    (define-key my-misc-keymap (kbd "r c") #'er/contract-region)
    (define-key my-misc-keymap (kbd "r f") #'recentf-open-files)
    (define-key my-misc-keymap (kbd "r r") #'consult-register)
    (define-key my-misc-keymap (kbd "r s") #'consult-register-store)
    (define-key my-misc-keymap (kbd "/") #'my/comment-or-uncomment)
    (define-key my-misc-keymap (kbd "m l") #'my/mark-line)
    (define-key my-misc-keymap (kbd "m b") #'my/mark-block)
    (define-key my-misc-keymap (kbd "s") (lambda () (interactive) (switch-to-buffer "*scratch*")))
    (define-key my-misc-keymap (kbd "w") #'my/quick-window-jump)
#+end_src

Some functions which need to be explained.

Comment or Uncomment

This is from captainflasmr (CaptainFlasmr) and his Emacs-core repository.

#+begin_src emacs-lisp
(defun my/comment-or-uncomment ()
  "Comments or uncomments the current line or region."
  (interactive)
  (if (region-active-p)
      (comment-or-uncomment-region
       (region-beginning)(region-end))
    (comment-or-uncomment-region
     (line-beginning-position)(line-end-position))))
#+end_src

Mark Line

Again from captainflasmr (CaptainFlasmr) and his Emacs-core repository.

#+begin_src emacs-lisp
(defun my/mark-line ()
  "Mark whole line."
  (interactive)
  (beginning-of-line)
  (push-mark (point) nil t)
  (end-of-line))
#+end_src

Mark Block

Again from captainflasmr (CaptainFlasmr) and his Emacs-core repository.

#+begin_src emacs-lisp
(defun my/mark-block ()
  "Marking a block of text surrounded by a newline."
  (interactive)
  (when (not (region-active-p))
    (backward-char))
  (skip-chars-forward " \n\t")
  (re-search-backward "^[ \t]*\n" nil 1)
  (skip-chars-forward " \n\t")
  (when (not (region-active-p))
    (push-mark))
  (re-search-forward "^[ \t]*\n" nil 1)
  (skip-chars-backward " \n\t")
  (setq mark-active t))
#+end_src

ace-windows Replacement

I was using ace-windows to move between windows. This, again from captainflasmr (CaptainFlasmr) and his Emacs-core repository, is a replacement which works well.

#+begin_src emacs-lisp
(defun my/quick-window-jump ()
  "Jump to a window by typing its assigned character label.
Windows are labeled starting from the top-left window and proceed top to bottom left to right."
  (interactive)
  (let* ((window-list (my/get-windows))
         (window-keys (seq-take '("j" "k" "l" ";" "a" "s" "d" "f")
                                (length window-list)))
         (window-map (cl-pairlis window-keys window-list))
         (key (read-key (format "Select window [%s]: " (string-join window-keys ", ")))))
    (if-let ((selected-window (cdr (assoc (char-to-string key) window-map))))
        (select-window selected-window)
      (message "No window assigned to key: %c" key))))

(defun my/get-windows ()
  "Return a list of windows in the current frame, ordered from top to bottom, left to right."
  (sort (window-list nil 'no-mini)
        (lambda (w1 w2)
          (let ((edges1 (window-edges w1))
                (edges2 (window-edges w2)))
            (or (< (car edges1) (car edges2)) ; Compare top edges
                (and (= (car edges1) (car edges2)) ; If equal, compare left edges
                     (< (cadr edges1) (cadr edges2))))))))
#+end_src

Other Changes

  • I got rid of ace-windows.
  • Got rid of hydra and all the hydras I had designed. The two major ones were for dired and Markdown. Need to learn the keyboard commands and not rely on the hydras. Might create a general keymap for dired. Not sure about it yet.
  • Got rid of discover and makey from Mickey Petersen. Wasn’t supported by other packages and hence not useful.
  • Tried to install kickingvegascasual-suite Casual Suite - An umbrella package to support a single install point for all Casual user interfaces.. For some reason, it didn’t work at all and I did not bother to troubleshoot it. Might come back to it at some point, but it is not an urgent need.
  • Was curious about Emacs: Xah Fly Keys. Couldn’t get it to work and then read the documentation and decided not to go there. It will require a major change to the way I interact with Emacs and I am not sure I want to climb that mountain yet.

Pain-point

I have an org-file called Emacs.org which tangles to an init.el. I notice that if I take an installed package and set the elisp code to tangle: no, it disappears from the init.el. However the package still exists in my elpa directory and it is accessible to me through M-x. Doesn’t work, but it shows up in the command-list. Annoying. I have to delete the package from the elpa directory myself. Is this normal behavior or is my configuration missing something? Any help would be appreciated.

This is the code I am using for auto-tangling the org file on save. It is from the Emacs from Scratch series at System Crafters.

#+begin_src emacs-lisp
  ;; Automatically tangle our Emacs.org config file when we save it
  (defun efs/org-babel-tangle-config ()
    (when (string-equal (file-name-directory (buffer-file-name))
                        (expand-file-name user-emacs-directory))
      ;; Dynamic scoping to the rescue
      (let ((org-confirm-babel-evaluate nil))
        (org-babel-tangle))))

  (add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'efs/org-babel-tangle-config)))
#+end_src

That is all I have for today.

macosxguru at the gmail thingie.

emacs
December 4, 2024

EmacsEmacs

Much Ado about Emacs 003

I am enjoying living in Emacs. Getting to know it better.

These are some of the changes I have made since the last time I wrote about Emacs:

  • Moved from Consult-notes to Org-roam. Not sure that this move is permanent. I am trying out Org-roam to find out what it adds.
  • I am sticking to god-mode. I tried out evil The extensible vi layer for Emacs. The problem is that I am still learning Emacs and everything gets more complicated with the introduction of Vim keybindings. Better off sticking to vanilla Emacs. Learn how that works and then I might consider evil-mode.
  • Trying out hydra make Emacs bindings that stick around. Not sure that I like it all that much but I am overwhelmed with all the keyboard commands I am trying to learn. Hydra helps with that.
  • I use NewsBlur for my RSS feeds. But I am reading Emacs related news in Emacs through elfeed An Emacs web feeds client. I can feel Emacs slowly taking over all of my computer tasks. Which leads me to the next addition.

Atomic-Chrome

From Mike Zamansky Using Emacs 40 - atomic-chrome - YouTube. Installed the Chrome extension, Chrome Emacs, and the following package. I can use Emacs to fill in text frames in Chrome.

#+begin_src emacs-lisp
  (use-package atomic-chrome
    :demand t
    :straight (atomic-chrome
               :repo "KarimAziev/atomic-chrome"
               :type git
               :flavor nil
               :host github)
    :commands (atomic-chrome-start-server)
    :config (atomic-chrome-start-server)
    (setq-default atomic-chrome-buffer-open-style 'frame)
    (setq atomic-chrome-default-major-mode 'markdown-mode)
    (setq atomic-chrome-extension-type-list '(atomic-chrome))
  (setq-default atomic-chrome-auto-remove-file t))
#+end_src

Killing a word at point

This is from: Some Excerpts From My Emacs Config - 2: Functions - The Emacs Cat

#+begin_src emacs-lisp
(defun kill-whole-word ()
  "Kill the current word at point."
  (interactive)
  (backward-word)
  (kill-word 1))
(define-key global-map (kbd "<M-DEL>") #'kill-whole-word)
#+end_src

Nuke all buffers

This is useful sometimes. From: Some Excerpts From My Emacs Config - 2: Functions - The Emacs Cat

#+begin_src emacs-lisp
(defun nuke-all-buffers ()
  "Kill all buffers, leaving *scratch* only."
  (interactive)
  (mapc
   (lambda (buffer)
     (kill-buffer buffer))
   (buffer-list))
  (delete-other-windows))
#+end_src

Multiple-cursors

I am trying out multiple-cursors. magnars/multiple-cursors.el: Multiple cursors for emacs.

#+begin_src emacs-lisp
(use-package multiple-cursors)
    (global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
    (global-set-key (kbd "C-S-l C-S-l") 'mc/edit-beginnings-of-lines)
    (global-set-key (kbd "C->") 'mc/mark-next-like-this)
    (global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
    (global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
#+end_src

Make C-g a little more useful

Protesilaos is a fantastic resource for Emacs users. Emacs a basic and capable configuration Protesilaos Stavrou has some nice additions. This is one of them.

This is the explanation from Protesilaos:

“Do-What-I-Mean behaviour for a general keyboard-quit. The generic keyboard-quit does not do the expected thing when the minibuffer is open. Whereas we want it to close the minibuffer, even without explicitly focusing it. The DWIM behaviour of this command is as follows:

  • When the region is active, disable it.
  • When a minibuffer is open, but not focused, close the minibuffer.
  • When the Completions buffer is selected, close it.
  • In every other case use the regular keyboard-quit.”
#+begin_src emacs-lisp
(defun prot/keyboard-quit-dwim ()
  (interactive)
  (cond
   ((region-active-p)
    (keyboard-quit))
   ((derived-mode-p 'completion-list-mode)
    (delete-completion-window))
   ((> (minibuffer-depth) 0)
    (abort-recursive-edit))
   (t
    (keyboard-quit))))

(define-key global-map (kbd "C-g") #'prot/keyboard-quit-dwim)
#+end_src

Do not show warnings

I needed this. The warnings were scaring me. From Emacs a basic and capable configuration Protesilaos Stavrou.

#+begin_src emacs-lisp
(add-to-list 'display-buffer-alist
             '("\\`\\*\\(Warnings\\|Compile-Log\\)\\*\\'"
               (display-buffer-no-window)
               (allow-no-window . t)))
#+end_src

That is all I want to talk about today. See you next time.

macosxguru at the gmail thingie.

emacs
November 21, 2024

EmacsEmacs

Much Ado About Emacs 002

It is overwhelming, what you need to learn to be able to use Emacs well. The operative word here is “well.” I can use Emacs badly. In the sense, that what is taking me some effort to achieve might be possible to do quicker and more efficiently if only I knew how to improve the process.

I guess, the knowledge and understanding of Emacs will grow over time. The trick is to keep at it. It is overwhelming how much I don’t know about Emacs.

Focus on New Window

I am trying to move away from tabs and rely on windows to move between files. I think I will end up using a combination of the two. There are some files which I need to be open and easily accessible. For instance, the diary file and the todo file. These can be two tabs. The third tab can be where I open windows, switch to a buffer, work on it, and then delete the window when I am done.

I ran into a problem with windows. When you open a new window, the focus of the cursor stays on the original buffer. Doesn’t make sense to me, but that is the default behavior. I wanted the focus to shift to the window that I just created.

I got the solution from Terencio Agozzino.

#+begin_src emacs-lisp
  (use-package window
    :ensure nil
    :preface
    (defun hsplit-last-buffer ()
      "Focus to the last created horizontal window."
      (interactive)
      (split-window-horizontally)
      (other-window 1))
    (defun vsplit-last-buffer ()
      "Focus to the last created vertical window."
      (interactive)
      (split-window-vertically)
      (other-window 1)))
    (global-set-key (kbd "C-x C-1") #'delete-other-windows)
    (global-set-key (kbd "C-x C-2") #'vsplit-last-buffer)
    (global-set-key (kbd "C-x C-3") #'hsplit-last-buffer)
    (global-set-key (kbd "C-x C-0") #'delete-window)
#+end_src

Much better.

Balanced vs. Golden Ratio

My configuration included the following:

#+begin_src emacs-lisp
(use-package balanced-windows
  :config
  (balanced-windows-mode))
#+end_src

This meant that new windows were roughly the same size as the existing window. It was working fine but I found an alternative.

romangolden-ratio.el Automatic resizing of Emacs windows to the golden ratio made sure that the new window was the main focus and had a much bigger size than the original window. I like it. This is the code I am using for it.

#+begin_src emacs-lisp
(use-package golden-ratio)
(golden-ratio-mode 1)
#+end_src

Update: Jack Baty has a warning about the golden-ratio package. I have been using it for a couple of weeks with no problems, but you might want to be careful.

Showing Folders in a Dired Buffer on the Top

I wanted the dired buffer to show folders at the top of the listing. Protesilaos Stavrou’s configuration comes to the rescue.

#+begin_src emacs-lisp
(setq dired-listing-switches
        "-AGFhlv --group-directories-first --time-style=long-iso")
#+end_src

Scratch buffers in org-mode or markdown-mode

When I am working in my Emacs.org configuration file, I want a scratch buffer in org-mode to try out some things. I also want a markdown-mode buffer when I am writing in Markdown. This is the package which lets me do that.

emacs-weirdwarescratch Mode-specific scratch buffers - Codeberg.org

The relevant code:

#+begin_src emacs-lisp
  (use-package scratch)
  (global-set-key (kbd "C-c s") 'scratch)
#+end_src

Updates:

  1. Still using god-mode. I am liking it.
  2. Using consult-notes but considering moving to org-roam.
  3. Reading the org-mode manual. Org-mode is the main reason I switched to Emacs. Would be nice to be able to use this well.
  4. I have expressed the intention to stop tweaking Emacs and concentrate on using the features I know about. Not going to happen. Emacs is a wet-dream for anyone interesting in tinkering with their environment. I am, apparently one of them. The more I get exposed to different things about Emacs, the more I find myself incorporating those into my configuration and giving it a go. At this stage, it is endless tinkering.

macosxguru at the gmail thingie.

emacs