December 9, 2024
Emacs
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.
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
Emacs
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
Emacs
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:
- Still using god-mode. I am liking it.
- Using consult-notes but considering moving to org-roam.
- 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.
- 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
November 18, 2024
Crossroads
Different Path
It occurs to me that the usual content of the blog has changed significantly in the previous few months. I don’t write about the newest Markdown based text editor that has been released. I write about some macOS stuff. But mainly I write about Emacs.
I don’t see that changing much in the near future. I have moved on from Obsidian, VSCode and the others into Emacs. I have BBEdit and iA Writer installed. I use them for specific things. BBEdit is my comfort blanket. It is there to remind me that if I get overwhelmed by Emacs, there is a tool which I can use to solve my current problem. iA Writer is there to provide me with its syntax checker and easy syncing with my iPhone.
I am not interested in the newest addition to the plethora of text editors which deal with Markdown. I use Emacs for that. Completely immersed in Emacs, I don’t have the energy to check some new editor out. Thus the content of the blog is going to change to focus on what I am working on and using. Sorry if you miss the previous focus.
macosxguru at the gmail thingie.
Thanks to: Photo by Emiel Vansteenbrugge
macOS
writing
emacs
November 12, 2024
completely unnecessary cat picture
Links of Note 2024-11-11
macosxguru at the gmail thingie.
Note: Thanks to Photo by Tranmautritam
macOS
emacs
bbedit