Irreal: Rolling Your Own Emacs Modal Mode

Lukas Lazarek has a very interesting post that details how he implemented his own evil-like mode for Emacs. Lazarek begins by describing the difference between Emacs and Vim. His distinction is much like mine: Vim wants to be a lightweight, fast editor and nothing else, while Emacs wants to be a text-based programming environment. I usually express that as Emacs being a lightweight Lisp machine but the meaning is pretty much the same.

Lazarek says the big advantage of Vim is its modal editing. I like modal editing but I see it as more something you’re used to rather than an actual advantage (unless we’re talking about RSI, which Lazarek does appear to be) but I don’t see it as an advantage. For me, the real advantage of Vim is not that it’s modal but that its command set is composable. I’ve written about this before.

Regardless, Lazarek wanted to implement a modal mode but didn’t want the exact Vim experience that Evil offers. It might seem like implementing your own Evil mode would be a significant undertaking but Lazarek demonstrates how simple it is by showing a short bit of Elisp that provides an “Evil mode” that merely implements the jklh cursor movement commands. It really is amazingly simple.

He also provides a link to his full implementation. It’s longer, of course, but still pretty simple and very easy to understand. That last clause is, I think, the main takeaway. It’s really easy to customize Emacs even in ways that seem complicated and outré. As always, Emacs lets you have it your way and often fairly easily.

-1:-- Rolling Your Own Emacs Modal Mode (Post jcs)--L0--C0--August 06, 2020 04:45 PM

Irreal: Zettelkasten Explained and Demoed

Continuing with yesterday’s theme about Zettelkastens, today I’d like to point you at two videos that explain and demonstrate the idea. The first, ZETTELKASTEN METHOD (Explained Clearly with Examples and Software), by Mike and Matty, two brothers who are physicians among other things, explains what a Zettelkasten is, why you might find it advantageous to use one, and how to use it effectively. They demonstrate the ideas with Roam and show how notes can be linked together to make exploring your ideas and notes on a topic easy. The video is just over 6 minutes long so it should be easy to find time for it if you’re interested.

The second video, A Tour of Org Roam, is by Ian Jones. He gives a quick tour of Org-roam and demonstrates the Zettelkasten idea in an Emacs setting. He demonstrates the backlink feature and how it’s useful for organizing and finding notes. The best part of his video, I think, is the segment on Org-roam-server that presents a graphical representation of your notes and how they’re linked. You can click on a node and Org-roam will take you to the corresponding note. It’s a powerful feature and a great part of Org-roam. Jones’ video is just under 5 minutes so it will be even easier to find time for.

If you’re not an Emacser but are interested in the Zettelkasten concept, the first video will explain things without mentioning Emacs. If you are an Emacser, you should watch the second video too. It shows you an excellent implementation that’s available for you in Emacs.

-1:-- Zettelkasten Explained and Demoed (Post jcs)--L0--C0--August 05, 2020 03:28 PM

Irreal: Zettelkasten Goes Mainstream

Until March of this year, I had never heard the term “Zettelkasten” or anything about the concept to which it applies. I first came across the idea in a post by Tiago Forte, which pointed me to Sönke Ahrens’ book, How to Take Smart Notes. I read the book and thought that it was a very powerful scheme that I could probably use in my workflow.

At the time, I felt like a pioneer. As far as I could tell, hardly anyone knew about the idea and virtually no one was writing about it. That’s all changed. Six months later, the idea is popping up everywhere and almost everyone concerned with personal information management is writing about it.

Over at Fast Company there’s an excellent article by Jack Beaudoin—Zapier on Zettelkastens and how to implement them. The article considers using existing applications, such as Evernote, OneNote, or Notion but concludes that these aren’t ideal solutions. In the first place, they fail to implement important Zettelkasten concepts such as atomicity and backlinks. Perhaps more importantly, they’re proprietary and offer no guarantees that they’ll be there for you tomorrow.

Another possibility is bespoke applications written specifically to implement the Zettelkasten idea. The premier example of this, of course, is Roam, which I’ve mentioned before. It’s a really excellent implementation of the Zettelkasten idea but, sadly, also suffers from its proprietary nature. The database is held on their servers so longevity is a real concern.

Finally, there are the solutions that use standard tools and the OS filesystem. These certainly speak to the proprietary and longevity issues but may not offer a good Zettelkasten implementation. They mention Obsidian but most of the ideas in this category aren’t really worthwhile. What they don’t mention, of course, are all the solutions available to Emacs users. That’s reasonable for media like Fast Company that aren’t addressed to geeks or the open source community. But if you are an Emacs user, you have your choice of the several solutions that have been discussed on Irreal recently. I continue to believe that Org-roam is the standout in this cohort but I still haven’t had a chance to experiment with it; I’m stuck struggling with mu4e.

-1:-- Zettelkasten Goes Mainstream (Post jcs)--L0--C0--August 04, 2020 01:42 PM

Sacha Chua: 2020-08-03 Emacs news

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Hacker News, planet.emacslife.com, YouTube, the Emacs NEWS file and emacs-devel.

-1:-- 2020-08-03 Emacs news (Post Sacha Chua)--L0--C0--August 04, 2020 02:25 AM

Irreal: A Short Tutorial on ERT

Abrochard has an excellent short tutorial on using ERT for running regression tests on your Elisp code. Most of us, of course, don’t write enough Elisp to worry about regression tests but if you want to contribute to Emacs or an Emacs related project, it’s worth spending a couple of minutes learning about ERT.

It’s really easy to specify a test. In the simplest case you simply make one or more statements of the form

(should (equal <expected value> (<tested-function> <function-parameters>)))

and call ERT.

ERT can handle more complicated cases, including those that don’t return a value. Abrochard has a nice example of how to mock up a test when a function doesn’t return a value. Take a look at his post to see the particulars. There’s even more information in the ERT manual so take a look at that too. It’s really easy to use and there’s no reason not to take advantage of it.

-1:-- A Short Tutorial on ERT (Post jcs)--L0--C0--August 03, 2020 02:43 PM

tycho garen: Running Emacs

