Emacs APAC: Announcing Emacs Asia-Pacific (APAC) virtual meetup, Saturday, September 28, 2024

This month’s Emacs Asia-Pacific (APAC) virtual meetup is scheduled for Saturday, September 28, 2024 with BigBlueButton and #emacs on Libera Chat IRC. The timing will be 1400 to 1500 IST. The meetup might get extended by 30 minutes if there is any talk, this page will be updated accordingly. If you would like to give a demo or talk (maximum 20 minutes) on GNU Emacs or any variant, please contact bhavin192 on Libera Chat with your talk details:
-1:-- Announcing Emacs Asia-Pacific (APAC) virtual meetup, Saturday, September 28, 2024 (Post)--L0--C0--September 14, 2024 12:01 AM

Protesilaos Stavrou: Emacs: cursory version 1.1.0

Cursory provides a thin wrapper around built-in variables that affect the style of the Emacs cursor on graphical terminals. The intent is to allow the user to define preset configurations such as “block with slow blinking” or “bar with fast blinking” and set them on demand. The use-case for such presets is to adapt to evolving interface requirements and concomitant levels of expected comfort, such as in the difference between writing and reading.

Below are the release notes.


Version 1.1.0 on 2024-09-14

Cursory is in a stable state. This version includes quality-of-life refinements.

The cursory-mode simplifies how the state is stored

Cursory has functions to store and restore its state. In previous versions, we would document how to use those by adding them to the relevant hooks. This approach still works, though we now provide an easier way to achieve the same result: just enable the cursory-mode.

Technically, all this does is to set the hooks if enabled, and unsets them if disabled.

The “restore” phase is the same as before. For example:

;; Set last preset, if available, or fall back to the `bar' preset
;; from the `cursory-presets'.
(cursory-set-preset (or (cursory-restore-latest-preset) 'bar))

Use the cursory-set-preset-hook

The cursory-set-preset-hook is a normal hook (where functions are invoked without any arguments), which is called after the command cursory-set-preset. Here are some ideas on how to use it:

;; Imagine you have a preset where you want minimal cursor styles.
;; You call this `focus' and want when you switch to it to change the
;; cursor color.
(defun my-cursory-change-color ()
"Change to a subtle color when the `focus' Cursory preset is selected."
  (if (eq cursory-last-selected-preset 'focus)
      (set-face-background 'cursor "#999999")
    (face-spec-recalc 'cursor nil)))

;; Here we just show how to disable a given mode.  Of course, we can
;; have something more sophisticated, which stores the last value and
;; restores it if the condition we are testing for here is not met.
;; Keeping it simple for now.
(defun my-cursory-change-color-disable-line-numbers ()
  "Disable line numbers if the Cursory preset is `presentation' or `focus'."
  (when (memq cursory-last-selected-preset '(presentation focus))
    (display-line-numbers-mode -1)))

I am happy to include more examples here, if users have any questions.

Miscellaneous

  • Fixed a dependency for older Emacs versions. The subr-x, which is built into Emacs, needs to be explicitly loaded at compile time. This makes some parts of the code work as expected. Thanks to Mehdi Khawari for reporting the problem and Nicholas Vollmer for suggesting this change. The exchange took place in issue 1: https://github.com/protesilaos/cursory/issues/1. Users should already have this change, as I published a minor release for it (version 1.0.1).

  • Added some missing metadata to the manual. This is useful for the indices and COPYING section.

  • Updated the relevant links to the package sources. The main repository is now on GitHub.

-1:-- Emacs: cursory version 1.1.0 (Post)--L0--C0--September 14, 2024 12:00 AM

İsmail Efe: 5 Life Lessons

5 Life Lessons

İsmail Efe Top

2024-09-14

I’ve been reflecting on life for the past couple of months, and my world view has changed a lot. I feel like I have grown as a person, and I wanted to share the lessons I’ve learned during this time and throughout my life. Here are 5 life lessons from a 20-year-old.

Calling an ambulance

A lot of people my age tend to question if calling an ambulance is the right thing to when faced with health and emergency situations. I can understand the reasoning, as these kinds of situations are almost always in gray areas.

Here is a simple trick if you want to decide if you should call an ambulance; call 911.

If the situation escalates into you thinking you might need an ambulance, that's all the reason you need. Even if you think the situation might be minor and you think you might waste a first responders time, you should call. Because this is what first responders are for and you won't waste anyone's time.

911 operators are trained professionals and will know what to do.

In the worst-case scenario, where you call 911 and an ambulance isn’t necessary, they will connect you to a medical professional who can guide you on what to do next and also will advise you to call again if the situation worsens.

And, worst case scenario, if you don't call 911, is the situation escalating and someone dying.

"Fake it till you make it" is a powerful weapon

We humans tend to think the worst of situations. We feel like we are not good enough, feel like we don't have what it takes, and so on.

And we act accordingly to this. Whether in a work or a school setting, we find ourselves in situations where we don't want to speak up or step on anyone's toes.

We also feel like we are not good enough to achieve our dreams. Hell, sometimes we don't even dare to dream.

The best way to shake of this mindset is to fake your ideal mindset into existence.

In my opinion, while hard and sometimes cringe, it is the best way to deal with low self-confidence and self-worth.

Think of yourself as your ideal self, work hard, speak your mind on things, and dream big. Even if you are faking it and are well aware of the fact, with time, it will turn into reality.

Books, textbooks, and YouTube videos

Let's say that you want to learn about investing;

Introduction to investing books or textbooks are 10 times slower than watching a YouTube video.

But… they are 100 times more effective.

Let me explain, if you are not watching an actual university lecture. What you are watching is a fast-paced tutorial that tries to cram as much as possible into the shortest possible amount of time.

In these kinds of videos…

  • You are not able or encouraged to take notes because of it's fast-paced nature.
  • Rewinding is always a bother.
  • And because you are not taking the lesson at your own pace, your brain doesn't want to absorb it.

And don't get me started on how distracting it is to learn something in YouTube where entertainment is one click away and everything else is one tab away.

Yes, reading about something can be really slow. But because you are the one deciding the pace, your brain has an easier time absorbing the information.

If buying books are becoming too expensive or cumbersome, investing in a nice e-book reader might be a great idea.

The only person you can truly depend upon: You

Family and friends are one of the most important things in the world. You should love, cherish, and trust them. But you can't lean on them for all situations.

There will be times where you need or have to go through something on your own. These challenges tend to be hardest and being prepared is important.

Always work and invest in yourself. People can die, material things can perish. The only person you can depend on is you. Because if you are no more, then all is done.

I also think that life has a lot more meaning when you work on yourself regularly. When you eat healthy, read, exercise, or do anything that helps you become a better person. You feel like you are more in control and the things that cannot be changed becomes more bearable.

The only metric of success: happiness

Until this year, I thought that success would come in the form of money or fame. But it turns out I was extremely wrong.

Money doesn't mean anything if you are not happy. Fame doesn't mean anything if you are not happy. Career advancement doesn't mean anything if you are not happy.

Of course, you don't have to be happy constantly. But if you have all the things above and you don't feel any happiness, what is the point?

Everyone would choose being a happy person in a cheap car than be a sad person in a Porsche.

If material things bring you happiness go for it. If traveling brings you happiness travel. If being alone and doing your own thing brings you happiness do that. Also, you don't have to do these things right now. Even dreaming about these is a lot of fun.

In my opinion, having the people you love nearby, working on your goals and self, and having the insight to recognize what truly matters in life is the key to happiness and living a content life.

-1:-- 5 Life Lessons (Post İsmail Efe Top (ismailefetop@gmail.com))--L0--C0--September 13, 2024 09:00 PM

Irreal: Red Meat Friday: A Poetic Incursion Into The Editor Wars

Here’s a bit of Friday Red Meat for all you Emacs partisans in the eternal editor holy war.

Before you flame me, please keep in mind that I was a long time Vim user and often write approvingly of it. As I’ve often said, these days the editor wars are more about comic relief than a serious dispute. The real point of contention is not the editors themselves but the workflow that they engender.

Some people want a Lisp Machine, others want a small, fast, editor that’s good at editing and nothing more. The nice thing is that the Emacs/Vim duopoly lets you choose the environment most comfortable to you.

Anyway, enjoy the short diversion and get back to work. After all, we all have serious matters to deal with.

-1:-- Red Meat Friday: A Poetic Incursion Into The Editor Wars (Post jcs)--L0--C0--September 13, 2024 05:20 PM

Sacha Chua: Combining Mastodon timelines using mastodon.el

I like checking out the #emacs hashtag when I put together Emacs News. In the past, I usually browsed the hashtag timeline on emacs.ch, which also picked up updates from other people that emacs.ch was following. Now that I've moved to @sacha@social.sachachua.com and emacs.ch is winding down, I wanted to see if there was a way for me to see a combined view using mastodon.social's API feed (paging by max_id as needed). I haven't enabled public timeline feeds on my server, so I also need to reuse the OAuth mechanics from mastodon.el.

First, let's start by making a unified timeline. By digging around in mastodon-tl.el, I found that I could easily create a timeline view by passing it a vector of toot JSONs.

(defun my-mastodon-fetch-posts-after (base-url after-date)
  "Page backwards through BASE-URL using max_id for all the posts after AFTER-DATE."
  (require 'plz)
  (require 'mastodon-http)
  (let ((results [])
        (url base-url)
        (use-mastodon-el (not (string-match "^http" base-url)))
        page filtered)
    (while url
      (setq page (if use-mastodon-el
                     (mastodon-http--get-json (mastodon-http--api url) nil :silent)
                   (seq-map (lambda (o)
                              (cons (cons 'external t) o))
                            (plz 'get url :as #'json-read)))
            filtered (seq-filter (lambda (o) (string< after-date (assoc-default 'created_at o)))
                                 page))
      (if filtered
          (progn
            (setq results (seq-concatenate 'vector filtered results)
                  url (concat base-url (if (string-match "\\?" base-url) "&" "?")
                              "max_id=" (number-to-string (1- (string-to-number (assoc-default 'id (elt (last page) 0)))))))
            (message "%s %s" (assoc-default 'created_at (elt (last page) 0)) url))
        (setq url nil)))
    results))

(defun my-mastodon-combined-tag-timeline (later-than tag servers)
  "Display items after LATER-THAN about TAG from SERVERS and the current mastodon.el account."
  (interactive (list
                (org-read-date nil nil nil nil nil "-Mon")
                "#emacs"
                '("mastodon.social" "emacs.ch")))
  (require 'mastodon)
  (require 'mastodon-tl)
  (require 'mastodon-toot)
  (let* ((limit 40)
         (sources (cons (format "timelines/tag/emacs?count=%d" limit)
                        (mapcar (lambda (s)
                                  (format "https://%s/api/v1/timelines/tag/emacs?count=%d" s limit))
                                servers)))
         (combined
          (sort
           (seq-reduce (lambda (prev val)
                         (seq-union prev
                                    (my-mastodon-fetch-posts-after val later-than)
                                    (lambda (a b) (string= (assoc-default 'uri a)
                                                           (assoc-default 'uri b)))))
                       sources [])
           (lambda (a b)
             (string< (assoc-default 'created_at b)
                      (assoc-default 'created_at a))))))
    (with-current-buffer (get-buffer-create "*Combined*")
      (let ((inhibit-read-only t))
        (erase-buffer)
        (mastodon-tl--timeline combined)
        (mastodon-mode))
      (setq mastodon-tl--buffer-spec `(account ,(cons mastodon-active-user mastodon-instance-url) buffer-name ,(buffer-name)))
      (display-buffer (current-buffer)))))

The tricky thing is that boosting and replying in mastodon.el both use the toot IDs instead of the toot URLs, so they only work for toots that came in via my current mastodon.el account. Toots from other timelines might not have been fetched by my server yet. Adding an external property lets me find that in the item_json text property in the timeline buffer. For those toots, I can use (mastodon-url-lookup (mastodon-toot--toot-url)) to open the toot in a new buffer that does allow boosting or replying, which is probably enough for my purposes.

(defun my-mastodon-lookup-toot ()
  (interactive)
  (mastodon-url-lookup (mastodon-toot--toot-url)))

When I go through Emacs News, I have a shortcut ethat boosts a post and saves it to as an Org Mode capture with a link to the toot. I sometimes want to reply, too. So I just need to intervene before boosting and replying. Boosting and favoriting both use mastodon-toot--action, which looks up the base-item-id text property. Replying looks up the item-json property and gets the id from it.

(defun my-text-property-update-at-point (pos prop value)
  (let ((start (previous-single-property-change (or pos (point)) prop))
        (end (next-single-property-change (or pos (point)) prop)))
    (put-text-property (or start (point-min))
                       (or end (point-max))
                       prop value)))

(defun my-mastodon-update-external-item-id (&rest _)
  (when (mastodon-tl--field 'external (mastodon-tl--property 'item-json))
    ;; ask the server to resolve it
    (let* ((response (mastodon-http--get-json (format "%s/api/v2/search" mastodon-instance-url)
                                              `(("q" . ,(mastodon-toot--toot-url))
                                                ("resolve" . "t"))))
           (id (alist-get 'id (seq-first (assoc-default 'statuses response))))
           (inhibit-read-only t)
           (json (get-text-property (point) 'item-json)))
      (when (and id json)
        (my-text-property-update-at-point (point) 'base-item-id id)
        (my-text-property-update-at-point (point) 'item-json
                                          (progn
                                            (setf (alist-get 'id json) id)
                                            (setf (alist-get 'external json) nil)
                                            json))))))

So now all I need to do is make sure that this is called before the relevant mastodon.el functions if I'm looking at an external toot.

(with-eval-after-load 'mastodon-tl
  (advice-add #'mastodon-toot--action :before #'my-mastodon-update-external-item-id)
  (advice-add #'mastodon-toot--reply :before #'my-mastodon-update-external-item-id)
  (advice-add #'mastodon-tl--thread :before #'my-mastodon-update-external-item-id))

The only thing is that I need to press RET after loading a thread with T (mastodon-tl--thread) for some reason, but that's okay. Now I can boost and save posts with my usual Emacs News shortcut, and I can reply easily too.

I'm curious: how many toots would I be missing if I looked at only one instance's hashtag? Let's look at the #emacs hashtag toots on 2024-09-12:

Mastodon comparison
(defun my-three-way-comparison (seq1 seq2 seq3 &optional test-fn)
  `(("1" ,@(seq-difference seq1 (seq-union seq2 seq3 test-fn) test-fn))
    ("2" ,@(seq-difference seq2 (seq-union seq1 seq3 test-fn) test-fn))
    ("3" ,@(seq-difference seq3 (seq-union seq1 seq2 test-fn) test-fn))
    ("1&2" ,@(seq-difference (seq-intersection seq1 seq2 test-fn) seq3 test-fn))
    ("1&3" ,@(seq-difference (seq-intersection seq1 seq3 test-fn) seq2 test-fn))
    ("2&3" ,@(seq-difference (seq-intersection seq2 seq3 test-fn) seq1 test-fn))
    ("1&2&3" ,@(seq-intersection (seq-intersection seq2 seq3 test-fn) seq1 test-fn))))
(defun my-three-way-comparison-report (label1 seq1 label2 seq2 label3 seq3 &optional test-fn)
  (let ((list (my-three-way-comparison seq1 seq2 seq3)))
    `((,(format "%s only" label1) ,@(assoc-default "1" list #'string=))
      (,(format "%s only" label2) ,@(assoc-default "2" list #'string=))
      (,(format "%s only" label3) ,@(assoc-default "3" list #'string=))
      (,(format "%s & %s" label1 label2) ,@(assoc-default "1&2" list #'string=))
      (,(format "%s & %s" label1 label3) ,@(assoc-default "1&3" list #'string=))
      (,(format "%s & %s" label2 label3) ,@(assoc-default "2&3" list #'string=))
      ("all" ,@(assoc-default "1&2&3" list #'string=)))))

(assert (equal (my-three-way-comparison '("A" "A&B" "A&C" "A&B&C" "A1")
                                        '("B" "A&B" "A&B&C" "B&C")
                                        '("C" "A&C" "A&B&C" "B&C"))
               '(("1" "A" "A1")
                 ("2" "B")
                 ("3" "C")
                 ("1&2" "A&B")
                 ("1&3" "A&C")
                 ("2&3" "B&C")
                 ("1&2&3" "A&B&C"))))

(let* ((later-than "2024-09-12")
       (earlier-than "2024-09-13")
       (results
        (mapcar (lambda (o)
                  (cons (car o)
                        (seq-map (lambda (o) (assoc-default 'uri o))
                                 (seq-filter (lambda (toot)
                                               (string< (assoc-default 'created_at toot)
                                                        earlier-than))
                                             (my-mastodon-fetch-posts-after
                                              (format "%stimelines/tag/emacs?count=40" (cdr o))
                                              later-than)))))
                `((mastodon-social . "https://mastodon.social/api/v1/")
                  (emacs-ch . "https://emacs.ch/api/v1/")
                  (my-instance . ""))))
       (intersections
        (let-alist results
          (my-three-way-comparison-report
           "mastodon.social"
           .mastodon-social
           "emacs.ch"
           .emacs-ch
           "my instance"
           .my-instance
           #'string=))))
  (mapcar
   (lambda (row)
     (list (elt row 0) (length (cdr row))
           (string-join
            (seq-map-indexed (lambda (o i)
                               (org-link-make-string o (number-to-string (1+ i))))
                             (cdr row))
            " ")))
   intersections))
mastodon.social only 3 1 2 3
emacs.ch only 1 1
my instance only 0  
mastodon.social & emacs.ch 9 1 2 3 4 5 6 7 8 9
mastodon.social & my instance 0  
emacs.ch & my instance 1 1
all 11 1 2 3 4 5 6 7 8 9 10 11

Here's an Euler diagram visualizing it.

2024-09-13-12-45-10.png
Figure 1: #emacs posts on 2024-09-12 - an Euler diagram showing the table above

I love that I can tinker with mastodon.el to get it to combine the timelines. (I'm crossing the streams!) Yay Emacs!

-1:-- Combining Mastodon timelines using mastodon.el (Post Sacha Chua)--L0--C0--September 13, 2024 04:55 PM

Kisaragi Hiu: When is something executed? (mental model)

From code being written to code working in an app, there are a wide variety of places where code is run. This distinction needs to be kept in mind, especially for something like web metaframeworks, where you have code running on different contexts using the same language (so it's no longer as obvious). So I think it's a good idea to write it down. My mental model When making the thing: While editing I can use my editing commands, as well as on save, on commit…
-1:-- When is something executed? (mental model) (Post Kisaragi Hiu)--L0--C0--September 12, 2024 09:39 PM

Irreal: Emacs Pretest 30.0.91

Andrea Corallo has just announced that the first Emacs 30 pretest (30.0.91) is available for download and testing. You can check the NEWS file to see what’s new in the release.

As always, thanks to Eli, Andrea, and all the other devs who worked so hard to bring us this release and who keep Emacs a vital and thriving enterprise. The release of this pretest means that the release cycle for Emacs 30 is underway and we can expect the first release candidate sometime soon depending on how many errors are discovered in 30.0.91.

The developers depend on the Emacs community to help find those errors so if you can, please download and test the new version. It will help us all and move Emacs 30 closer to the official release.

-1:-- Emacs Pretest 30.0.91 (Post jcs)--L0--C0--September 12, 2024 04:02 PM

Sanel Zukan: evil-mode in terminal without Alt/Meta

This morning I found the following post on reddit /r/emacs: Evil mode on a vt100 and I recalled having the same issue with terminal Emacs in xterm. By default, xterm emulates VT102, and behaving like VT100, will not send Alt/Meta key to Emacs without this workaround.In short, the workaround to send M-x in evil-mode even if Alt/Meta doesn't work is to use this combo: \ Esc-x. \ will temporarily suspend evil-mode and Esc-x is the same as M-x. The same will work with C-u M-x: type \ C-u Esc-x.I wasn't satisfied with this, we are using Emacs, after all ;) How about we can call M-x directly as evil-mode ex command? Sure, run this:
-1:-- evil-mode in terminal without Alt/Meta (Post)--L0--C0--September 11, 2024 10:00 PM

Alvaro Ramirez: Spiffing up those echo messages

11 September 2024 Spiffing up those echo messages

Well-ingrained into every Emacs user is the echo area, a one-stop shop to receive any kind of message from the editor, located at the bottom of the frame. Posting messages to this area from elisp couldn't be simpler:

(message  "Hello world")

svg-hello-world.gif

If we want to get a little fancier, we can propertize the text to add some styling.

(message (propertize  "hello " 'face '(:foreground  "#C3E88D"))
         (propertize  "world" 'face '(:foreground  "#FF5370")))

svg-hello-world-colors.gif

With this in mind, I set out to add a tiny command to ready-player.

I wanted the ability to ask what's on without switching to another buffer. The echo area is perfect for that. It should display track title, artist, and album.

(message (concat  "Ahead "  ;;  title
                 (propertize  "Wire " 'face '(:foreground  "#C3E88D"))  ;;  artist
                 (propertize  "The Ideal Copy" 'face '(:foreground  "#FF5370"))))  ;;  album

svg-ready-player-colors.gif

This kinda work, but I wasn't convinced with the styling. Maybe I need multi-line?

(message (concat  "Ahead\n"  ;;  title
                 (propertize  "Wire\n" 'face '(:foreground  "#C3E88D"))  ;;  artist
                 (propertize  "The Ideal Copy" 'face '(:foreground  "#FF5370"))))  ;;  album

svg-ready-player-colors-multiline.gif

I felt something was missing. If I could just add the album artwork as a thumbnail… The ideal layout would maybe look something like:

+-------+
|       | Ahead
| image | Wire
|       | The Ideal Copy
+-------+

While the text-everywhere nature of Emacs buffers has many advantages, building more involved layouts can have its challenges. But hey, for that simple read-only message we're aiming at, we can certainly get creative without too much trouble. You see, Emacs has native svg support, so we can craft our fancy layout in elisp and tell Emacs to render it for us.

While I'm a noob at doing anything in svg from Emacs, adding an image and three labels, really isn't that difficult.

(message
 (let* ((image-width 90)
        (image-height 90)
        (text-height 25)
        (svg (svg-create (frame-pixel-width) image-height)))
   (svg-embed svg  "path/to/thumbnail.png"
               "image/png" nil
               :x 0  :y 0  :width image-width  :height image-height)
   (svg-text svg  "Ahead"
              :x (+ image-width 10)  :y text-height
              :fill (face-attribute 'default  :foreground))
   (svg-text svg  "Wire"
              :x (+ image-width 10)  :y (* 2 text-height)
              :fill  "#C3E88D")
   (svg-text svg  "The Ideal Copy"  :x (+ image-width 10)  :y (* 3 text-height)
              :fill  "#FF5370")
   (with-temp-buffer
     (svg-insert-image svg)
     (buffer-string))))

The code is fairly self-explanatory. While there may be an even simpler way (please lemme know), I used a temporary buffer to embed the svg in the propertized text prior to feeding to the handy message function.

…and with that, we get a richer display of the current track.

svg-ready-player-colors-image.gif

While I haven't experimented with other ways of creating multi-column layouts in Emacs (including images), I'd love to know if there's anything else available besides svg.

Enjoying these tips? Using one of my Emacs packages?

Help make them sustainable. Consider supporting this work.

-1:-- Spiffing up those echo messages (Post)--L0--C0--September 11, 2024 08:14 PM

Irreal: Casual Symbol Overlay

A couple of months ago, I wrote about Álvaro Ramírez’s gluing together of Symbol Overlay and Multiple Cursors. I was really taken with Symbol Overlay and its ability to select a given symbol for further actions. There are many possible operations and symbol-overlay lets you define your own commands for them. Of course, those commands are going to be hard to remember so it’s a perfect candidate for one of Charles Choi’s Casual apps.

Choi has, of course, stepped up to that challenge with Casual Symbol Overlay. As usual, it provides a Transient menu for those commands that you can invoke at will. You don’t, of course, have to use the menu. If you use a given command enough to remember it, you just use it but if you can’t remember the command, you can just invoke the menu and execute the command from there. It’s the best of both worlds.

At this point, I’ve just about decided to install Casual Suite so that I get all the Casual apps. You still have to configure them so they won’t be loaded unless you want them but Choi is making additions so often that it makes sense to reduce the friction of adding them. I don’t want them all but I do want a lot of them so it makes sense to add them all to my ELPA repository and configure the ones I actually want to be available.

-1:-- Casual Symbol Overlay (Post jcs)--L0--C0--September 11, 2024 04:08 PM

Protesilaos Stavrou: Emacs: show-font version 0.1.0

This is about the first version of show-font.el. I just pushed the changes to show-font.git and elpa.git, so expect the new package to be available in the coming hours. Below are some screen shots and the release notes for version 0.1.0.

Sources

Screen shots

Always click to enlarge the image for best results.

show-font.el with different fonts using a light theme

show-font.el with different fonts using a dark theme

show-font.el with different fonts in a list using a light theme

show-font.el with different fonts in a list using a dark theme

Version 0.1.0 on 2024-09-10

Version 0.1.0 on 2024-09-10

With show-font the user has the means to preview fonts inside of Emacs. This can be done in the following ways:

  • The command show-font-select-preview uses the minibuffer to prompt with completion for a font on the system. The selected font is then displayed in a bespoke buffer.

  • The command show-font-list produces a list with all the fonts available on the system. Each font on display is styled with its given character set.

  • The show-font-mode is a major mode that gets activated when the user visits a .ttf or .otf file. It will preview with the font, if it is installed on the system, else it will provide a helpful message and an option to install the font (NOTE 2024-09-10: this only works on Linux).

The previews include a pangram, which is controlled by the user option show-font-pangram. The default value is a playful take on the more familiar “the quick brown fox jumps over the lazy dog” phrase. Users can select among a few presets, or define their own custom string.

The function show-font-pangram-p is available for those who wish to experiment with writing their own pangrams (it is not actually limited to the Latin alphabet).

The user option show-font-character-sample provides a more complete character set that is intended for use in full buffer previews (i.e. not in the list of fonts). It can be set to any string. The default value is a set of alphanumeric characters that are commonly used in programming: a good monospaced font should render all of them unambiguously.

Finally, the following faces control the appearance of various elements.

  • show-font-small
  • show-font-regular
  • show-font-medium
  • show-font-large
  • show-font-title
  • show-font-title-small
  • show-font-misc
  • show-font-button
-1:-- Emacs: show-font version 0.1.0 (Post)--L0--C0--September 10, 2024 12:00 AM

Magnus: Followup on secrets in my work notes

I got the following question on my post on how I handle secrets in my work notes:

Sounds like a nice approach for other secrets but how about :dbconnection for Orgmode and sql-connection-alist?

I have to admit I'd never come across the variable sql-connection-alist before. I've never really used sql-mode for more than editing SQL queries and setting up code blocks for running them was one of the first things I used yasnippet for.

I did a little reading and unfortunately it looks like sql-connection-alist can only handle string values. However, there is a variable sql-password-search-wallet-function, with the default value of sql-auth-source-search-wallet, so using auth-source is already supported for the password itself.

There seems to be a lack of good tutorials for setting up sql-mode in a secure way – all articles I found place the password in clear-text in the config – filling that gap would be a nice way to contribute to the Emacs community. I'm sure it'd prompt me to re-evaluate incorporating sql-mode in my workflow.

-1:-- Followup on secrets in my work notes (Post)--L0--C0--September 09, 2024 08:36 PM

Irreal: Babel and Python

This is a sort of Public Service Announcement. One of the great things about Org mode is the code block where you can run code in an Org buffer and have the results inserted into the Org document. I use this all the time. It’s a particularly elegant way of practicing literate programming and writing “live” documents that automatically rewrite themselves when the data the changes.

It’s usually a seamless process but there are gotchas for some languages. Sadly, Python, a widely used language, is one of those where you have to be careful. If you don’t follow the rules correctly, you can end up with erroneous results.

Recently, on the Org Mode mailing list there was a nice discussion of the problems that Python can present. As of right now, there are only three posts in the thread so you should read them all to get a full idea of what’s going on. The TL;DR is that you (usually) have to provide an explicit return in your Python code to get the correct results into your Org buffer.

Python is the only language that I use—even occasionally—that has these problems: usually things just work. It is, therefore, worth spending a few minutes familiarizing yourself with the problems that Python and a few other languages have in the Babel environment.

-1:-- Babel and Python (Post jcs)--L0--C0--September 09, 2024 04:13 PM

Charles Choi: Announcing Casual Symbol Overlay

The excellent Symbol Overlay package for Emacs lets one highlight a programming language symbol (such as a variable or function/method) and perform operations on it. Common operations on a highlighted symbol include bulk renaming and navigating between different instances of said symbol. Out of the box, Symbol Overlay defines a keymap (symbol-overlay-map) where the user is intended to specify their preferred bindings to different symbol-overlay commands. This setup adds more friction than I’d like though, as a user is forced to define and remember these bindings to get at the nice features of Symbol Overlay.

For folks who like working with highlighted symbols but are less enamored with remembering more bindings, I’m happy to announce a new Transient user interface for Symbol Overlay: Casual Symbol Overlay, now available on MELPA.

A screenshot of this menu is shown below:

Note that keymap symbol-overlay-map will only be active over a highlighted symbol. To actually highlight a symbol, you'll need to define a binding for the command symbol-overlay-put. I leave it to the reader to determine which binding to use here but personally, I have that assigned to a pre-released Casual Transient menu which I intend to release soon. For readers who prefer a menu-driven workflow, consider the binding for symbol-overlay-put to be an interim solution until then.

If symbol-based operations are new to you, I encourage you to give them a try, especially if you code. They can be genuinely useful.

-1:-- Announcing Casual Symbol Overlay (Post Charles Choi)--L0--C0--September 09, 2024 04:00 PM

Sacha Chua: 2024-09-09 Emacs news

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Mastodon #emacs, Hacker News, lobste.rs, programming.dev, lemmy.world, lemmy.ml, communick.news, planet.emacslife.com, YouTube, the Emacs NEWS file, Emacs Calendar, and emacs-devel. Thanks to Andrés Ramírez for emacs-devel links. Do you have an Emacs-related link or announcement? Please e-mail me at sacha@sachachua.com. Thank you!

-1:-- 2024-09-09 Emacs news (Post Sacha Chua)--L0--C0--September 09, 2024 01:18 PM

Troy Hinckley: What is the best pointer tagging method?

In this post, we are going to take a deep dive into pointer tagging, where metadata is encoded into a word-sized pointer. Doing so allows us to keep a compact representation that can be passed around in machine registers. This is very common in implementing dynamic programming languages, but can really be used anywhere that additional runtime information is needed about a pointer. We will look at a handful of different ways these pointers can be encoded and see how the compiler can optimize them for different hardware.
-1:-- What is the best pointer tagging method? (Post)--L0--C0--September 09, 2024 12:00 AM

Irreal: Using .authinfo With Org Code Blocks

As most of you know, I’m a big fan of using literate programming techniques in the context of what might be described as “devops”. The technique boils down to writing an Org file with code blocks that document how you are solving a particular problem. The key is that the code blocks are executable and are what you actually use to solve the problem. Howard Abrams has a really good introduction to the idea in a post and subsequent video.

Magnus Therning has a nice nice post that expands on the same theme. His wrinkle is that the applications he’s interacting with require login credentials. For a long time, he simply kept those credentials as plain text in his Org file but, of course, he realized that was a bad thing.

He solved the problem by putting his credentials in his .authinfo file and accessing them with the auth-source library. He wrote a couple of functions that used the auth-source library to retrieve the necessary credentials. He populated these in a properties block. This is perfect because the source code doesn’t show any secrets but those secrets are made available to the executing code.

I do something similar to retrieve secrets that I don’t want exposed in plain text. The .authinfo file and associated library is a really useful set of tools to enable access to secure applications without exposing the required credentials. Take a look at his post to see how easy it is.

-1:-- Using .authinfo With Org Code Blocks (Post jcs)--L0--C0--September 08, 2024 03:45 PM

Alvaro Ramirez: Seek and you shall find

07 September 2024 Seek and you shall find

A couple of months ago, I introduced Ready Player Mode, an Emacs major mode used to peek at media files from my beloved text editor. The goal was simple. Treat opening media files like any other file, that is, open and go.

The initial implementation served me well while reviewing lots of tiny audio files I used to practice learning a new language. At this point, I started thinking, could I use ready-player for regular music consumption? The thing is, long ago I had stopped buying music and relied on streamed music from online services. Could I go back to offline?

Dusting off my old media collection brought lots of memories as I rediscovered tunes. Having said that, the ready-player experience wasn't quite cutting it for an extended listening experience. I no longer wanted to occasionally peek at media to learn a language. I wanted to load a full music collection. I wanted random access to everything. I wanted Emacs to remember what I was listening to across sessions… While I did add some pluggable flows, I still needed additional changes to make the experience more pleasant.

While plugging away at my own ready-player's pet peeves, I also collected a handful of feature requests. Let's go over the latest features.

Seek (f/b binding) - feature request

While not a feature I initially thought ranked highly in priority, I now find myself seeking audio files from time to time. Ready Player delegates all playback to the likes of mpv, vlc, mplayer, and so on… Up until now, interacting with these utilities merely consisted of feeding a media file path on to the respective process.

Command line utilities like mpv offer socket communication via --input-ipc-server to enable further requests like seeking forward and back. Ready player now supports seeking via mpv. Maybe support for other utilities can be added in the future.

If you're on a recent version of ready-player, seeking is automatically enabled if you've got mpv installed and aren't explicitly customizing ready-player-open-playback-commands. The default value takes care of things:

(defcustom  ready-player-open-playback-commands
  '(("mpv"  "--audio-display=no"  "--input-ipc-server=")
    ("vlc")
    ("ffplay")
    ("mplayer"))
   "..."
   :type '(repeat (list string))
   :group 'ready-player)

seek.webp

Pause/resume (SPC binding) - feature request

Until now, ready-player could only play and stop, so you always had to start playing tracks from the beginning. With mpv ipc support now in place, adding pause/resume was a breeze. Like seek, it should just work for ya if mpv is on your system and no explicit customization of ready-player-open-playback-commands.

Repeat current file (r binding) - feature request

While repeating current playlist (or directory) was already supported, there was a feature request to enable repeating files. Toggling repeat now cycles through available modes.

repeat.webp

Selective players - feature request

With ready-player delegating to a single utility for either audio or video playback, folks may have a need to specify different utilities for either of these two. While I'm happy for mpv to handle both audio and video now have a couple of prepending options.

Use a predicate function

Prepend each utility with either the built-in ready-player-is-audio-p or ready-player-is-video-p functions, or maybe create your own predicate helper.

(setq ready-player-open-playback-commands
      '((ready-player-is-audio-p  "ffplay")
        (ready-player-is-video-p  "mpv")))

Use an extension list

In this example, we delegate mp3 and ogg playback to ffplay and everything else to mpv.

(setq ready-player-open-playback-commands
      '((("mp3"  "ogg")  "ffplay")
        ("mpv")))

Autoplay (a binding) - feature request

Automatically start playing once file opens. No need for user to explicitly request playback.

Mark in dired (m binding) - feature request

Open a dired buffer and mark the currently played file.

mark.gif

M3u playlists - feature request

While I talked about how the dired abstraction made basic m3u playlist support possible, it wasn't until recently that I included this experiment in the package itself. In addition, .m3u are now recognized by Emacs and automatically open like any other file: find-file, dired, projectile…

Load recursive directory

With the dired abstraction at its core, ready player can load any dired buffer. You could do something like:

  1. M-x find-dired RET.
  2. Pick a directory. RET.
  3. Type "-iname \*.mp3 -o -iname \*.ogg -o -iname \*.m4a" RET.
  4. M-x ready-player-load-dired-buffer RET.

While uber flexible, there's no need to regularly do that, so you can now invoke M-x ready-player-load-directory and it will recursively find all media files in it.

Toggle player view (C-c m m binding)

While we can always get back to the player buffer via our favourite buffer-switching mechanism (I like ivy's ivy-switch-buffer), we now have M-x ready-player-view-player available for quicker toggle.

Remember session

Playback is now remembered across Emacs sessions. Toggling player view (C-c m m binding) or playback (C-c m SPC binding) starts the last song you were playing on your previous Emacs session.

Index + searching (/ or C-c m /)

We now have automatic indexing, which enables richer searching across your collection, not to mention that random access I was craving.

search.webp

Global bindings

Last but not least, you may have noticed a handful of key bindings throughout the post. Single-character bindings all work within a ready-player buffer. Bindings prefixed C-c m are now globally available when ready-player-mode is turned on. This can be customized via ready-player-set-global-bindings.

Please help make it all self-sustainable

If you find this package useful or got the features you wanted, please consider sponsoring the work. I've left my tech job (maybe a post for another time) and looking to make projects like ready-player self-sustainable.

If you're an iOS/macOS user, you can also buy my apps. Here's another freebie ( macosrec) I've put out there, which I regularly use to capture Emacs demos for this blog.

You may also enjoy this blog and all the tips I share. Blog posts take time. Consider sponsoring my blog.

I've built other Emacs packages you may already use or would like to. Maybe I already built a feature request? Consider sponsoring:

I'm also building lmno.lol, a new blogging platform, with drag and drop to the web. Maybe you want to try that too? Get in touch.

Thank you!

Álvaro

-1:-- Seek and you shall find (Post)--L0--C0--September 07, 2024 01:27 PM

James Dyer: New Package arscript-mode

As an avid ArtRage user for almost 10 years I have in the past delved into the subtle art of editing arscript files:

-1:-- New Package arscript-mode (Post)--L0--C0--September 07, 2024 07:55 AM

Protesilaos Stavrou: I talked with Gavin Freeborn about Emacs, philosophy, life, and politics

Raw link: https://www.youtube.com/watch?v=yHHlYB3zE3U

Gavin does videos about Emacs, Vim, and related technology issues. Follow the channel:

In this ~1-hour video I talk with Gavin about all sorts of interesting topics:

  • how I got into Emacs and what I do with it
  • the Vim paradigm and structural editing
  • programming and writing prose have different requirements
  • living in a city and then going to the mountains
  • how taking a step back can help you be in control
  • physical activity, hikes, and the like
  • what kind of philosophy I do
  • whether people should study philosophy
  • if I am drawn to the academic philosophical discourse and what I think about it
  • whether we should have an interest in politics
  • how I see politics and why I focus on common sense
  • if I could change society, what I would try to do
  • how we take freedoms for granted and why this can be a mistake
  • the idea of small communities organising their collective life

Thanks to Gavin for this interview! I had a good time and learnt new things in the process. I hope you will enjoy it as well.

-1:-- I talked with Gavin Freeborn about Emacs, philosophy, life, and politics (Post)--L0--C0--September 07, 2024 12:00 AM

Andrea: How to setup python-lsp-server with lsp-mode using pipx

-1:-- How to setup python-lsp-server with lsp-mode using pipx (Post)--L0--C0--September 07, 2024 12:00 AM

Andrea: Emacs as your code-compass: who is the person who refactored most in this project?

Emacs as your code-compass: who is the person who refactored most in this project?

It is a while I don't post about code-compass. I recently jumped back in the consulting world and it is a hectic life! In a couple of months I moved from a project to another. Furthermore, I cannot say I got somebody introducing me to the software architecture of these projects (or even their status).

Lucky me these years (from Ph.D. to industry times) have given me some experience, so my boat is well equipped for this wavy sea. Also I have a great tool: in both projects I just had to rely on my Emacs for a reliable code-compass.

So armed of hotspots, knowledge and communication graphs with a bit of churn, fragmentation and complexity on the side, I could get up and running faster than ever! Yay!!

One thing I have been missing is to explore graphically who dedicated themselves to the lovely art of refactoring. Indeed, the project on which I rely, the fantastic code-maat, offers a refactoring analysis. This finds who has deleted most lines in a file using Git commits information.

Naturally deletions are an approximation for refactoring, but good enough as less code is always an improvement (at least for our eyes).

Well there I go: I added it just now. It was pretty easy because is super-similar to the knowledge graph implementation. So a tweak here and there and it is now available.

Below a video that gives you a sense of what it is about.

/assets/blog/2022/11/23/emacs-as-your-code-compass-who-is-the-person-who-refactored-most-in-this-project/refactoringCodeCompass.mp4

If you want to try that yourself it is easy: just try out code-compass ;)

Happy refactoring!

-1:-- Emacs as your code-compass: who is the person who refactored most in this project? (Post)--L0--C0--September 07, 2024 12:00 AM

Irreal: 🥩 Red Meat Friday: Should You Replace Emacs With An “AI Editor”?

Over at the Emacs subreddit, harmanola, an Emacs user of 16 years, says that he’s recently switched from Emacs to Cursor, the AI code editor. It’s his opinion that Emacs has become unstable, that he’s tired of its “non-standard defaults”, that AI can increase his productivity by 5 times, that Emacs doesn’t scale, and that its developers aren’t on Discord. He also thinks that Emacs might be history soon.

One hardly knows where to begin. Well, I may not but the commenters certainly do. If there was ever a legitimate point to harmanola’s post, it got demolished by one or more of the commenters. To me, the silliest of his arguments is that one needs an “AI editor” to be productive. It seems to me that the AI suggestions are usually just slightly better than the code generated by previous editors that offered to write code for you: great for folks who are mostly generating boilerplate but used by virtually no one else.

The silliness about the Emacs developers not being on Discord strikes me as revealing a sense of entitlement: “I would like your help but I don’t want to go where you give it; please come over here instead.” If you spend 10 minutes on the Emacs mailing list you can’t help but be impressed by how much time guys like Eli Zaretskii spend—for free—on Emacs. As one of the commenters noted, all the things that comprise a healthy development environment—bug fixes, responding to pull requests, and regular updates—are, in fact, happening.

I’m sorry to see harmanola abandon Emacs and I hope he finds happiness elsewhere but his arguments for why we should leave Emacs for an AI editor just don’t withstand scrutiny.

-1:-- 🥩 Red Meat Friday: Should You Replace Emacs With An “AI Editor”? (Post jcs)--L0--C0--September 06, 2024 04:06 PM

Irreal: More On Upgrading Builtins

Last month, I wrote about Charles Choi’s post on the the on package-install-upgrade-built-in variable and how it controls the upgrading of builtin packages. The TL;DR is that when it’s set to t, package.el treats builtin packages as if they had been installed like any other 3rd party package for upgrading purposes.

My first inclination was to wonder why anyone would not want to have it set to t. I could imagine some outlying cases where it didn’t make sense but mostly I’d have expected that upgrading builtin packages was what most users wanted.

Apparently not. Over at the Emacs subreddit, jonas37 asks if people are setting package-install-upgrade-built-in and the comments are revealing. It’s hard to imagine the answer would be controversial but lots of people have strong feelings on the matter.

Take a look at the comments to see what I mean. The answer, as it usually is, is that “it depends”. In short, it’s hard to automate the decision. Sometimes you want to upgrade the builtins and sometimes you don’t.

It’s easy to take the position that your editor, whatever it is, should take care of things for you, but people who do take that position are the first to complain when the algorithmic decision is not to their liking. Sadly, sometimes we just need to engage with Emacs and tell it what we want it to do about upgrading our packages. For many cases. setting apackage-install-upgrade-built-in to t is probably the right decision but sometimes not. It, as they say, depends.

-1:-- More On Upgrading Builtins (Post jcs)--L0--C0--September 05, 2024 03:28 PM

Kisaragi Hiu: Redirecting from under a load balancing NGINX

Let's say I have a server program running locally on 127.0.0.1:8080; and I've already set up DNS such that example.com points to the IP of the server this program is running on. I can then set up Nginx like this as a reverse proxy, mapping the domain name to a program so that I can host multiple programs for multiple domains on the same machine. server { server_name example.com; location / { proxy_pass http://127.
-1:-- Redirecting from under a load balancing NGINX (Post Kisaragi Hiu)--L0--C0--September 04, 2024 05:54 PM

Irreal: Casual Agenda

Charles Choi is announcing another member of his casual suite: Casual Agenda. Like the other members of his suite, Casual Agenda provides a Transient driven menu that helps you navigate the arcane functionality of Org Agenda View.

I say “arcane” because although it’s easy to use Agenda View to simply list the content of the target files, there’s a lot more functionality hidden in obscure commands that even if you know they exist are hard to remember. Remembering the commands is even harder because Org makes them context sensitive.

Take a look at Choi’s post to see the menus and how they work with each other. It’s a nice system and probably worth installing even if you don’t use the commands often. Especially if you don’t use them often.

I know these command exist but I can never figure out how to access them so I’m really glad to see this latest addition to Choi’s suite. If you’re in the same situation, you should consider installing Casual Agenda.

You can, alternatively, simply install Casual Suite to get all the apps in the collection. This has the advantage that you automatically get additions to the suite when Choi adds them. All the apps have to be invoked explicitly so they never get in the way. If, like me, you follow Choi’s recommendation to bind them all to Ctrl+o, you need only remember a single command to bring up the appropriate menu when you need it.

As I’ve said before, I really like this set of applications and recommend you install the ones you need or possibly just install the entire suite.

-1:-- Casual Agenda (Post jcs)--L0--C0--September 04, 2024 04:09 PM

Alvaro Ramirez: Anki bookmarks

-1:-- Anki bookmarks (Post)--L0--C0--September 04, 2024 01:27 PM

Protesilaos Stavrou: Emacs: Denote version 3.1.0

Denote aims to be a simple-to-use, focused-in-scope, and effective note-taking and file-naming tool for Emacs.

Denote is based on the idea that files should follow a predictable and descriptive file-naming scheme. The file name must offer a clear indication of what the contents are about, without reference to any other metadata. Denote basically streamlines the creation of such files or file names while providing facilities to link between them (where those files are editable).

Denote’s file-naming scheme is not limited to “notes”. It can be used for all types of file, including those that are not editable in Emacs, such as videos. Naming files in a constistent way makes their filtering and retrieval considerably easier. Denote provides relevant facilities to rename files, regardless of file type.

Below are the release notes.


Version 3.1.0 on 2024-09-04

Denote is stable and reliable though we keep adding minor refinements to it. Remember that many—if not all—of these are intended for experienced users who have developed their own workflow and want to adapt Denote to its particularities. We may call them “power users”.

New users do not need to know about every single feature. A basic configuration is enough and is why the original video I did about Denote (from even before I published version 0.1.0) is still relevant. For example:

;; Start with something like this.
(use-package denote
  :ensure t
  :bind
  (("C-c n n" . denote)
   ("C-c n r" . denote-rename-file)
   ("C-c n i" . denote-link) ; "insert" mnemonic
   ("C-c n b" . denote-backlinks))
  :config
  (setq denote-directory (expand-file-name "~/Documents/notes/")))

And here is the same idea with a little bit more convenience:

;; Another basic setup with a little more to it.
(use-package denote
  :ensure t
  :hook (dired-mode . denote-dired-mode)
  :bind
  (("C-c n n" . denote)
   ("C-c n r" . denote-rename-file)
   ("C-c n l" . denote-link)
   ("C-c n b" . denote-backlinks))
  :config
  (setq denote-directory (expand-file-name "~/Documents/notes/"))

  ;; Automatically rename Denote buffers when opening them so that
  ;; instead of their long file name they have a literal "[D]"
  ;; followed by the file's title.  Read the doc string of
  ;; `denote-rename-buffer-format' for how to modify this.
  (denote-rename-buffer-mode 1))

The denote-sort-dired command is more configurable

The denote-sort-dired command asks for a literal string or regular expression and then produces a fully fledged Dired listing of matching files in the denote-directory. Combined with the efficient Denote file-naming scheme, this is a killer feature to collect your relevant files in a consolidated view and have the full power of Dired available.

By default denote-sort-dired prompts for the file name component to sort by and then asks whether to reverse the sorting or not. Users who want a more streamlined experience can configure the user option denote-sort-dired-extra-prompts.

It is possible to skip the prompts altogether and use the default values for (i) which component to sort by and (ii) whether to reverse the sort. To this end, users can have something like this in their configuration:

;; Do not issue any extra prompts.  Always sort by the `title' file
;; name component and never do a reverse sort.
(setq denote-sort-dired-extra-prompts nil)
(setq denote-sort-dired-default-sort-component 'title)
(setq denote-sort-dired-default-reverse-sort nil)

For me, Dired is one of the best things about Emacs and I like how it combines so nicely with Denote file names (this is the cornerstone of Denote, after all).

The denote-sort-dired sorting functions are customisable

Power users may want to control how the sorting works and what it is matching on a per file-name-component basis. The user options are these:

  • denote-sort-title-comparison-function.
  • denote-sort-keywords-comparison-function.
  • denote-sort-signature-comparison-function.

One use-case is to match specific patterns inside of file names, such as Luhmann-style signatures. I wrote about this in the manual as well as on my blog (with screenshots): https://protesilaos.com/codelog/2024-08-01-emacs-denote-luhmann-signature-sort/.

Thanks to Riccardo Giannitrapani for discussing this with me and helping me understand the use-case better. This was done via a private channel and I am sharing it with permission.

Show the date of each linked file in Org dynamic blocks

All our Org dynamic blocks that produce links to files now read the parameter :include-date. When it is set to t, the listed files will include their corresponding date inside of parentheses after the file’s title.

Thanks to Sergio Rey for describing this idea to me. This was done via a private channel and the information is shared with permission.

Exclude specific directories from Org dynamic blocks

The optional Org dynamic blocks we define let users collect links to other files (and more) in a quick and effective way. Each block accepts parameters which control its output, such as how to sort files.

All our dynamic blocks now accept the :excluded-dirs-regexp. This is a regular expression which is matched against directory file system paths. Matching directories and their files are not included in the data handled by the dynamic block.

Note that we have the user option denote-excluded-punctuation-regexp which defines a global preference along the same lines.

I did a video about this feature: https://protesilaos.com/codelog/2024-07-30-emacs-denote-exclude-dirs-org-blocks/.

Thanks to Claudio Migliorelli for discussing this idea with me. It was done via a private channel and this information is shared with permission.

New dynamic block to insert files as headings

We already had an Org dynamic block that would insert file contents. Though that one inserts files as they are, optionally without their front matter. However, users may have a workflow where they want to eventually copy some of the block’s output into the main file they are editing, at which point it is easier for the entire inserted file to appear as a series of headings. The #+title of the inserted file becomes a top-level heading and every other heading is pushed deeper one level.

To this end, we provide the Org dynamic block known as denote-files-as-headings. Insert it with the command denote-org-extras-dblock-insert-files-as-headings or select it with the minibuffer after calling Org’s own command org-dynamic-block-insert-dblock.

The top-level headings (those that were the #+title) can optionally link back to the original file. Though please read the manual for all the parameters this dynamic block takes.

The dynamic block for backlinks can be about the current heading only

The Org dynamic block for backlinks can now read the optional :this-heading-only parameter. When it is set to t, the block will only include links that point to the specific heading inside of the current file. Otherwise, backlinks are about the whole file.

To insert such a dynamic block, use the command denote-org-extras-dblock-insert-backlinks.

Toggle the detailed view in backlinks buffers

By default, the buffer produced by the command denote-backlinks has a compact view of showing the file names linking to the current file. With the user option denote-backlinks-show-context set to a non-nil value, the backlinks buffer produces a detailed listing of matching results, where the links are shown in their original context.

Users can now choose to have this on-demand by calling the command denote-backlinks-toggle-context which switches between the detailed and compact views.

This blog post I wrote about it include screenshots: https://protesilaos.com/codelog/2024-07-25-emacs-denote-backlinks-context-toggle/.

Templates can have a function that returns a string

The denote-templates variable allows the user to specify one or more named templates which can then be inserted during the creation of a new note. One way to be prompted for a template among those specified is to modify the denote-prompts user option and then use the regular denote command. Another way is to use the command denote-template (alias denote-create-note-with-template), which will prompt for the template to use.

Templates ordinarily have a string as their value, though now their value can also be the symbol of a function. This function takes no arguments and is expected to return a string. Denote takes care to insert that below the front matter of the new note.

So it can look like this:

(setq denote-templates
      `((report . "* Some heading\n\n* Another heading") ; A string with newline characters
        (blog . my-denote-template-function-for-blog) ; the symbol of a function that will return a string
        (memo . ,(concat "* Some heading" ; expand this `concat' into a string
                         "\n\n"
                         "* Another heading"
                         "\n\n"))))

Thanks to skissue (Ad) for the contribution in pull request 398: https://github.com/protesilaos/denote/pull/398. The change is small, meaning that its author does not need to assign copyright to the Free Software Foundation.

Also thanks to Jean-Philippe Gagné Guay for extending this to denote-org-capture. Done in pull request 399: https://github.com/protesilaos/denote/pull/399. Jean-Philippe is a long-time contributor who has assigned copyright to the Free Software Foundation.

The denote-rename-buffer-mode can now show if a file has backlinks

This global minor mode takes care to rename the buffers of Denote files to a pattern that is easier for users to read. As with everything, it is highly configurable. The default value now includes an indicator that shows if the current file has backlinks (other files linking to it).

The exact characters used in this indicator are specified in the new user option denote-rename-buffer-backlinks-indicator. The default value is "<-->", which hopefully communicates the idea of a link (but, yeah, symbolism is hard). Users may want to modify this to add some fancier Unicode character.

Thanks to Ashton Wiersdorf for the original contribution in pull request 392: https://github.com/protesilaos/denote/pull/392. Ashton has assigned copyright to the Free Software Foundation.

The denote-rename-buffer-format has changed

In the same theme as above, the user option denote-rename-buffer-format has a new default value. Before, it would only show the title of the file. Now it shows the aforementioned denote-rename-buffer-backlinks-indicator, if there are backlinks, plus the title, plus a literal "[D]" prefix. The prefix should make it easier to spot Denote files in a buffer listing.

Read the documentation of denote-rename-buffer-format for how to tweak this to your liking.

New user option denote-kill-buffers

This controls whether and when Denote should automatically kill any buffer it generates while creating a new note or renaming an existing file. The manual describes the details.

By default, Denote does not kill any buffers to give users the chance to review what is on display and confirm any changes or revert them accordingly.

Thanks to Jean-Philippe Gagné Guay for the contribution in pull request 426: https://github.com/protesilaos/denote/pull/426. This is related to issues 273 and 413, so also thanks to Vineet C. Kulkarni and mentalisttraceur for their participation and/or questions.

The denote-journal-extras-new-or-existing-entry handles any filename component order

Version 3.0.0 of Denote introduced a new option to rearrange the file name components. All Denote commands should respect it. We did, however, have a problem with the command denote-journal-extras-new-or-existing-entry which was not recognising the date properly.

Thanks to Jakub Szczerbowski for the contribution in pull request 395: https://github.com/protesilaos/denote/pull/395. The change is small, meaning that Jakub does not need to assign copyright to the Free Software Foundation.

While I am documenting this here, users should already have the fix as I published a minor release for it in July (in fact, there were 8 minor releases in the aftermath of the 3.0.0 release, which addressed several small issues).

The denote-rename-file-using-front-matter recognises the file-at-point in Dired

This makes it consistent with how denote-rename-file works. I am implemented this in response to issue 401 where Alp Eren Kose assumed it was the default behaviour: https://github.com/protesilaos/denote/issues/401.

I think it makes sense to have it this way to avoid such confusion. Still, it seems easier to edit the file and call denote-rename-file-using-front-matter directly, rather do an intermediate step through Dired.

The denote-rename-file-using-front-matter does not ask to rewrite front matter

The workflow for this command is that the user modifies the front matter, invokes the command, and Denote takes care to rename the file accordingly. We had a regression were this would happen as expected, but Denote would still prompt if it was okay to update the front matter. That made no sense.

As with the change mentioned above, this was also fixed in a minor release so that users would not have to wait all this time.

The denote-add-links and denote-find-link commands always works inside a silo

This was always the intended behaviour, though there was an issue with the implementation that prevented the directory-local value from being read.

Thanks to yetanotherfossman for reporting the problem with denote-add-links in issue 386 and to Kolmas for doing the same for denote-find-link:

Also thanks to Jean-Philippe Gagné Guay for following up with a change to the code that should address the underlying problem with temporary buffers. This was done in pull request 419: https://github.com/protesilaos/denote/pull/419.

Denote commands should work in more special Org buffers

A case we already handled was org-capture buffers. Another one is the buffer produced by the command org-tree-to-indirect-buffer.

Thanks to coherentstate for bringing this matter to my attention in issue 418: https://github.com/protesilaos/denote/issues/418.

Also thanks to skissue for noting another edge case that prevented denote-rename-buffer-mode from doing the right thing. This was reported in issue 393: https://github.com/protesilaos/denote/issues/393.

Denote will not create a CUSTOM_ID via org-capture if not necessary

If the org-capture template does not include one of the specifiers which produce a link, then we take care to not include a CUSTOM_ID in the properties of the current heading. We do this to make it possible to link directly to a heading inside of a file (a feature that is documented in the manual).

Before, we were creating the CUSTOM_ID unconditionally, which was not the desired behaviour. Thanks to Jonas Großekathöfer for bringing this matter to my attention in issue 404: https://github.com/protesilaos/denote/issues/404.

The prompt for selecting a silo has the appropriate metadata

All the Denote minibuffer prompts have the appropriate completion metadata to integrate with core Emacs functionalities and with third-party packages that leverage them. One such case pertains to the completion category our prompts report. This is used by a package such as embark to infer the set of relevant actions to perform or by the marginalia package to produce the appropriate annotations.

Users will now notice a difference while using commands such as denote-silo-extras-create-note if they have marginalia-mode enabled: all completion candidates will have file-related annotations.

This is a small change which goes to show how the little things contribute to a more refined experience.

New name for option that controls where backlinks buffers are displayed

The user option is now called denote-backlinks-display-buffer-action. The old name denote-link-backlinks-display-buffer-action is an alias for it and will thus work the same way. Though you are encouraged to rename it in your configuration as I will eventually remove those obsolete symbols from the Denote code base.

The revert-buffer should do the right thing in backlinks buffers

I made several tweaks to the underlying code to ensure that reverting a backlinks buffer will always reuse the original parameters that generated it. Backlinks buffers are produced by the denote-backlinks command, among others.

Lots of new entries in the manual with custom code

The manual of Denote is a rich resource of knowledge for how to use this package and how to extend it with custom code. I have written the following entries to further help you improve your productivity:

  • A custom denote-region that references the source
  • Custom sluggification to remove non-ASCII characters
  • Sort signatures that include Luhmann-style sequences
  • Why are some Org links opening outside Emacs?

More functions for developers or advanced users

The following functions are now public, meaning that they are safe to be used in the code of other packages or incorporated in user configurations:

  • denote-identifier-p.

  • denote-get-identifier-at-point. I am implementing this in response to a question by Alan Schmitt in issue 400: https://github.com/protesilaos/denote/issues/400.

  • denote-org-extras-outline-prompt.

  • denote-silo-extras-directory-prompt.

Consult their respective doc strings for the technicalities.

Note that the Elisp convention is that private functions (intended for use only inside the package) have a double dash (--) in their name. In principle, these are undocumented and can change at any moment without any notice. I do try to avoid such cases and even add warnings when I make changes to them. Still, you should not use private functions without understanding the risks involved.

Miscellaneous

New release cycle starts in mid-September

I have many ideas for how to further refine Denote. Maybe you do too. Though we must all wait a couple of weeks in case someone reports a bug. This way, it is easy to fix it and publish a new minor version. Otherwise, we may have to bundle the fix with some in-development feature that we have not fully tested yet.

Git commits

This is just an overview of the Git commits, though remember that there is more that goes into a project, such as the reporting of inconsistencies, discussion of new ideas, etc.. Thanks to everybody involved!

~/Git/Projects/denote $ git shortlog 3.0.0..3.1.0 --summary --numbered
   104	Protesilaos Stavrou
     7	Jean-Philippe Gagné Guay
     3	Ashton Wiersdorf
     1	Ad
     1	Jakub Szczerbowski
     1	bryanrinders
-1:-- Emacs: Denote version 3.1.0 (Post)--L0--C0--September 04, 2024 12:00 AM

Charles Choi: Announcing Casual Agenda

Use Org mode long enough and invariably you'll get around to using Agenda views to manage your defined tasks. Agenda views have become core to my Emacs experience and I'm certain that I'm not alone in saying this. As with other packages, there's a steep learning curve to using Agenda views, largely because Org adopts the Emacs convention of using keybindings and the mini-buffer prompt as its primary user interface with an added twist of frequently making this behavior conditional on where the point is.

To help ease using Agenda views, I'm happy to announce Casual Agenda, a Transient user interface for Org Agenda available on MELPA today.

Casual Agenda organizes the Agenda view commands into the following sections:

  • Agenda - Modify the view duration (day, week, month, year).
  • Filter - Filter displayed headlines with different criteria.
  • Actions - Perform an activity on a headline, create/capture a headline, or even generate a different agenda view.
  • Navigation - move the point to where you want it to be.
  • Utils - Set a timer, get almanac info.

Note that all the menus in Casual Agenda are contextual so as one navigates the Agenda view, the menu items will be enabled as appropriate.

Operating on Headlines

Use the Operations menu to alter attributes about it such as TODO state, scheduling, tags, and priority. To use it, move the point to the line of a heading you wish to change and from the main menu select “(o) Operations”. The following menu will be displayed.

Marking Headlines

User the Mark menu to mark different headlines and perform a bulk action on them. From the main menu, select “(m) Mark” to display the following menu:

Changing Modes and Settings

Agenda views have different display modes and behavior that can be modified from the Settings menu. From the main menu, select “(,) Settings” to display the following menu:

Almanac

Get sunrise/sunset times, lunar cycle dates, and holidays with respect to a date via the Almanac menu. From the main menu, select “(l) Almanac” to display the following menu.

Unicode Symbol Support

By enabling “(u) Use Unicode Symbols” from the Settings menu, Casual Agenda will use Unicode symbols as appropriate in its menus.

Installation Notes

Casual Agenda requires that you have a relatively recent version of Org (≥ 9.7.1) and Transient, both built-in packages to Emacs 29.1+. To update those packages you will need to take into consideration Emacs' default policy of not upgrading built-in packages unless configuring it to explicitly do so. My last blog post provides more detail on this.

Closing Thoughts

As with the other Casual Suite packages, Casual Agenda is intended to lower the cognitive load of using Agenda views. Even as I’ve already committed to memory many of these commands, it’s often that I mess up by issuing the wrong binding at the wrong place or just plain failing to recall a command. Since building and using Casual Agenda, this has happened less so. You might perhaps share the same experience.

-1:-- Announcing Casual Agenda (Post Charles Choi)--L0--C0--September 03, 2024 06:00 PM

Irreal: Show Font

The ever industrious Protesilaos Stavrou (Prot) just uploaded another nice package to MELPA. It’s a simple little app that displays a font in an Emacs buffer but for those who are on an eternal quest for the perfect font it’s perfect.

The app displays a (configurable) bit of text—think “The quick brown fox…”—and an (again configurable) set of characters underneath. Currently, the app works only with locally installed fonts but Prot is planning to upgrade it to be able to display and install any font.

Prot describes it as a work in progress but it’s already useful and will probably become more so as Prot refines it. It’s not a big thing but it’s another nice example of how Emacs is—or can be made to be—a complete editing environment.

-1:-- Show Font (Post jcs)--L0--C0--September 03, 2024 04:32 PM

Protesilaos Stavrou: Emacs: logos version 1.2.0

This package provides a simple approach to setting up a “focus mode”. It uses the page-delimiter (typically ^L) or the outline together with some commands to move between pages whether narrowing is in effect or not. It also provides some optional aesthetic tweaks which come into effect when the buffer-local logos-focus-mode is enabled. The manual shows how to extend the code to achieve the desired result.

(all my videos since early 2022 where I show parts of code use logos).

Below are the release notes.


Version 1.2.0 on 2024-09-03

This version introduces minor refinements to an already stable package.

The logos-update-fringe-in-buffers works with enable-theme-functions

It is possible to hide the fringes when logos-focus-mode is enabled by setting the user option logos-hide-fringe to a non-nil value. To make sure that the proper colours are applied when the theme changes, users must also set up the logos-update-fringe-in-buffers to run after the theme is loaded.

In versions of Emacs before 29 there was no standard way to do this (my themes (Modus, Ef, Standard) have always had the relevant “post load” hook). With Emacs 29, users can now use the enable-theme-functions to make this work with all themes:

(add-hook 'enable-theme-functions #'logos-update-fringe-in-buffers)

New logos-hide-header-line user option for logos-focus-mode

Users can now optionally hide the header-line when logos-focus-mode is enabled in the current buffer. This is done by setting logos-hide-header-line to a non-nil value and then enabling the mode.

[ Remember to read the manual for all such options. ]

Documented how to conditionally toggle org-indent-mode

The logos-focus-mode operates in the current buffer to make the changes that are needed for a more “focused” editing experience. Here we extend it to work with Org’s virtual indentation.

It disables org-indent-mode when logos-focus-mode is enabled and restores it when logos-focus-mode is disabled. The logos-set-mode-arg function takes care of the technicalities.

(defun my-logos-org-indent ()
  (when logos-focus-mode
    (logos-set-mode-arg 'org-indent-mode -1)))

(add-hook 'logos-focus-mode-hook #'my-logos-org-indent)

Documented how to toggle the menu-bar, tool-bar, tab-bar, and tab-line

Continuing from above, the following code block below shows how to disable the menu-bar-mode, tool-bar-mode, tab-bar-mode, and tab-line-mode when logos-focus-mode is enabled. If the given mode is already disabled, the corresponding function does nothing. Otherwise, it toggles the mode off/on when logos-focus-mode is enabled/disabled.

(defun my-logos-hide-menu-bar ()
  (when logos-focus-mode
    (logos-set-mode-arg 'menu-bar-mode -1)))

(add-hook 'logos-focus-mode-hook #'my-logos-hide-menu-bar)

;; Assuming the `tool-bar-mode' is enabled by default...
(defun my-logos-hide-tool-bar ()
  (when logos-focus-mode
    (logos-set-mode-arg 'tool-bar-mode -1)))

(add-hook 'logos-focus-mode-hook #'my-logos-hide-tool-bar)

;; Assuming the `tab-bar-mode' is enabled by default...
(defun my-logos-hide-tab-bar ()
  (when logos-focus-mode
    (logos-set-mode-arg 'tab-bar-mode -1)))

(add-hook 'logos-focus-mode-hook #'my-logos-hide-tab-bar)

;; Assuming the `tab-line-mode' is enabled by default...
(defun my-logos-hide-tab-line ()
  (when logos-focus-mode
    (logos-set-mode-arg 'tab-line-mode -1)))

(add-hook 'logos-focus-mode-hook #'my-logos-hide-tab-line)

Fixed a malformed cond

This was affecting the logos-narrow-dwim function in some cases. Thanks to Edgar Vincent for the contribution, which happened in the now-defunct mailing list.

-1:-- Emacs: logos version 1.2.0 (Post)--L0--C0--September 03, 2024 12:00 AM

Marcin Borkowski: Rounding all timestamps in an srt file

Preview: This is another time I’m going to revisit subtitling in Emacs. This time I’m going to fix yet another minor annoyance. The srt files contain timestamps with millisecond resolution, which doesn’t make sense at all – when I edit subtitles for a video with 50fps, I don’t really need such precision. Instead, it makes sense for every timestamp to be rounded to the nearest 20 millisecond. I decided to write a simple piece of Elisp to do the rounding for me.
-1:-- Rounding all timestamps in an srt file (Post)--L0--C0--September 02, 2024 07:02 PM

Sacha Chua: 2024-09-02 Emacs news

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Mastodon #emacs, Hacker News, lobste.rs, programming.dev, lemmy.world, lemmy.ml, communick.news, planet.emacslife.com, YouTube, the Emacs NEWS file, Emacs Calendar, and emacs-devel. Thanks to Andrés Ramírez for emacs-devel links. Do you have an Emacs-related link or announcement? Please e-mail me at sacha@sachachua.com. Thank you!

-1:-- 2024-09-02 Emacs news (Post Sacha Chua)--L0--C0--September 02, 2024 06:33 PM

Protesilaos Stavrou: Emacs: fontaine version 2.1.0

Fontaine allows the user to define detailed font configurations and set them on demand. For example, one can have a regular-editing preset and another for presentation-mode (these are arbitrary, user-defined symbols): the former uses small fonts which are optimised for writing, while the latter applies typefaces that are pleasant to read at comfortable point sizes.

Below are the release notes.


Version 2.1.0 on 2024-09-02

Fontaine is in a stable state and I find it very useful every day. This release includes some small quality-of-life improvements.

Use the fontaine-toggle-preset command

It will switch between the last preset and the one you are currently using. If it cannot find an older preset, it will prompt for one using minibuffer completion.

Presets are set with the fontaine-set-preset command, either interactively or from Lisp (e.g. in the init.el file).

Internally, fontaine-toggle-preset takes care to only switch between existing presets, so old preset names (such as from the time of some experiment) will be skipped if they are not part of the current value of fontaine-presets.

All entries in the fontaine-presets accept and optional width attribute

This is for users who need to set an explicit width value to the underlying face they are targeting. This, of course, depends on the capabilities of the font family that is used. Those that do not support varying widths will have no effect.

The width attribute for all existing entries is composed by the name of the face plus the -width suffix, such as :fixed-pitch-width. Check the Fontaine manual for a complete example.

Thanks to Adam Porter for making the suggestion to cover the width attribute in issue 6: https://github.com/protesilaos/fontaine/issues/6.

The fontaine-presets can look very long if all values are set, as we cover all typography-related faces and all their attributes. But do not let this intimidate you. Your configuration can be short and still highly usable. For example:

(setq fontaine-presets
      '((coding ; get the fallback values and override the `:default-height'
         :default-height 120)
        (reading  ; change more stuff from the fallback values
         :default-height 140
         :default-family "Fira Sans"
         :fixed-pitch-family "Fira Mono"
         :variable-pitch-family "Merriweather")
        (presentation
         :inherit reading ; copy the attributes of `reading', then override the `:default-height'
         :default-height 220)
        (t ; everything falls back to this
         :default-family "Iosevka Comfy"
         :default-height 100
         :fixed-pitch-family "Iosevka Comfy Motion"
         :variable-pitch-family "Iosevka Comfy Duo")))

With these, you can switch between coding, reading, and presentation to match your evolving workflow requirements.

These allow you to switch between not only different font families, but also font combinations to match a certain style, with higher or lower heights, and so on.

The fontaine-set-preset prompt only uses relevant default presets

When you invoke the command fontaine-set-preset it tries to find a previous preset to set it as the default minibuffer value. This means that if you press RET without selecting anything, the default will be used (check with your minibuffer package in case this does not happen, or contact me if you need help).

Before, the default value was the last selected preset. This could be out-of-date though if the fontaine-presets were rewritten in the meantime. Now we take care to only produce a default value that is among those specified in the fontaine-presets.

-1:-- Emacs: fontaine version 2.1.0 (Post)--L0--C0--September 02, 2024 12:00 AM

Srijan Choudhary: 2024-09-01-002

My small #emacs #orgmode #gtd customization of the day:

org-edna is a plugin that can be used to setup auto triggers (and blockers) when completing a task. org-gtd uses it to auto-forward the next TODO item in a project to NEXT when a task in the project is marked as DONE. The #orgedna trigger it uses is: relatives(forward-no-wrap todo-only 1 no-sort) todo!(NEXT).

This works okay for me, but also results in tickler tasks configured as repeated tasks to go to NEXT state instead of TODO state when they are completed. This results in them showing up in the org agenda even before they are due.

To fix this, I had to add this property to the top-level headings of the tickler file:

:PROPERTIES:
:TRIGGER: self todo!(TODO)
:END:

This overrides the global triggers configured by org-gtd for these org subtrees.

Syndicated to:

-1:-- 2024-09-01-002 (Post Srijan Choudhary)--L0--C0--September 01, 2024 09:45 PM

Irreal: The Emacs Writing Studio Is Finished and Available

I’ve written about Peter Prevos and his Emacs Writing Studio several times [1, 2, 3, 4 ]. It’s a series of articles on using Emacs for long form writing. Now, happily, Prevos has announced that the project—or at least the first version of it—is finished and available as a book from several e-bookstores. The source files are also available from his GitHub respository.

This is, as I’ve written, a great resource with lots of useful information. But don’t take my word for it. Protesilaos Stavrou also has a few words to say about it. He has, in fact, contributed those words as a forward to the book.

Those of you who have been around for a while know that I’m very interested in stories about people who use Emacs for non-technical purposes such as prose writing. Those who share that interest will find Prevos’ book a handy resource for using Emacs in their own projects.

I’ve read a lot of Prevos’ articles but never read them through as a book. I’m looking forward to reading the complete work.

-1:-- The Emacs Writing Studio Is Finished and Available (Post jcs)--L0--C0--September 01, 2024 03:10 PM

Magnus: Improving how I handle secrets in my work notes

At work I use org-mode to keep notes about useful ways to query our systems, mostly that involves using the built-in SQL support to access DBs and ob-http to send HTTP requests. In both cases I often need to provide credentials for the systems. I'm embarrassed to admit it, but for a long time I've taken the easy path and kept all credentials in clear text. Every time I've used one of those code blocks I've thought I really ought to find a better way of handling these secrets one of these days. Yesterday was that day.

I ended up with two functions that uses auth-source and its ~/.authinfo.gpg file.

(defun mes/auth-get-pwd (host)
  "Get the password for a host (authinfo.gpg)"
  (-> (auth-source-search :host host)
      car
      (plist-get :secret)
      funcall))

(defun mes/auth-get-key (host key)
  "Get a key's value for a host (authinfo.gpg)

Not usable for getting the password (:secret), use 'mes/auth-get-pwd'
for that."
  (-> (auth-source-search :host host)
      car
      (plist-get key)))

It turns out that the library can handle more keys than the documentation suggests so for DB entries I'm using a machine (:host) that's a bit shorter and easier to remember than the full AWS hostname. Then I keep the DB host and name in dbhost (:dbhost) and dbname (:dbname) respectively. That makes an entry look like this:

machine db.svc login user port port password pwd dbname dbname dbhost dbhost

If I use it in a property drawer it looks like this

:PROPERTIES:
:header-args:sql: :engine postgresql
:header-args:sql+: :dbhost (mes/auth-get-key "db.svc" :dbhost)
:header-args:sql+: :dbport (string-to-number (mes/auth-get-key "db.svc" :port))
:header-args:sql+: :dbuser (mes/auth-get-key "db.svc" :user)
:header-args:sql+: :dbpassword (mes/auth-get-pwd "db.svc")
:header-args:sql+: :database (mes/auth-get-key "db.svc" :dbname)
:END:
-1:-- Improving how I handle secrets in my work notes (Post)--L0--C0--September 01, 2024 01:03 PM

Irreal: Remote Emacs in Terminal Mode

There are some people who prefer to run Emacs in terminal mode. I have no problem with that but I do think that GUI Emacs has so much more to offer that it’s usually the best choice. Sometimes there’s no choice.

The need to use terminal mode often comes up when developers have to work on remote systems rather than their local machine. The usual advice is to use Tramp, which often works well and solves the problem but sometimes—especially with remote servers that are not on the local network—tramp can be too slow.

Wai Hon Law is in that situation. His employer does not allow source code on individual machines so he has do all his development on a remote server. Tramp didn’t work for him so he had to find another solution.

That solution involves a good terminal emulator and tmux. The two main problems are getting good colors for syntax highlighting and enabling the clipboard. These mostly depend on choosing the right terminal emulator but Law’s solution may not help too much because he’s using Chrome OS but there are doubtless terminal emulators suitable for your system.

The TL;DR is that you may have to experiment a bit to find the right emulator for your OS but once you do, you can look at Law’s post to get an idea of the other things you need.

I’m lucky that I’ve never been in this situation and could always just use Emacs in GUI mode but if you aren’t so lucky, take a look at Law’s post to see some possible ways forward.

-1:-- Remote Emacs in Terminal Mode (Post jcs)--L0--C0--August 31, 2024 04:15 PM

Protesilaos Stavrou: The Emacs Writing Studio is available—I wrote the foreword

[ I am not affiliated with this work. I just enjoy what Peter is doing and I am sharing it as a fellow Emacs user. ]

Peter Prevos has just published the book Emacs Writing Studio. It is a high quality resource for those who want to use Emacs to write at length (books, scientific papers, personal notes, …). EWS comes with an accompanying Emacs configuration to help users get started. Peter used this configuration to produce EWS!

Buy the book from one of the many available bookstores listed here: https://books2read.com/u/4NpgQ9. And check the source code on GitHub: https://github.com/pprevos/emacs-writing-studio.

Below is the foreword to EWS that I wrote.


With Emacs Writing Studio you have what you need to get started with writing. The book and the concomitant configuration for Emacs provide a solid foundation for you to organise your ideas, capture information, and elucidate your thoughts.

This book provides an overview of Emacs’ capabilities for writers. It does it in a way that is approachable. You get the essentials and are then guided through the various facets of the workflow.

Consider Emacs Writing Studio a companion on a long journey. It helps you get started with Emacs and will be there for you as a valuable reference when you need to do something a little bit more advanced but forgot how to proceed.

What you get at the outset is a curated experience. This is exactly what you need to get on with the task of writing: it minimises distractions. Though do not think of it as a constraint: you are still using Emacs — a powerful tool that can be reprogrammed or extended to do more with text and related patterns of interaction. The Emacs Writing Studio setup consists of sensible defaults. You will not be locked in to a bespoke system. This is the standard Emacs experience and you are free to modify it to your liking.

You can always find more resources to address whatever issue you may have. Beside the official manual of Emacs, you will discover a rich corpus of knowledge produced by the community. There are blog posts, drawings, and video demonstrations. They will all apply to what you have here.

No configuration can be a replacement for the work you put in. This is true for your time using Emacs but also for writing in general. Do not come with the expectation that Emacs Writing Studio will do miracles for you: it will not make you an Emacs expert overnight and it will not boost your creativity without you doing anything.

This is a tool that has been tested and proven to work well. Like every tool, it must be used properly by someone who has the requisite skills or is willing to acquire them through continuous practice. As a beginner, you will not know much: the book is here to ensure that you find the information you need to keep going.

The expectation you can have is that Emacs Writing Studio will deliver on its promise of giving you a set of tools for authoring your next works. It will do it in a reliable way. The rest is up to you: conduct the research and start creating.

Beside the technicalities, this book will make you think about matters of method. It does it indirectly through the functions it describes. You then have to consider how each of those will fit in to your workflow.

Piecing together a set of tools or procedures is part of the process of discovery that authors must go through. Through trial and error, you figure out what works for you. You may then stick with it and strongly prefer it over alternative approaches. Whether your methods are appropriate for others does not really matter: you know that one size does not fit all.

Emacs is the perfect tool for those who want to be particular with their writing. It is highly configurable and will grow with you as a user to always match your current level. If you do ever get the chance to learn some Emacs Lisp, you will realise that there is so much you can do to tweak every little thing exactly how you want it to be.

The key to learning your way around Emacs is to be patient and methodical. Try one thing at a time, learn how to use it, and then move on to the next one. This is why Emacs Writing Studio is helpful: it lets you experiment at your own pace while giving you something that works well out-of-the-box.

Remember that you are just getting started and you will be here long-term. Good luck!

-1:-- The Emacs Writing Studio is available—I wrote the foreword (Post)--L0--C0--August 31, 2024 12:00 AM

Ben Simon: gptel: Mindblowing integration between Emacs and ChatGPT

ChatGPT and its LLM brethren have been a potent source of FOMO: the AI revolution is happening, and I feel like I'm forever late to the party. After getting comfortable with OpenAI's web interface and coding my own command line tool, I figured it was time to complete the trilogy by integrating an LLM AI into Emacs.

As with many topics, there were a number of available Emacs packages, and it wasn't immediately obvious which was 'the best.' And then I watched this (to me) blandly named YouTube video: Every LLM in Emacs, with gptel and was hooked.

This 17 minute video blew my mind. If you're remotely interested in emacs and LLMs, stop reading this post and go watch this video. Heck, watch it a couple of times. In it, the gptel package developer goes through the why and how of gptel, and demonstrates some next-level uses of this package.

So gptel is my answer for adding them magic of ChatGPT to Emacs. gptel can be used both interactively and programmatically. I've found the former capability let's me have a running conversation with an 'assistant.' I can get answers to coding, writing or any other question on my mind without having to leave Emacs. Score.

But interactive use is just the beginning. By leveraging gptel-request, it's possible to automate common patterns. For example, I can set the region to include a word and run bs-gptel-define-word. In a few moments, ChatGPT will come back with a definition, examples, synonyms and antonyms. Here's the definition this function reports for FOMO:

In some respects, this is hardly exciting. There are a number of dictionary services are already integrated into Emacs, so why bother hand coding another? Yet, using gptel has two advantages. First, by changing the prompt, I can easily adjust the output. For example, here's the FOMO definition with a prompt that asks for active and passive voice examples:

The other benefit of using gptel for definitions is that the universe of what's considered a definable term is far larger. For example, I can ask for the 'definition' of a CSS property box-sizing: border-box.

Heck, it even handles slang. Here's the definition of slang: what the sigma

This would have been handy when we were traveling with our nieces and nephew, and this phrase came up repeatedly.

Another example of automating a task by leveraging gptel is gptel-proof. This is an early attempt at coding a proofreading tool within Emacs. The package works by taking an arbitrary region of text and asking ChatGPT to fix the spelling and grammar. The result is embedded back in the original document, surrounded by the familiar version control conflict markers. For example, here's what I see when I proofread this paragraph.

By using the conflict markers, I can use M-x vc-resolve-conflicts, to interactively compare and adopt the improved text.

What I like about this approach is that I don't need to blindly accept the LLM's changes. By using ediff, I'm combining both the magic of AI with the magic of emacs, to make, well, more magic. It's magical. A

This all feels like a very awkward start to using such a game-changing capability. But, at least I've started!

Here's some additional inspiration on the topic: Integrate Emacs with ChatGPT or any LLM, Powerful AI Prompts I have Known and Loved - that you can use, and Emacs pinky Saver: a voice driving GPT4 co-worker for emacs. together.ai is a platform for letting me interact with more LLMs than just ChatGPT.

-1:-- gptel: Mindblowing integration between Emacs and ChatGPT (Post Ben Simon (noreply@blogger.com))--L0--C0--August 30, 2024 09:03 PM

Please note that planet.emacslife.com aggregates blogs, and blog authors might mention or link to nonfree things. To add a feed to this page, please e-mail the RSS or ATOM feed URL to sacha@sachachua.com . Thank you!