OK, this is a weird post, but after reading a post about running emacs with systemd, [1] I've realized that the my take on how I run and manage processes is a bit unique, and worth enumerating and describing. The short version is that I regularly run multiple instances of emacs, under systemd, in daemon mode, and it's pretty swell. Here's the rundown:

  • On Linux systems, I use a build of emacs with the lucid toolkit, rather than GTK, because of this bug with GTK, which I should write more about at some point. Basically, if the X session crashes with GTK emacs, even if you don't have windows open, the daemon will crash, even if the dameon isn't started from a GUI session. The lucid toolkit doesn't have this problem.

  • I run the process under my user's systemd instance, rather than under the PID 1 systemd instance. I like keeping things separate. Run the following command to ensure that your user's systemd will start at boot rather than at login:

    sudo loginctl enable-ligner $(whoami)
    
  • I have a systemd service file named emacs@.service in my ~/.config/systemd/user/ directory that looks like this:

    [Unit]
    Description=Emacs-tychoish: the extensible, self-documenting text editor.
    
    [Service]
    Type=forking
    ExecStart=/usr/bin/emacs --daemon=%i --chdir %h
    ExecStop=/usr/bin/emacsclient --server-file=hud --eval "(progn (setq kill-emacs-hook 'nil) (kill-emacs))"
    Restart=always
    TimeoutStartSec=0
    
    [Install]
    WantedBy=default.target
    

    I then start emacs dameons:

    systemctl --user start emacs@work
    systemctl --user start emacs@personal
    systemctl --user start emacs@chat
    

    To enable them so that they start following boot:

      systemctl --user enable emacs@work
      systemctl --user enable emacs@personal
      systemctl --user enable emacs@chat
    
    Though to be honest, I use different names for daemons.
    
  • I have some amount of daemon specific code, which might be useful:

    (setq server-use-tcp t)
    
    (if (equal (daemonp) nil)
        (setq tychoish-emacs-identifier "solo")
      (setq tychoish-emacs-identifier (daemonp)))
    
    ;; this makes erc configs work less nosily. There's probably no harm in
    ;; turning down the logging
    (if (equal (daemonp) "chat")
        (setq gnutls-log-level 0)
      (setq gnutls-log-level 1))
    
    (let ((csname (if (eq (daemonp) nil)
                 "generic"
                 (daemonp))))
      (setq recentf-save-file (concat user-emacs-directory system-name "-" csname "-recentf"))
      (setq session-save-file (concat user-emacs-directory system-name "-" csname "-session"))
      (setq bookmark-default-file (concat user-emacs-directory system-name "-" csname "-bookmarks"))
      (setq helm-c-adaptive-history-file (concat user-emacs-directory system-name "-" csname "--helm-c-adaptive-history"))
      (setq desktop-base-file-name (concat system-name "-" csname "-desktop-file"))
      (setq desktop-base-lock-name (concat system-name "-" csname "-desktop-lock")))
    

    Basically this just sets up some session-specific information to be saved to different files, to avoid colliding per-instance.

  • Additionally, I use the tychoish-emacs-identifier from above to provide some contextual information as to what emacs daemon/window I'm currently in:

    (setq frame-title-format '(:eval (concat tychoish-emacs-identifier ":" (buffer-name))))
    
    (spaceline-emacs-theme 'daemon 'word-count)
    (spaceline-define-segment daemon tychoish-emacs-identifier)
    

    Also, on the topic of configuration, I do have a switch statement that loads different mu4e configurations in different daemons.

  • To start emacs sessions, I use operations in the following forms:

    # create a new emacs frame. Filename optional.
    emacsclient --server-file=<name> --create-frame --no-wait <filename>
    
    # open a file in an existing (last-focus) frame/window. Filename required.
    emacsclient --server-file=<name> --no-wait <filename>
    
    # open a terminal emacs mode. Filename optional .
    emacsclient --server-file=<name> --tty --no-wait <filename>
    

    That's a lot to type, so I use aliases in my shell profile:

    alias e='emacsclient --server-file=personal --no-wait'
    alias ew='emacsclient --server-file=personal --create-frame --no-wait'
    alias et='emacsclient --server-file=personal --tty'
    

    I create a set of aliases for each daemon prefixing e/ew/et with the first letter of the daemon name.

And that's about it. When I've used OS X, I've managed something similar using launchd but the configuration files are a bit less elegant. On OS X, I tend to install emacs with cocoa toolkit, using homebrew.

Using multiple daemons is cool, though not required, for a number of reasons:

  • you can have good separation between personal things and professional/work things, which is always nice, but particularly gratifying during the pandemic when it's easy to work forever.
  • Managing multiple separation of email. While mu4e has profiles and contexts, and that's great, I like a firmer boundary, and being able maintain separate email databases.
  • Running emacs lisp applications that do a lot of networking, or do other blocking operations. The main case where this matters in my experience is running big erc instance, or something else that isn't easily broken into async/subprocesses.
[1]And commenting!
-1:-- Running Emacs (Post)--L0--C0--August 03, 2020 12:00 AM

Irreal: Troubleshooting Mu4e

After I upgraded to macOS Catalina—or perhaps after I replaced my laptop because of the spilled drink catastrophe—I’ve been having problems with mu/mu4e. That’s serious for me because they are my primary email client. There are two problems.

First, mds and its helper apps were running not quite continually but regularly. Mds is the indexer for Spotlight, the macOS utility that provides system wide content searches. Mds uses a significant amount of CPU time when it’s running. So much so that the laptop gets significantly hotter. My hypothesis is that mds was getting kicked off every time mu ran mbsync to sync with the IMAP server—every 5 minutes on my machine. After it finishes running, there was a fairly short period until it got kicked off again.

I fixed that problem by telling Spotlight not to bother indexing my mail repository or the Xapian index that mu maintains. I can’t find anyone else complaining about this, which is odd because both my Spotlight configuration was the default (before I told it not to index the mail) and I’m not doing anything special in my mu4e configuration.

The second problem is sometimes it can take 30 seconds or longer for the email list to come up. Less often there is also a delay when I select a message before it appears. The delays appear to happen when mu is running. I haven’t figured out what’s causing this yet. I’d be happy to hear from anyone with some wisdom on the matter.

I’m inclined to think these problems were caused by the OS update and hope that they’ll be resolved when Big Sur is released. That happened before with a delay when invoking the browser from an Org link: the problem resolved itself with a new OS release. Again, if anyone has seen similar problems, let me know.

-1:-- Troubleshooting Mu4e (Post jcs)--L0--C0--August 02, 2020 06:48 PM

Grant Rettke: Is It Impossible To Print Org-Mode Files With Unicode To PDF?

Org-Mode uses UTF-8 files. Therefore you can use the full range of Unicode characters in them. As long as you have a font that contains them, then they will show up correctly. However, when you export to a PDF, why don’t they show up in the PDF? The reason is that the exporter from Org-Mode … Continue reading "Is It Impossible To Print Org-Mode Files With Unicode To PDF?"
-1:-- Is It Impossible To Print Org-Mode Files With Unicode To PDF? (Post grant)--L0--C0--August 02, 2020 12:15 AM

Alvaro Ramirez: SwiftUI macOS desk clock

02 August 2020 SwiftUI macOS desk clock

everclock.gif

For time display, I've gone back and forth between an always-displayed macOS's menu bar to an auto-hide menu bar, and letting Emacs display the time. Neither felt great nor settled.

With some tweaks, Paul Hudson's How to use a timer with SwiftUI, led me to build a simple desk clock. Ok, let's not get fancy. It's really just an always-on-top floating window, showing a swiftUI label, but hey I like the minimalist feel ;)

Let's see if it sticks around or it gets in the way… Either way, here's standalone snippet. Run with swift deskclock.swift.

 import Cocoa
 import SwiftUI

 let application = NSApplication. shared
 let appDelegate =  AppDelegate()
NSApp. setActivationPolicy(. regular)
application. delegate = appDelegate
application. mainMenu = NSMenu. makeMenu()
application. run()

 struct  ClockView: View {
   @State  var time =  "--:--"

   let timer =  Timer. publish(every: 1, on: . main,  in: . common). autoconnect()

   var body:  some View {
    GeometryReader { geometry  in

      VStack {
         Text(time)
          . onReceive(timer) { input  in
             let formatter =  DateFormatter()
            formatter. dateFormat =  "HH:mm"
            time = formatter. string(from: input)
          }
          . font(. system(size: 40))
          . padding()
      }. frame(width: geometry. size. width, height: geometry. size. height)
        . background(Color. black)
        . cornerRadius(10)
        . frame(maxWidth: . infinity, maxHeight: . infinity)
    }
  }
}

 extension  NSWindow {
   static  func  makeWindow() -> NSWindow {
     let window =  NSWindow(
      contentRect:  NSRect. makeDefault(),
      styleMask: [. closable, . miniaturizable, . resizable, . fullSizeContentView],
      backing: . buffered,  defer:  false)
    window. level = . floating
    window. setFrameAutosaveName("everclock")
    window. collectionBehavior = [. canJoinAllSpaces, . stationary, . ignoresCycle, . fullScreenPrimary]
    window. makeKeyAndOrderFront(nil)
    window. isMovableByWindowBackground =  true
    window. titleVisibility = . hidden
    window. backgroundColor = . clear
     return window
  }
}

 class  AppDelegate:  NSObject, NSApplicationDelegate {
   var window = NSWindow. makeWindow()
   var hostingView: NSView?

   func  applicationDidFinishLaunching(_ notification:  Notification) {
    hostingView =  NSHostingView(rootView:  ClockView())
    window. contentView = hostingView
    NSApp. activate(ignoringOtherApps:  true)
  }
}

 extension  NSRect {
   static  func  makeDefault() ->  NSRect {
     let initialMargin =  CGFloat(60)
     let fallback =  NSRect(x: 0, y: 0, width: 100, height: 150)

     guard  let screenFrame = NSScreen. main?. frame  else {
       return fallback
    }

     return  NSRect(
      x: screenFrame. maxX - fallback. width - initialMargin,
      y: screenFrame. maxY - fallback. height - initialMargin,
      width: fallback. width, height: fallback. height)
  }
}

 extension  NSMenu {
   static  func  makeMenu() -> NSMenu {
     let appMenu =  NSMenuItem()
    appMenu. submenu =  NSMenu()

    appMenu. submenu?. addItem(
       NSMenuItem(
        title:  "Quit \( ProcessInfo. processInfo. processName )",
        action:  #selector(NSApplication. terminate(_:)), keyEquivalent:  "q"
      ))

     let mainMenu =  NSMenu(title:  "Main Menu")
    mainMenu. addItem(appMenu)
     return mainMenu
  }
}

-1:-- SwiftUI macOS desk clock (Post Álvaro Ramírez)--L0--C0--August 01, 2020 11:00 PM

Irreal: Update On My 27.1RC1 Experience

It’s been a few days since I installed and starting using Emacs 27.1RC1 for all my day-to-day chores. If you follow the Emacs development list, all the items concerning 27.1 problems might lead you to think that it still wasn’t very stable but I haven’t found that to be the case at all.

By now, I’ve performed just about every one of the workflow operations that I do with Emacs and it’s performed flawlessly. The only difference I’ve seen is that Org-mode on large files is much speedier that it was before. It’s the same Org-mode so that probably means Emacs itself is faster.

I even tried EWW although I don’t usually use it much. It seemed about the same as before but I don’t have enough experience with it to say for sure. I’d really like to move as much browsing as possible into Emacs so perhaps I’ll try to use it more and get better familiar with it.

The TL;DR is that 27.1RC1 seems very stable to me, a very heavy user, and I have no hesitation in recommending that others upgrade to it. Doubtless the final version will be released soon so if you’re really wary just wait but as far as I can see there’s no reason not to start using it and help with the final testing. All you have to do if you find a problem is file a bug report, which, of course, you can do right from Emacs.

-1:-- Update On My 27.1RC1 Experience (Post jcs)--L0--C0--August 01, 2020 05:24 PM

Irreal: Red Meat Friday: Offered Without Comment

-1:-- Red Meat Friday: Offered Without Comment (Post jcs)--L0--C0--July 31, 2020 04:25 PM

Andrea: YASnippet list my email questions please!

How to make a dynamic YASnippet list questions in an email
-1:-- YASnippet list my email questions please! (Post)--L0--C0--July 31, 2020 12:00 AM

Irreal: Emacs 27.1-RC1

Emacs 27 is entering the home stretch. Nicolas Petton has pushed a commit bumping the version number from 27.0.91 to 27.1 and prepared tar and zip files for RC1.

If you can, download it and try it out. The testing will help sand off any remaining burrs on the release candidate and get Emacs 27.1 officially released as soon as possible.

As you all know, Emacs is the center of my computer workflow and I’m inclined to be very conservative about making changes. Nonetheless, I downloaded RC1, compiled, and installed it. I kept the 26.3 package in case of problems but I’m committed to using Emacs 27 for my daily work. If I can do it, you can too. It’s still early but so far thing are working wonderfully. Emacs seems snappier and I haven’t seen any problems.

-1:-- Emacs 27.1-RC1 (Post jcs)--L0--C0--July 30, 2020 04:22 PM

Adrien Brochard: ERT: Emacs Lisp Regression Testing

ERT: Emacs Lisp Regression Testing

ERT: Emacs Lisp Regression Testing

Link

This is the written version of a lightning talk I recently gave at the NYC Emacs Meetup, which is a great meetup that I cannot recommend enough.

1Why

The goal is simple: automatically make sure that a program is not broken by writing tests for it and running them automatically.

Emacs lisp in particular is a good candidate for automated testing because it is ancient and quirky, provides no static types, and is often the result of many individual contributors. And to make things super easy, Emacs is shipped with ert, the Emacs Lisp Regression Testing library to write and run tests.

2Simple example

Let's start by writing a silly package in a silly.el file with some silly functions like this silly-division
    (defun silly-division (a b)
      "Silly divide A by B."
      (if (equal b 1)
          a
        (/ a b)))
  1. divide a by b
  2. if b is 1, spare ourselves the computation and return a

2.1Simple test

We can now write our first silly test:
     (require 'ert)

     (ert-deftest silly-test-division ()
       (should (equal 4 (silly-division 8 2))))
  1. import the ert library
  2. create a test named silly-test-division
  3. make sure that in our world 8/2 = 4

For practical reasons, I would write my tests in a file named silly-test.el next to silly.el.

2.2How to run

You can run a test interactively via M-x ert and selecting it, or by evaluating
     (ert 'silly-test-division)

ert-results

Once ran, you will be in the debugging editor where you can:

  • "TAB" to move around
  • "." to jump to code
  • "b" for backtrace
  • "l" to show all should statements

2.3Testing multiple cases

To be a bit more comprehensive we can pack multiple should statements in the same test. This allows us to look at multiple cases while still keeping the test results clear.
     (ert-deftest silly-test-division ()
       (should (equal 4 (silly-division 8 2)))
       (should (equal 2 (silly-division 10 5)))
       (should (equal 10 (silly-division 10 1)))
       (should (equal 2 (silly-division 8 4))))

     (ert 'silly-test-division)

Remember that the "l" key in the tests results buffer will show all the should statements individually:

ert-should-list

2.4Testing for error

Sometimes it can be useful to make sure that our code errors under certain scenarios. In the case of silly-division, we do want to throw an error if the user tries to divide by zero. To test that, we can use the should-error function and optionally pass the type of error we expect to see.
     (ert-deftest silly-test-division-by-zero ()
       (should-error (silly-division 8 0)
                     :type 'arith-error))

     (ert 'silly-test-division-by-zero)

2.5Testing for failure

An even more under-estimated feature is the ability to write a failing test. This can be very useful for recording known bugs and helping contributors fix things. In our case, silly-division has a problem: it only does integer division. If you run (silly-division 1 2), you should see the output as 0.

Rather than fix our function to perform floating point division, let's write a test for this bug:

     (ert-deftest silly-test-float-division-bug ()
       :expected-result :failed
       (should (equal .5 (silly-division 1 2))))

     (ert 'silly-test-float-division-bug)
When ran, we will see a failure in the result buffer but the failure will be indicated by a green lower-case f.

ert-test-failure

3Trickier function

Let's add another silly function to our silly-package
    (defun silly-temp-writer (str)
      (with-temp-buffer
        (insert (format "L %s L" str))
        (write-file "/tmp/silly-write.txt")))
  1. take a string
  2. format it "L %s L"
  3. write that string to "/tmp/silly-write.txt"
  4. don't return anything

How can we reliably test this? And what are we actually trying to test? I would argue that we want to make sure that what ends up being written to the file what we expect.

3.1Naive method

We can try a naive approach which will work:
     (ert-deftest silly-test-temp-writer ()
       (silly-temp-writer "my-string")
       (should (equal "L my-string L"
                      (with-temp-buffer
                        (insert-file-contents "/tmp/silly-write.txt")
                        (string-trim (buffer-string))))))

     (ert 'silly-test-temp-writer)
  1. call silly-temp-write-function with string "my-string"
  2. read the content of "/tmp/silly-write.txt"
  3. remove the new line
  4. compare it to expected result "Lmy-stringL"

However, we have a few issues here:

  • side effects in the test, we are leaving a file on the machine after running the test
  • no isolation, if another process deletes the file mid-test, we could have a false negative
  • testing more than we should, we are not just testing our logic but also the write-file function
  • test complexity, our test is convoluted and hard to read

3.2Better approach with mocking

A better approach when trying to test functions which do not return a value or have side-effects is to use mocking. We will temporarily re-wire the write-file function to perform some assertion instead of actually writing to a file on disk.
     (require 'cl-macs)

     (ert-deftest silly-test-temp-writer ()
       (cl-letf (((symbol-function 'write-file)
                  (lambda (filename)
                    (should (equal "/tmp/silly-write.txt" filename))
                    (should (equal "L my-string L" (buffer-string))))))
         (silly-temp-writer "my-string")))

     (ert 'silly-test-temp-writer)
  1. Define a mock write-file function
    • check that we write in the correct location
    • check that the content is formatted properly
  2. Temporarily replace the real write-file with our mock
  3. Call silly-temp-writer

We can observe that now most of our issues from the naive test are gone:

  • Not actually writing to the system or leaving state
  • Test more and closer to the intended behavior
  • Not testing something we didn't intend to (ie. the write-file function)

NB: In the past I used to do this with the flet function but apparently it is obsolete since Emacs 24.3. As a replacement, I found that cl-left from the cl-macs library did the job pretty well.

4Running all tests at once

Now that we have a whole bunch of tests defined, we can run them all once. You may have noticed that all example tests were prefixed the same way, it was to make this task easier by passing a regexp to the ert function:
    (ert "silly-test-*")

And you can take it even further by running the tests from a bash script or a docker command, perfect for your CI pipeline:

     docker run -it --rm  -v $(pwd):/silly silex/emacs emacs -batch -l ert -l /silly/silly.el -l /silly/silly-test.el -f ert-run-tests-batch-and-exit

Which will output:

    Running 4 tests (2020-07-08 14:47:49+0000)
       passed  1/4  silly-test-division
       passed  2/4  silly-test-division-by-zero
       failed  3/4  silly-test-float-division-bug
       passed  4/4  silly-test-temp-writer

    Ran 4 tests, 4 results as expected (2020-07-08 14:47:49+0000)
    1 expected failures

5Visualizing coverage

A less known feature, but it is possible to visually see which lines are covered by your tests and how well.
  1. M-x testcover-start
  2. Select the silly.el file
  3. Run tests
           (ert "silly-test-*")
    
  4. M-x testcover-mark-all and select silly.el
  5. See results:
    • red is not evaluated at all
    • brown is always evaluated with the same value

ert-testcover

For example, in this case, we can see that I only have one test case for my silly-division with b equal to 1 and returning a directly.

6Best practices

  • ask yourself what you want to test
  • start by making tests fail, there's nothing better to insure you are taking the code path you think you are taking
  • write clean test with no side effect, and if you must have side effect, run a cleanup function afterwards
  • descriptive test names can really help figure out what is broken
  • good tests means good debugging

7More Resources

-1:-- ERT: Emacs Lisp Regression Testing (Post)--L0--C0--July 30, 2020 01:34 AM

Irreal: Super-links

This looks promising. Karl Voit has a post about org-super-links and their use in implementing a sort of poor man’s Zettelkasten. Super-links is still very preliminary but the idea is to provide an automatic way of implementing back links, something you need for an effective Zettelkasten.

You can, of course, add those links manually. That’s what I do in my homegrown Zettelkasten but it’s a pain and adds enough friction to prevent me from entering as many items as I should. That’s why my future plans are still centered around Org-roam. I just need to find the time and energy to get it configured and start using it.

On the other hand, if you’re like Voit and don’t need or want a full blown Zettelkasten but have applications where back links would be useful, super-links may be just what you need. I’m looking forward to seeing how this project develops. Perhaps it will even be integrated into Org itself once it matures.

-1:-- Super-links (Post jcs)--L0--C0--July 29, 2020 04:10 PM

Irreal: An Emacs/Org-mode Setup for Writing

Bhalla Kunal over at expLog has an interesting post on his writing setup. It’s Emacs and Org-mode based but, interestingly, he says that the thing that helped his workflow the most was rotating his monitor so that he had more lines on the screen. That means, of course, that he doesn’t have as much horizontal real estate but Kunal likes to keep his lines at 80 characters or less so it works out well for him.

He does, of course, use Olivetti but that’s not too surprising. Mostly he configures Emacs and Org-mode the way you’d expect someone would for a writing environment but he does have a few customizations worth mentioning.

He’s very dedicated to keeping his lines less than 80 characters so he didn’t like the indentation for subheadings in Org-mode. He modified that by setting the indentation to a single space. That helped him keep each line on the screen. Likewise, he inhibited the indentation of the text under each headline for the same reason. He’s also set the text to be in variable pitch font. This is a popular tweak but I’ve never been a fan. I tend to think in “markup” so ASCII input text seems natural to me.

His final tweak is to enable org-hide-emphasis-markers. That means that Org will hide the markup used for bold, Italics, underline, and so on. This is exactly the sort of change that would drive me crazy but I understand how some might prefer it. I probably don’t like it for the same reason I prefer ASCII text for input.

You can get all the details in Kunal’s post so head on over there if you’d like to try some or all of his workflow.

-1:-- An Emacs/Org-mode Setup for Writing (Post jcs)--L0--C0--July 28, 2020 06:17 PM

Sacha Chua: 2020-07-27 Emacs news

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Hacker News, planet.emacslife.com, YouTube, the Emacs NEWS file and emacs-devel.

-1:-- 2020-07-27 Emacs news (Post Sacha Chua)--L0--C0--July 28, 2020 04:01 AM

Andrea: How to integrate YASnippet and Yankpad with Org-Capture

-1:-- How to integrate YASnippet and Yankpad with Org-Capture (Post)--L0--C0--July 28, 2020 12:00 AM

Irreal: The Right Dictionary and How to Get It

Yesterday, I saw a tweet in which someone referred to Marcin Borkowski’s 2017 post on using the Webster 1923 dictionary in Emacs. Why would you want to do that? The answer to that is given in James Somers’ 2014 post, You’re Probably Using the Wrong Dictionary that I wrote about in 2015.

Since I wrote about it, I’ve been using the Webster dictionary to help me find just the right word. At first, I just used the Web site as Borkowski did but when that disappeared, I followed Borkowski’s simple instructions and installed it locally. Using sdcv-mode, it’s available directly from Emacs. If you write at all and would like to do a better job of it, you should consider installing it too. I can’t overemphasize what a great resource it is.

If this is the first time you’ve come across the Webster 1923 dictionary, do yourself a favor and read Somer’s post. It’s beautifully written and makes a strong case for using the dictionary. Integrating it into Emacs is easy and even if you’re not an Emacs user, you can still use it from the command line. If you’re a Mac user, you can install sdcv from Homebrew.

-1:-- The Right Dictionary and How to Get It (Post jcs)--L0--C0--July 27, 2020 03:47 PM

Grant Rettke: Make Your Emacs Frame Fit Flush On macOS

When you try to align your Emacs frame flush on macOS and it just doesn’t quite reach the edge You can fix it with Via Reddit.
-1:-- Make Your Emacs Frame Fit Flush On macOS (Post grant)--L0--C0--July 25, 2020 11:12 PM

(with-emacs: What you Need to Know About Hooks

Hooks are an important mechanism for customizing Emacs. They are used to execute code on certain occasions and are part of any non-trivial Emacs setup. In this post you will learn how to use them for your own configurations and about some pitfalls you might encounter in practice.

This post assumes that you already know some basics about Elisp and variables as discussed earlier. All examples also assume you use a fairly recent Emacs version (v.26 or later).

Basic usage

Hooks are regular variables which hold a function or more commonly a list of them. These functions are called when the hook runs. Here is a typical snippet of user configuration:

(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p)

The above adds the function executable-make-buffer-file-executable-if-script-p to after-save-hook. Afterwards this function gets called each time you save a buffer. If the file is a script (as detected by #!) the file is made executable.

To remove the function again you use remove-hook:

(remove-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p)

By convention those variables end with -hook in their name so you can easily search for them. Because many packages and modes come with their own set of hooks it can be hard to track down the more general ones but you can find a list of the standard Emacs hooks in the manual.

It’s important to mention that you shouldn’t use anonymous functions for your hooks because it becomes hard to tell the purpose of a lambda when you inspect the hook at some later point. Another benefit of using named functions is that you can easily remove them by passing their name to remove-hook.

Major mode hooks

If you want to run setup functions for specific modes you can use major mode hooks. These hooks will run when you enter the mode. Note that hooks don’t need to be defined ahead of time so you can add functions to them before the corresponding mode is loaded by Emacs.

Sometimes you will come across examples where major mode hooks are used to setup keybindings like this:

(defun python-key-setup+ ()
  (local-set-key ...) ...)

(add-hook 'python-mode-hook #'python-key-setup+)

While this works it will set the key bindings every time a buffer enters the mode which isn’t necessary. The local keymap is usually the major mode keymap which is shared by all buffers which use that mode. You can achieve the same effect by defining the bindings only once after the keymap is available:

(with-eval-after-load 'python
  (define-key python-mode-map ...))

Buffer local hooks

In the first section executable-make-buffer-file-executable-if-script-p was added to the global hook but often you want to adjust hooks only for specific buffers. You might be tempted to check for buffer names or major modes in your hook functions like this:

(add-hook 'after-save-hook #'after-save-in-some-buffer+)

(defun after-save-in-some-buffer+ ()
  (when (string= (buffer-name) ...)
    ...))

But a better way is to adjust the hook variable buffer locally by using the local argument of add-hook and remove-hook. For example if you want to run the executable-make-buffer-file-executable-if-script-p only in sh-mode buffers you can use:

(defun sh-mode-setup+ ()
  (add-hook 'after-save-hook
            #'executable-make-buffer-file-executable-if-script-p
            nil 'local))

(add-hook 'sh-mode-hook #'sh-mode-setup+)

When the major mode sh-mode is entered, sh-mode-setup+ will run and add executable-make-buffer-file-executable-if-script-p to the buffer local save hook.

Usually you shouldn’t use make-local-variable to make hook variables local because add-hook automatically handles some things for you: It arranges for a final t at the end of the local hook list. This will tell run-hooks that the global hook should run as well. Usually this is what you want because the global hook should be expected to run regardless of any additional local setup. Further any subsequent calls to add-hook won’t automatically affect the local value which is useful because there might be some other setup functions running down the chain which don’t expect the hook variable to be local.

Like with other local variables if you want to get completely rid of the local version you can use kill-local-variable.

Minor mode hooks

A common pitfall is to think minor mode hooks work like major mode hooks but there is an important difference: Minor modes run their hooks when you enter and when you leave them. This can be used to run additional setup or teardown code. For example if you always want to toggle a mode in tandem with another one you can use something like:

(add-hook 'visual-fill-column-mode-hook #'visual-fill-column-toggle-wrap+)

(defun visual-fill-column-toggle-wrap+ ()
  (adaptive-wrap-prefix-mode
   (if visual-fill-column-mode 1 -1)))

The mode variable visual-fill-column-mode will be t when activating the mode. The example above uses this to activate and deactivate adaptive-wrap-prefix-mode accordingly.

Abnormal hooks

In contrast to the normal hooks this post talked about there are also so called abnormal hooks which by convention end with -functions in their name. Those can receive additional arguments or their return value is used for further processing. The exact details need to be described by their documentation. They are not as relevant for user configuration but can be very useful when writing Elisp so you might want to learn more about how to use them (see the comments). Generally the same concepts apply for these hooks and conveniently you can continue to use add-hook or remove-hook for them, too.

-1:-- What you Need to Know About Hooks (Post clemera)--L0--C0--July 25, 2020 06:45 PM

Irreal: A Paper-Like Emacs Writing Configuration

Manuel Uberti enjoys writing his journal entries with pen and paper. Lots of people do although I’m not one of them. The fact, as I’m sure I’ve mentioned before, that I have terrible handwriting no doubt has something to do with that. Still, I do understand the urge.

Uberti likes the pen and paper experience so much that he’s tried to recreate it for writing his blog entries. He’s got a post that describes his Emacs configuration to recapitulate the pen and paper experience. This means he uses the aggressively light theme Modus Operandi with a variable pitch font. As you’d expect, he uses Olivetti to further enhance the illusion of writing on a sheet of paper.

Finally, he uses freeze-it so that he can work only on the current paragraph. The idea is to inhibit the natural urge to edit what you’ve written before. I’m not sure what this has to do with recapitulating a bullet journal but I do know that it would drive me crazy. Perhaps that’s an indication I should be using it.

If this sort of thing appeals to you, you can get all the details from Uberti’s post. I’m perfectly happy to write in a normal Org-mode buffer but lots of folks like the feeling of working on a blank page when they write. As usual, Emacs has got you covered.

-1:-- A Paper-Like Emacs Writing Configuration (Post jcs)--L0--C0--July 25, 2020 03:40 PM

tycho garen: Emacs and LSP Mode

I've been using emacs for a long time, and it's mostly pretty unexceptional. A few months ago, I started using LSP mode, and it's been pretty great... mostly. This post reflects on some of the dustier corners, and some of the broader implications.

History and Conflict

Language Server is a cool idea, that (as far as I know) grew out of VS Code, and provides a way to give a text editor "advanced, IDE-like" features without having to implement those features per-language in the text editor. Instead, editor developers implement generic integration for the protocol, and language developers produce a single process that can process source code and supports the editor features. Sounds great!

There are challenges:

  • The LSP protocol uses JSON for encoding data between the server and emacs. This is a reasonable choice, and makes development easy, but it's not a perfect fit. Primarily, in emacs, until version 27, which hasn't reached an official release yet (but is quite usable on Linux), parsed JSON in lisp rather than C, which made everything rather slow, but emacs 27 helps a lot. Second,

  • There is some overhead for the lsp, particularly as you attempt to scale very large numbers of files or very large files. Emacs is really good with large files, as an artifact of having had to support editing larger files on computers 20 or 30 years ago, and lsp feels sluggish in these situations.

    I think some of this overhead is probably depends on the implementation of the language server's themselves, and some percentage is probably protocol itself: http's statelessness is great in big distributed web services, and for the local use cases where responsiveness matters, it's less good. Similarly JSON's transparency and ubiquity is great, but for streaming streaming-type use cases, perhaps less so.

I've not poked around the protocol, or any implementations, extensively, so I'm very prepared to be wrong about these points.

There's also some tension about moving features, like support for adding editor support for a language, out of lisp and into an external process. While I'm broadly sympathetic, and think there are a bunch of high-quality language integrations in emacs lisp, and for basic things, the emacs lisp ones might be faster. Having said that, there's a lot of interface inconsistency between different support for languages in emacs, and LSP support feels spiffy my comparisons. Also at least for python (jedi,) go (gocode), and C/C++ (irony,) lisp (slime,) the non-lsp services were already using external processes for some portion of their functionality.

It's also the case that if people spend their emacs-lisp-writing time doing things other than writing support for various development environments it's all for the better anyway.

Suggestions / Notes

  • things will break or get wedged, call lsp-restart-workspace to restart the server (I think.) It helps.
  • use lsp-file-watch-ignored to avoid having the language servers process emacs process files from vendored code, intermediate/generated code, or similar, in cases where you might have a large number of files that aren't actually material to your development work
  • I believe some (many? all?) servers are sourced from the PATH (e.g. clang/llvm, gopls), which means you are responsible for updating them and their dependencies.
  • I've found it useful to update lsp-mode itself more often than I typically update other emacs packages. I also try and keep the language servers as up to date as possible in coordination with lsp-mode updates.
  • If Emacs 27 can work on your system, it's noticeably faster. Do that.
  • If you have an existing setup for a language environment, the LSP features end up layering over existing functionality, and that can have unexpected results.

My Configuration

None of this is particularly exciting, but if you use use-package, then the following might be an interesting starting point. I stole a lot of this from other places, so shrug.

I must say that I don't really use dap or treemacs, because I tend to keep things pretty barebones.

(use-package helm-lsp
  :ensure t
  :after (lsp-mode)
  :commands (helm-lsp-workspace-symbol)
  :init (define-key lsp-mode-map [remap xref-find-apropos] #'helm-lsp-workspace-symbol))

(use-package lsp-mode
  :diminish (lsp-mode . "lsp")
  :bind (:map lsp-mode-map
    ("C-c C-d" . lsp-describe-thing-at-point))
  :hook ((python-mode . #'lsp-deferred)
    (js-mode . #'lsp-deferred)
    (go-mode-hook . #'lsp-deferred))
  :init
  (setq lsp-auto-guess-root t       ; Detect project root
   lsp-log-io nil
   lsp-enable-indentation t
   lsp-enable-imenu t
   lsp-keymap-prefix "C-l"
   lsp-file-watch-threshold 500
   lsp-prefer-flymake nil)      ; Use lsp-ui and flycheck

  (defun lsp-on-save-operation ()
    (when (or (boundp 'lsp-mode)
         (bound-p 'lsp-deferred))
      (lsp-organize-imports)
      (lsp-format-buffer))))

(use-package lsp-clients
  :ensure nil
  :after (lsp-mode)
  :init (setq lsp-clients-python-library-directories '("/usr/local/" "/usr/")))

(use-package lsp-ui
  :ensure t
  :after (lsp-mode)
  :commands lsp-ui-doc-hide
  :bind (:map lsp-ui-mode-map
         ([remap xref-find-definitions] . lsp-ui-peek-find-definitions)
         ([remap xref-find-references] . lsp-ui-peek-find-references)
         ("C-c u" . lsp-ui-imenu))
  :init (setq lsp-ui-doc-enable t
         lsp-ui-doc-use-webkit nil
         lsp-ui-doc-header nil
         lsp-ui-doc-delay 0.2
         lsp-ui-doc-include-signature t
         lsp-ui-doc-alignment 'at-point
         lsp-ui-doc-use-childframe nil
         lsp-ui-doc-border (face-foreground 'default)
         lsp-ui-peek-enable t
         lsp-ui-peek-show-directory t
         lsp-ui-sideline-update-mode 'line
         lsp-ui-sideline-enable t
         lsp-ui-sideline-show-code-actions t
         lsp-ui-sideline-show-hover nil
         lsp-ui-sideline-ignore-duplicate t)
  :config
  (add-to-list 'lsp-ui-doc-frame-parameters '(right-fringe . 8))

  ;; `C-g'to close doc
  (advice-add #'keyboard-quit :before #'lsp-ui-doc-hide)

  ;; Reset `lsp-ui-doc-background' after loading theme
  (add-hook 'after-load-theme-hook
       (lambda ()
         (setq lsp-ui-doc-border (face-foreground 'default))
         (set-face-background 'lsp-ui-doc-background
                              (face-background 'tooltip))))

  ;; WORKAROUND Hide mode-line of the lsp-ui-imenu buffer
  ;; @see https://github.com/emacs-lsp/lsp-ui/issues/243
  (defadvice lsp-ui-imenu (after hide-lsp-ui-imenu-mode-line activate)
    (setq mode-line-format nil)))

;; Debug
(use-package dap-mode
  :diminish dap-mode
  :ensure t
  :after (lsp-mode)
  :functions dap-hydra/nil
  :bind (:map lsp-mode-map
         ("<f5>" . dap-debug)
         ("M-<f5>" . dap-hydra))
  :hook ((dap-mode . dap-ui-mode)
    (dap-session-created . (lambda (&_rest) (dap-hydra)))
    (dap-terminated . (lambda (&_rest) (dap-hydra/nil)))))

(use-package lsp-treemacs
  :after (lsp-mode treemacs)
  :ensure t
  :commands lsp-treemacs-errors-list
  :bind (:map lsp-mode-map
         ("M-9" . lsp-treemacs-errors-list)))

(use-package treemacs
  :ensure t
  :commands (treemacs)
  :after (lsp-mode))
-1:-- Emacs and LSP Mode (Post)--L0--C0--July 25, 2020 12:00 AM

Andrea: Fail fast and then fail better

-1:-- Fail fast and then fail better (Post)--L0--C0--July 25, 2020 12:00 AM

Andrea: Automate boring configuration changes

-1:-- Automate boring configuration changes (Post)--L0--C0--July 25, 2020 12:00 AM

Andrea: Functional abstractions in JavaScript: fishing fmaps with Kleisli

-1:-- Functional abstractions in JavaScript: fishing fmaps with Kleisli (Post)--L0--C0--July 25, 2020 12:00 AM

Andrea: Fold the recursive function

-1:-- Fold the recursive function (Post)--L0--C0--July 25, 2020 12:00 AM

Andrea: How to jump to next bullet point in org mode

-1:-- How to jump to next bullet point in org mode (Post)--L0--C0--July 25, 2020 12:00 AM

Andrea: Make Org-feed wget timeout

-1:-- Make Org-feed wget timeout (Post)--L0--C0--July 25, 2020 12:00 AM

Andrea: Going through Lacinia tutorial to get familiar with GraphQL

-1:-- Going through Lacinia tutorial to get familiar with GraphQL (Post)--L0--C0--July 25, 2020 12:00 AM

Andrea: A docstring for Scala functions through YaSnippet

-1:-- A docstring for Scala functions through YaSnippet (Post)--L0--C0--July 25, 2020 12:00 AM

Manuel Uberti: Paper Emacs

Since I moved to bullet-journaling, most of the time I have been writing on paper. Even though I’ve not restricted my Emacs time to Clojure programming, paper and fountain pen have changed the way I approach my favourite text editor for prose.

As I was writing articles for my blogs, I’ve discovered that I wanted my text-editing environment as close as possible to the beautiful, distraction-free feeling of a blank page. There are plenty of themes and modes out there to suit this particular need, but the combination of settings and packages I am about to describe has proven to be the most satisfying so far.

Theme

A light theme is the obvious choice to mirror the paper look. Since I have been using modus-operandi for a while now, there is no reason to look for something else. Everything in markdown-mode is supported, and with a variable-pitch font (FiraGO in my case) the buffer stops resembling code for once.

Editing modes

I write all my articles in Markdown, but to achieve the desired distraction-free effect I rely on Protesilaos Stavrou’s tips, slightly adjusted to my preferences: “Focused editing tools” for Emacs and Emacs: configuring mixed fonts in Org mode. I am using a variant of Olivetti like him, the only difference being the use of text-scale-increase to increase the text size and text-scale-decrease to restore it back to normal when leaving the mode.

On top of that I use freeze-it, which is like having someone slapping my hands away from the text before the current paragraph. Harsh, yes, but for the obsessive-compulsive writer an effective way to keep the mind focused on one thing at the time. I can always review the previous paragraphs later, and with the big picture in front of me editing often becomes deleting.

Mode-line

Once again, I find myself tweaking the mode-line. Setting modus-operandi-theme-3d-modeline has been enough thus far, but something less prominent can be closer to the no-frills of my BuJo. Luckily William Rankin, the author of Olivetti and freeze-it, shared his magic tricks and I followed his lead. I merely threw in coloured indicators for modified, read-only, and remote buffers. Sorry, I can’t resist a little bit of fanciness.

Final notes

There is more than this to my writing environment. For instance, I wrote about spell-checking before and I use Artur Malabarba’s suggestions on paragraph movements. Not to mention the default Emacs facilities for marking, killing, yanking, and moving around the buffer. Nonetheless, this should be enough to write prose in a quieter and more fruitful way.

-1:-- Paper Emacs (Post)--L0--C0--July 24, 2020 12:00 AM

Irreal: Quit Processes on Exit from Emacs

Yesterday, I wrote about fixing a small annoyance on my MacBook. Here’s a quickie from Bozhidar Batsov that fixes another small annoyance. This time the annoyance is with Emacs, although as Batsov explains, it’s particularly annoying on macOS.

The problem is that Emacs wants you to confirm that it’s okay to kill any running processes when you exit Emacs. Until Emacs 26 there was no way to prevent that but now, as Batsov explains, it’s simple. You merely set confirm-kill-processes to nil and Emacs will exit without worrying about any processes that are still running.

I can sort of see why asking about the processes before exiting is a good idea—you don’t want to interrupt some important long running process—but I can’t ever remember answering anything but y to the prompt so, at least for me, turning off the prompt makes sense. If you feel the same—particularly if you’re running macOS—you might want to consider turning it off too.

-1:-- Quit Processes on Exit from Emacs (Post jcs)--L0--C0--July 23, 2020 04:41 PM

Alex Schroeder: Demonstrating Gemini Wiki

This wiki is also served via the Gemini protocol (something between Gopher and the Web as we know it). I’ve written an extension that allows me to write back to the wiki (and not just leave a single line of comments).

In case you’re curious, today I made a short 50s video!

Made using Emacs, Elpher, Gemini, Oddmuse, Peek, and Garage Band. 😀

If you’re interested in how this works, I think the two two bash functions I wrote make two good examples: gemini allows you to read and titan allows you to write.

Tags:

-1:-- Demonstrating Gemini Wiki (Post)--L0--C0--July 22, 2020 10:06 AM

Irreal: A Shortcut Manager for My Emacs-centric Workstation

At first glance, this post might appear to be of interest only to Mac users but most of the ideas also apply to other systems. As I’ve written many times, Emacs is at the center of my computing workflow. Almost everything I do, I do in Emacs. The only major exception is browsing for which I use Safari. Of course, other things are always going on—my continual Backblaze backup, for example—but I don’t normally interact with those.

Because I run Emacs and Safari in full screen on their own pages, it’s important that I have a quick and easy way of switching between them. I also want to bring up an Org capture buffer from anywhere in the system. I do all these things by assigning systemwide function keys to the desired action. Thus F6 switches to Emacs and F7 to Safari.

I used to do all that through Quicksilver but it’s really more heavy duty than I need since all I’m interested in is mapping shortcuts to actions. I’ve long considered getting one of the key mappers available for the Mac but as I mentioned in my Emacsclient and macOS post, I recently learned about iCanHazShortcut, which does just what I need. I specify a key combination and the desired operation and iCanHazShortcut takes care of the rest.

One of the tricky things on a Mac is telling the system to switch to an app—Emacs, say—rather than starting a new instance. It turns out that the proper command line invocation is open -a emacs. Now I have a simple and lightweight way of switching between Emacs and Safari.

That leaves only invoking a capture buffer from outside Emacs. This is the thing I’ve had the most trouble with historically. I used to use a bit of applescript to do it but it didn’t always work and other methods I tried worked even less well. Then I found Alphapappa’s yequake. It does just what I need and I can easily invoke it with iCanHazShortcut: I have it mapped to F9.

Finally, I had to deal with the touch strip on my MacBook. It likes to present different “buttons” depending on what app has focus but you can set it to always display the function keys and bring up the other buttons with the fn key.

Naturally, most of this will work on any system. You’ll have to find a key mapper appropriate to your OS but other than that, the ideas in this post should travel well.

-1:-- A Shortcut Manager for My Emacs-centric Workstation (Post jcs)--L0--C0--July 21, 2020 03:33 PM

Sacha Chua: 2020-07-20 Emacs news

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Hacker News, planet.emacslife.com, YouTube, the Emacs NEWS file and emacs-devel.

-1:-- 2020-07-20 Emacs news (Post Sacha Chua)--L0--C0--July 21, 2020 03:34 AM

Irreal: Emacs for Everything

Alex Schroeder is an Emacs user who, like me, does as much as he can in Emacs. Also like me, he spends most of his tube time in Emacs or a browser. Unlike me, he uses EWW for a good part of his browsing. I’ve tried to do that too but could never make it stick. Something always seems to go wrong.

Schroeder has an interesting post in which he documents some of his configuration. Especially interesting is his Dired configurations. He use Dired as his file manager so it gets a lot of use and he has some tweaks that you might not know about. If you’re an EMMS user, you might be interested in how he uses Dired as his play list.

If you’re looking for ways to subsume more of your tasks under Emacs, Schroeder’s post may have some ideas you can use. Take a look; if nothing else you’ll enjoy his rant about open plan offices.

-1:-- Emacs for Everything (Post jcs)--L0--C0--July 20, 2020 04:54 PM

Raimon Grau: tangling files with org-mode

I've been inspecting this repo https://github.com/kinnala/nixpkgs, and it was the first time I looked at the org tangling. Quite simple to do so:

Mostly using ":mkdirp yes :tangle path", is like doing a "cat block >>path". And you use (org-babel-tangle) as the exporter

#+begin_src elisp :mkdirp yes :tangle ~/.emacs
(org-babel-tangle)
#+end_src
-1:-- tangling files with org-mode (Post Raimon Grau (noreply@blogger.com))--L0--C0--July 20, 2020 08:43 AM

John Herrlin: Learn AWK with Emacs

Intro This post describes my workflow for learning the AWK programming language using Emacs, Org mode and Org-drill. The workflow may work for other programming languages. The post won't cover details on how to use Emacs, Org mode or Org-drill. It's intention is to provide a general overview of a workflow. A git repo is available with flash cards, note book and some text files here. Content I just read a few chapters in the "The AWK programming language" book and found AWK to be awesome and I want to learn more of the language.
-1:-- Learn AWK with Emacs (Post)--L0--C0--July 20, 2020 12:00 AM

Irreal: Emacs Keybindings on macOS Redux

I just saw this tweet from Vivek Haldar

and thought that it’s probably time for Irreal’s semiperiodic reminder that the reality is actually much better than a few default Emacs keybindings.

As I wrote back in 2011, you can customize the keybindings for many of macOS’s editing commands. It’s really easy to setup. You just download a file, rename it, stash it in your ~/Library/KeyBindings folder, and enjoy Emacs editing keybindings across your entire system. Even if we can’t stay in Emacs all the time, at least we can take our muscle memory with us when we’re forced to leave. All the details are in the 2011 post, so take a look at that if you’re interested.

By the way, I checked the links and they’re all still good even after the 14 years since Rus originally wrote about this.

-1:-- Emacs Keybindings on macOS Redux (Post jcs)--L0--C0--July 19, 2020 04:48 PM