Irreal: Who Cares About Emacs?

Over at Opensource.com, Seth Kenlon has an article that asks the question, “Who cares about Emacs?” After all, the editor is ancient. Its GNU incarnation has been around since 1983 and there are plenty of glittery new editors to choose from. Furthermore, whatever functionalities you like in Emacs are probably available in those other editors too. Kenlon asks if Emacs is even relevant anymore.

Of course, we all know the answer. Kenlon gives several reasons why learning and using Emacs still makes a lot of sense. You can read the article for the complete list but the two that resonated with me were that Emacs works just fine in text mode and, most importantly, that it’s hackable.

Some folks prefer using Emacs in a terminal—and emacsclient makes that simple and painless—but even those of us who prefer the GUI there are times when the GUI version is too heavyweight. In those cases, having a text based Emacs with all the features of the GUI version—modulo things like displaying PDFs or images—is a real win.

Of course, the thing that sets Emacs apart is its hackability. Lots of editors claim they’re hackable but often this means, “We provide an API and maybe a scripting language to use with it.” Emacs is not like that. At its base, Emacs is a Lisp interpreter and almost all its functionality is implemented in that Lisp. The important point is that that Lisp is available to the user too, so you can change or add functionality on the same basis as the original implementers. There’s no API to limit what you can do; you can do anything.

Hardcore Emacsers won’t learn anything they didn’t already know but the article is an enjoyable read and worth a few minutes of your time.

-1:-- Who Cares About Emacs? (Post jcs)--L0--C0--February 25, 2020 04:38 PM

Irreal: Refcards

Emacs has many subsystems that are complicated enough that they have their own reference cards: Dired, Org Mode, and Calc are prime examples but there are others. If I find myself using a refcard frequently, I bookmark in my browser and maybe in Emacs’ bookmarks so it’s easy to find. I recently saw a tweet with another idea:

That never occurred to me probably because the locate database isn’t built by default on MacOS and I’ve never bothered to build it. The Mac does have Spotlight, though, which includes locate’s functionality so I invoked it and typed in “refcards.” Just as Manerikar said, I got a list of every refcard on my system. When I clicked on dired-ref.pdf it opened a Preview window with Dired’s refcard. That’s really handy. I may even build the locate database just to try it out there.

-1:-- Refcards (Post jcs)--L0--C0--February 24, 2020 05:40 PM

Sacha Chua: 2020-02-24 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-02-24 Emacs news (Post Sacha Chua)--L0--C0--February 24, 2020 04:10 PM

Irreal: Zamansky 67: Emacs vs. Vi(m)

As promised, Mike Zamansky has published his thoughts on the Emacs vs. Vi controversy in a another video in his Using Emacs Series. Unlike Zamansky, I was a long time user of Vi/Vim before I moved to Emacs so I’m intimately familiar with both editors on a muscle memory level. Zamansky is absolutely right that neither is objectively better than the other; they both have good points and bad points and furthermore what those good and bad points are can vary with every user. As I’ve said before, choosing an editor is like choosing a mate: everyone else should butt out. Zamansky echoes that feeling and says to choose whatever works best for you but to spent some serious time with your candidates to give them a reasonable evaluation.

One of the very best features of Zamansky’s video is that he covers the history of the two editors to show how they evolved and why they are the way that are. He even gives a demo of the Teco editor, which I’ve never seen running before. He also demonstrates Ex and shows how it evolved into Vi. Most of what partisans claim are examples of superior design turn out to be accidents of history.

I hold onto my belief that Emacs and Vi are two different things: that Emacs is an entire development or operating environment and that Vi is an editor that embraces the Unix philosophy of doing one thing and doing it well and that therefore the type of workflow you are looking for should be the deciding factor. I do think that Vi’s composable keybindings are easier to learn any possibly a bit faster but that Emacs has more and better editing features and if you find one it doesn’t have, it’s easy to add it as a first class command at the same level as every other Emacs command.

This is a really excellent video. You probably won’t learn anything new—except possibly what a Teco or Ex session looks like—but the historical background and good sense suggestions make it more than worth watching. The video is 35 minutes, 20 seconds so you’ll need to plan ahead.

-1:-- Zamansky 67: Emacs vs. Vi(m) (Post jcs)--L0--C0--February 23, 2020 06:10 PM

Mike Zamansky: Using Emacs Episode 67 - Emacs vs Vi a rant with some historical perspective

I've been meaning to do my version of the Emacs VI rant for a while. A few years ago I staged out a video showing what it would be like for a beginner to start with Emacs, Vim, Atom, and Sublime Text but decided it would be long, unwieldy and clunky to present - particularly when it came to customization. I tabled it for a while but recently have been seeing a bunch of threads, videos and posts talking about Emacs and Vim.
-1:-- Using Emacs Episode 67 - Emacs vs Vi a rant with some historical perspective (Post)--L0--C0--February 23, 2020 11:57 AM

Irreal: A Comparison of Vim and Emacs

Over at the YouTube DistroTube Channel, Derek Taylor has an even handed video that explores the question Vim Versus Emacs. Which Is Better? Taylor is a n00b with both editors but has come to the same conclusion that I have: why would a serious developer not use one of these editors? The video is barely a week old as I write this so we can be sure that Taylor is aware of all the hot new coolness such as VS Code, Sublime Text, Atom, and the others but he still recommends the “ancient” Vi/Vim and Emacs editors.

Taylor starts off by making the same observation that I often have: comparing Vim and Emacs doesn’t make much sense because they are really different things. Vim is a fast, efficient editor that embraces the notion of doing one thing well. Emacs is more of a development environment that can do almost anything and ships with many built-in apps one of which is an editor.

Taylor is using the Doom distribution so he says actual editing between the two editors is virtually identical and not worth comparing. Rather, he looks at a range of other chores such as file handling, git, and invoking shells. He compares the ease of doing all these with the two editors. Oddly, he doesn’t mention the real Emacs killer app: Org Mode. Everyone here knows that I depend on Org mode and consider it one of the most important parts of Emacs but it’s not just me. Org mode is widely considered Emacs’ killer app and the gateway for many new Emacs users.

The video is 30 minutes, 37 seconds so you’ll need to schedule some time. If you’re interested in a relative new comer’s opinion on the great Editor War the video is definitely worth your time. Taylor is worth listening to because he doesn’t have any preconceived preferences and is not defending his own choices.

-1:-- A Comparison of Vim and Emacs (Post jcs)--L0--C0--February 22, 2020 06:08 PM

Manuel Uberti: Ripgrepping with Helm

Sometimes curiosity leads me to use alternative packages for built-in solutions which I should have explored better. For instance, it took me moving through helm-ag and helm-rg1 before realising Helm already comes with a functionality suitable for my needs: helm-do-grep-ag.

By now I expect you to be familiar with the wonders of ripgrep. I was heavily relying on counsel-rg back in my Ivy days, and I needed a similar command in Helm. Truth be told, helm-do-grep-ag is not the replacement I was looking for, but understanding its code helped me devise my own utilities for super fast searches.

First of all, let’s use ripgrep instead of ag:

(setq helm-grep-ag-command (concat "rg"
                                   " --color=always"
                                   " --smart-case"
                                   " --no-heading"
                                   " --line-number %s %s %s")
      helm-grep-file-path-style 'relative)

Note that the string for helm-grep-ag-command comes from its documentation. I chose relative for helm-grep-file-path-style because I find relative file paths in the search result buffer more useful than their base name.

Now, helm-do-grep-ag defers to helm-grep-ag, which in turns defers to helm-grep-ag-1, and this is the Helm facility I can leverage for my own ripgrep variant.

(defun mu-helm-rg (directory &optional with-types)
  "Search in DIRECTORY with RG.
With WITH-TYPES, ask for file types to search in."
  (interactive "P")
  (require 'helm-adaptive)
  (helm-grep-ag-1 (expand-file-name directory)
                  (helm-aif (and with-types
                                 (helm-grep-ag-get-types))
                      (helm-comp-read
                       "RG type: " it
                       :must-match t
                       :marked-candidates t
                       :fc-transformer 'helm-adaptive-sort
                       :buffer "*helm rg types*"))))

It’s basically helm-grep-ag with minor aesthetic changes, but you know me. Note the with-types parameter. If I use this command with C-u I get to pick one or more file types to narrow the search down to. I don’t remember if this is possible with counsel-rg, but in large projects it is an absolute must have. Furthermore, the symbol at point, if any, is the default search parameter. Why is this awesome? Keep reading.

With mu-helm-rg in place, I can build a couple of commands to make my life easier.

(defun mu-helm-project-search (&optional with-types)
  "Search in current project with RG.
With WITH-TYPES, ask for file types to search in."
  (interactive "P")
  (mu-helm-rg (mu--project-root) with-types))

(defun mu-helm-file-search (&optional with-types)
  "Search in `default-directory' with RG.
With WITH-TYPES, ask for file types to search in."
  (interactive "P")
  (mu-helm-rg default-directory with-types))

In case you are wondering, mu–-project-root is a trivial function to figure out the current project’s root directory.

(defun mu--project-root ()
  "Return the project root directory or `helm-current-directory'."
  (require 'helm-ls-git)
  (if-let (dir (helm-ls-git-root-dir))
      dir
    (helm-current-directory)))

I don’t need mu-helm-file-search as often as mu-helm-project-search, which is why I’ve bound the latter to M-?. I use this key binding so much it must be a quick one. And this is why having the symbol at point automatically picked up by mu-helm-rg is so important: it just makes the whole search operation as simple as possible.

Oh wait, the symbol at point is not what you are after? No problem, you can start typing whatever you want and have Helm ripgrepping your files.

Notes

  1. Both packages seem hardly maintained these days. 

-1:-- Ripgrepping with Helm (Post)--L0--C0--February 22, 2020 12:00 AM

Irreal: An Org Mode Workflow for Spacemacs

Over at OutOfCheeseError there’s a useful discussion of an Org-mode workflow for Spacemacs. If you’re a member of the Spacemacs sect, you should take a look. Interestingly, the post is part of his .spacemacs file so it’s pretty much always up to date.

Even if you’re not a Spacemacs user, there’s some good ideas and useful information in the post. The author likes fancy text and symbols so he makes heavy use of org-entities and shows some examples. I already knew about org-entities-help but I tend to forget about them. It’s amazing how many there are. If you have a use for these, take a look at John Kitchin’s code to bring up an Ivy list to choose from. There’s also a version that works with Helm.

There’s also a very nice section on how he uses capture templates. He even has one for starting a blog post. Again, aside from the key shortcuts, none of this is specific to Spacemacs so all Emacs users can benefit from reading it, especially if you like to work with nice looking text.

If you’re coming from Vim, you may be surprised at what a powerful workflow Spacemacs and Org can provide. As always with Emacs, it’s all about reducing friction.

-1:-- An Org Mode Workflow for Spacemacs (Post jcs)--L0--C0--February 21, 2020 05:27 PM

Sacha Chua: 2020-02-17 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-02-17 Emacs news (Post Sacha Chua)--L0--C0--February 18, 2020 02:15 AM

Irreal: Emacs Variables

Emacs variables are at once both easier and more difficult than in other languages. On the one hand, Emacs variables are typeless so you can put whatever you like in them and even use the same variable to hold different types at different times. Whether this is a good or bad idea is a religious issue and one I don’t want to litigate here.

On the other hand, Emacs variables can have differing scoping rules that can seem arcane and confusing, especially if you’re used to “normal” languages. The situation is more complicated than in other Lisps because Elisp also has buffer-local-variables and custom-variables with their own scopes and setting rules.

Over at (with-emacs, Clemens Radermacher has a post that gives a nice introduction to Elisp variables. It’s the first in a series that Radermacher is planning on Elisp fundamentals that he is aiming at beginners. One of the hardest things for Lisp n00bs to grasp is the difference between lexical and dynamic scoping. Dynamic variables are (much) more than just global variables and can have some surprising behaviors. As Radermacher says, the situation is exacerbated with Elisp because, for historical reasons, dynamic variables are the default and it’s only recently that lexical variables have been added. Even with their official introduction, lexical variables require some special handling. Radermacher does a pretty job of explaining all this so if you’re new to Elisp, the post is worth reading to help get you started.

Update [2020-02-16 Sun 13:25]: Fixed link to Radermacher’s post.

-1:-- Emacs Variables (Post jcs)--L0--C0--February 15, 2020 06:16 PM

Irreal: When Will They Ever Learn?

Jacob Eisenstein is wondering at the madness that has overtaken the academic world. He wonders why in the world they are depending on someone else’s computer and SaaS to do one of their most important jobs: writing and publishing papers.

For context, the ICML is the International Conference on Machine Learning and the “ICML deadline” refers to last date for submitting papers to the 2020 conference. Eisenstein’s question is well taken. These are computer scientists and using tools like Emacs and Git is certainly within their skill set. Instead they chose to depend on someone else’s computer and software, which inconveniently became inaccessible just prior to the submission date of one of their major conferences.

Most disturbing, though, is the response. I’m sure it’s true that Overleaf is great for collaboration and at least they’re writing in LaTeX—instead of the monstrosity that must not be named—but (1) we’re not talking about social and political scientists here; we’re talking about computer scientists and (2) it’s simply not true that people in the “soft” sciences can’t learn Emacs and Git. Irreal often publishes stories about people in the liberal arts and social sciences doing exactly that.

None of this is to say that computer scientists, let alone social or political scientists, must write in Emacs or collaborate through Git. The point is what it always is when I’m on this particular rant: if you’re committing writing that you care about to a third party for processing and safekeeping, you’re asking for trouble. In this case, the trouble probably wasn’t too severe but as I’ve argued elsewhere, it could have been. The answer is also the same as it always is: use open-source/open-standards software on a computer you control. Anything else is reckless.

-1:-- When Will They Ever Learn? (Post jcs)--L0--C0--February 14, 2020 06:19 PM

Irreal: Org 9.3.6

Bastien lets us know that Org 9.3.6 has been released:

It’s another bug release but the Org 9.4 with new features is coming soon.

-1:-- Org 9.3.6 (Post jcs)--L0--C0--February 13, 2020 04:41 PM

Irreal: Emacs As a Terminal IDE

Palmer Cluff has an interesting post that makes the case for Emacs as a terminal-based IDE. We usually think of IDEs as having a GUI, lots of buttons and menus and of being mouse intensive. Cluff says it doesn’t have to be that way and that Emacs—even in terminal mode—can be a perfectly fine IDE.

His post discusses some of the packages that you’ll need to realize this and at the end he warns us to be ready to spend some time configuring our Emacs to make it the way we want it. Some people are put off by that, I guess, but I think of it as an enjoyable exercise in getting things just the way I want them. The key is that it’s an ongoing process not something that requires you to stop what you’re doing and devote a large block of time to configuring Emacs. I’ve been using Emacs for about 12 years and I’m still tweaking my environment regularly.

Cluff doesn’t make—or try to make—the case that you should prefer terminal Emacs over the GUI version. He merely says that sometimes—when you’re logged into a remote machine, say—it makes sense to use the lighter weight terminal version. Those of us who work with fast and reliable networks are incline to say, “Bah! Just use tramp.” but sometimes we’re using a slow network and the GUI version is just too painful. In those cases, it makes sense to SSH into the remote host and use a terminal Emacs, especially for small tweaks to a large file.

In any event, you’ll probably enjoy reading how Cluff gets his terminal Emacs as close as possible to an IDE.

-1:-- Emacs As a Terminal IDE (Post jcs)--L0--C0--February 11, 2020 06:21 PM

Raimon Grau: spicing up your prompt

I've been using this very silly overloading of the prompt for some time, and even though it's dead simple, it gets to cheer me up sometimes.

On every emacs startup, and every 24 hours, you get  a different message on your prompt when 'm-x'.

Happy hacking,


-1:-- spicing up your prompt (Post Raimon Grau (noreply@blogger.com))--L0--C0--February 10, 2020 06:26 PM

Sacha Chua: 2020-02-10 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-02-10 Emacs news (Post Sacha Chua)--L0--C0--February 10, 2020 04:31 PM

Irreal: Bastien’s Org-mode Tricks

If you follow the Emacs scene, you’ve probably seen some references to Bastien Guerry’s post on Org-mode Features You May Not Know. There’s been several tweets about it and, of course, Sacha covered it in her Weekly Emacs News. If you haven’t already seen it and you’re an Org user you should definitely take a look. There are a lot of useful tips that, as Guerry says, you may not know.

It doesn’t make any sense for me to repeat his list of tips but I do want to mention three that I found especially useful. Two of them I didn’t know before so I found them especially helpful. The first is that if you have speed keys enabled (setq org-use-speed-commands t), and the cursor is at the beginning of a headline, you can narrow to the headline’s subtree by typing s. I’ve already used this a couple of times and it really is useful, especially when you’re dealing with headlines that have nearly identical data.

The second tip I didn’t know about was applying filters to the agenda. If you have the an agenda up and want to look at only certain entries—say to save them to another file—you can type = and a regular expression to see only those entries that satisfy the regex. Another = or a | clears the filter.

Finally, there’s timestamped lists. I first learned about this in one of Rainer König’s videos in his OrgMode tutorial series. The idea is that you can make a list with each entry having a relative timestamp. That’s perfect for taking notes about a lecture or video where you want to refer to specific parts of the lecture or video. You start the list with Ctrl+c Ctrl+x - and new entries with the usual Meta+Return.

There are several other use tips in Guerry’s post so be sure to check it out if you’re an Org user. Some you may have no use for, some you may already know, but others may be both new and useful to you. Definitely recommended.

-1:-- Bastien’s Org-mode Tricks (Post jcs)--L0--C0--February 10, 2020 04:08 PM

Irreal: Zamansky 66: An Eshell Switcher

Mike Zamansky has another video up in his Using Emacs Series. The video is about his trying to use eshell more and building an eshell switcher so that he can easily switch among his active eshell instances. I really like this video because it offers another example of the joys and strengths of what I call “interactive programming.” By interactive programming, I mean the ability to try out small snippets of code, see what they return, and combine these into ever bigger pieces until you have the desired functionality.

Zamansky starts off by mentioning the exec-path-from-shell package, Steve Purcell’s excellent package to make Emacs aware of your PATH and other environment variables. If you’re running on MacOS, this package is pretty much mandatory if you don’t want Emacs to drive you crazy with “Not Found” messages. Zamansky’s use is the first time I’ve seen it used on a Linux system so it has wider applicability than I thought.

The rest of the video shows Zamansky building his switcher app. It’s a wonderful demonstration of how nice Elisp development can be. Even if your Elisp is rusty—as Zamansky says his is—you can experiment by trying various functions until you find one that returns what you need. He literally builds the function brick by brick by continually adding small snippets of code until he has a working function.

I’ve used eshell for a long time but I’ve never felt the need for multiple instances. Perhaps this video will inspire me to expand my horizons. The video is 23 minutes, 43 seconds long so you’ll probably need to schedule some time but if you’re interested in eshell or in Elisp programming, you should definitely find the time to watch it.

-1:-- Zamansky 66: An Eshell Switcher (Post jcs)--L0--C0--February 08, 2020 07:26 PM

Mike Zamansky: Using Emacs 66 - an eshell switcher in elisp

I thought it was time to give eshell in Emacs another try. It has some pretty cool features but for whatever reason, I've never really been able to adopt Emacs as my go to shell. Eshell out of the box is pretty cool but could use some enhancements. When launching at login it doesn't know about the path you set in your .bashrc or .zshrc in my case files. It just seemed to have problems with paths in general but that was fixed with the exce-path-from-shell package.
-1:-- Using Emacs 66 - an eshell switcher in elisp (Post)--L0--C0--February 08, 2020 12:12 PM

Irreal: Finding Intersections Redux

Last month, I published a post on Finding The Intersection of Two Lists. The impetus for the post was an Emacs Stack Exchange question asking if there was a better way to find the intersection of two lists than looping over both of them. I thought putting the entries of the first list in a hash table and checking the entries of the second list against it was a better solution and I wrote some code to check out that hypothesis. You can see the details in the original post.

I got some gentle pushback from two Elisp luminaries, Chris Wellons and Alphapapa. Wellons noted that I could get a small speed increase by using dolist instead of mapc. More importantly, he noted that I should have compiled my code with lexical mode as that makes a large difference in running time.

Alphapapa, commenting as NoonianAtall, noted that I wasn’t eliminating duplicates and pointed me at some macros that make benchmarking this type of thing easier. He published a gist that showed one of those macros in action.

Naturally, I had to check all this out. I wrote a new version of hash-intersection that used dolist instead of mapc and also made a small change (hash-intersection-dedup) to the algorithm so that duplicates were eliminated. Finally, I stole Alphapapa’s version of the code that uses the loop macro instead dolist.

Here’s all the code, including the bit to generate random lists, for reference:

(require 'epdh)
(require 'dash-functional)
(defun make-random-list (n)
  (let ((l nil))
    (dotimes (i n l)
      (push (random 1500) l))))

(defconst lst1 (make-random-list 1000))
(defconst lst2 (make-random-list 1000))

(defun hash-intersection-orig (l1 l2)
  (let ((ht (make-hash-table :test #'equal))
        (acc nil))
    (mapc (lambda (x) (puthash x t ht)) l1)
    (mapc (lambda (x) (if (gethash x ht nil)
                          (push x acc)))
          l2)
    acc))

(defun hash-intersection-dolist (l1 l2)
  (let ((ht (make-hash-table :test #'equal))
        (acc nil))
    (dolist (l l1)
      (puthash l t ht))
    (dolist (l l2)
      (if (gethash l ht nil)
          (push l acc)))
    acc))

(defun hash-intersection-dedup (l1 l2)
  (let ((ht (make-hash-table :test #'equal))
        (acc nil))
    (dolist (l l1)
      (puthash l t ht))
    (dolist (l l2)
      (when (gethash l ht nil)
        (puthash l nil ht)              ;only one to a customer
        (push l acc)))
    acc))

;; From Alphapapa
(defun hash-intersection-loop (l1 l2)
  (let ((ht (make-hash-table :test #'equal) ))
    (cl-loop for e1 in l1
             do (puthash e1 t ht))
    (cl-loop for e2 in l2
             when (gethash e2 ht)
             collect it)))

Now we’re ready to test Wellons’ claims. First, I used the bench-dynamic-vs-lexical-binding macro to measure the difference that compiling with lexical bindings made:

(bench-dynamic-vs-lexical-binding
  :times 100
  :forms (("hash-intersection-orig"   (progn
                                        (defun hash-intersection-orig (l1 l2)
                                          (let ((ht (make-hash-table :test #'equal))
                                                (acc nil))
                                            (mapc (lambda (x) (puthash x t ht)) l1)
                                            (mapc (lambda (x) (if (gethash x ht nil)
                                                                  (push x acc)))
                                                  l2)
                                            acc))
                                        (hash-intersection-orig lst1 lst2)))))
Form x faster than next Total runtime # of GCs Total GC runtime
Lexical: hash-intersection-orig 1.25 0.027208 0 0
Dynamic: hash-intersection-orig slowest 0.033979 0 0

Just as Wellons promised, the lexical version is 25% faster. Next, I compared all the implementations (as well as seq-difference) compiled with lexical bindings. There were a couple of surprises. First, the deduping version ran slightly faster than the dolist version. That was a pretty consistent result across several runs of the comparison. The only reason for it that I can see is that eliminates the push for all the duplicates.

A bit more surprising is that the dolist version ran 28% faster than the mapc version. That seems pretty high but the numbers did jump around a bit between different runs so perhaps it’s just an anomaly. If you want to play around with Alphapapa’s macros (they’re here) that would be a good experiment to run. There are more macros than I’ve mentioned here so they should meet whatever your benchmarking needs are.

(bench-multi-lexical
  :times 100
  :forms (("hash-intersection-orig"   (progn
                                        (defun hash-intersection-orig (l1 l2)
                                          (let ((ht (make-hash-table :test #'equal))
                                                (acc nil))
                                            (mapc (lambda (x) (puthash x t ht)) l1)
                                            (mapc (lambda (x) (if (gethash x ht nil)
                                                                  (push x acc)))
                                                  l2)
                                            acc))
                                        (hash-intersection-orig lst1 lst2)))
          ("hash-intersection-dolist"   (progn
                                          (defun hash-intersection-dolist (l1 l2)
                                            (let ((ht (make-hash-table :test #'equal))
                                                  (acc nil))
                                              (dolist (l l1)
                                                (puthash l t ht))
                                              (dolist (l l2)
                                                (if (gethash l ht nil)
                                                    (push l acc)))
                                              acc))
                                          (hash-intersection-dolist lst1 lst2)))
          ("seq-intersection" (seq-intersection lst1 lst2))
          ("hash-intersection-loop"   (progn
                                        (defun hash-intersection-loop (l1 l2)
                                          (let ((ht (make-hash-table :test #'equal) ))
                                            (cl-loop for e1 in l1
                                                     do (puthash e1 t ht))
                                            (cl-loop for e2 in l2
                                                     when (gethash e2 ht)
                                                     collect it)))
                                        (hash-intersection-loop lst1 lst2)))
          ("hash-intersection-dedup"   (progn
                                         (defun hash-intersection-dedup (l1 l2)
                                           (let ((ht (make-hash-table :test #'equal))
                                                 (acc nil))
                                             (dolist (l l1)
                                               (puthash l t ht))
                                             (dolist (l l2)
                                               (when (gethash l ht nil)
                                                 (puthash l nil ht) ;only one to a customer
                                                 (push l acc)))
                                             acc))
                                         (hash-intersection-dedup lst1 lst2)))))
Form x faster than next Total runtime # of GCs Total GC runtime
hash-intersection-dedup 1.02 0.021943 0 0
hash-intersection-loop 1.09 0.022341 0 0
hash-intersection-dolist 1.28 0.024367 0 0
hash-intersection-orig 315.94 0.031197 0 0
seq-intersection slowest 9.856230 0 0

Finally, I should mention that the macros are part of Alphapapa’s Emacs Package Developer’s Handbook, which has a wealth of useful information—even if you aren’t writing packages—and is definitely worth taking a look at if you haven’t already.

Update [2020-02-08 Sat 11:22]: NoonianAtall (Alphapapa) says that I should have included cl-intersection and -intersection in my comparisons. Fortunately, he’s already done that in the gist that I mentioned so you can check them out there. Cl-intersection is, of course, included with Emacs and -intersection is from Dash which you probably also have since it’s a dependency of many popular packages.

-1:-- Finding Intersections Redux (Post jcs)--L0--C0--February 07, 2020 07:43 PM

Irreal: Restoring the Elfeed Default Filter

I’m a very happy user of Chris Wellons’ excellent RSS reader, elfeed. It has a very powerful search/filter function that lets you control what entries will be displayed and to search for an older entry that you want to revisit. Elfeed has a useful default filter that displays unread items younger than six months old. You can configure the default filter, of course, but the built-in one works well for me so I use it.

The problem is that I can never remember the syntax for the default filter so when I do a search, I always have to look up the incantation to restore the filter to “unread items from the last six months.” A consequence of that is that I didn’t use the search function as often as I otherwise would have. I’ve just discovered that I’ve been doing things the hard way. It turns out that if you clear the current filter, the default is restored. I don’t know if this is a recent addition or if it’s always been that way and I just missed it when I was learning to use Elfeed.

In either case, you can call elfeed-search-clear-filter or use the shortcut c to clear the current filter and restore the default. It’s embarrassing to admit that I was ignorant of a feature that makes the Elfeed experience so much better for this long. If you’re an Elfeed user and didn’t know this, you’re welcome.

-1:-- Restoring the Elfeed Default Filter (Post jcs)--L0--C0--February 06, 2020 04:40 PM

Emacs Redux: Projectile 2.1

Projectile had a pretty quiet year since the massive amount of work that lead to the release of Projectile 2.0 early last year. These days Projectile is both quite mature and feature-full, so there wasn’t really any burning need to add anything new. Still, there’s always some room for improvement. Enter the recently released Projectile 2.1.

The focus in Projectile 2.1 was bug-fixes and small improvements here and there. There’s no few functionality worth highlighting, other than the addition of basic integration with vterm (projectile-run-vterm). You can read all about the changes in the release notes.

Most likely in the future the focus is going to remain on polishing the existing functionality (e.g. bug-fixes, performance improvements) as opposed to adding more features. There are plenty of open issues and help from anyone would be most welcome!

There’s also a lot of work to be done on the documentation side. After launching https://docs.projectile.mx the content there has stayed mostly the same and there’s certainly a lot of ground to cover. At the very least I want to add some animated gifs to the manual this year, so it’s easier for people to understand how to use certain commands.

That’s all I have for you today. I hope you’ll enjoy the latest Projectile. Until next time!

P.S. You can now support my work on Projectile via GitHub Sponsors.

-1:-- Projectile 2.1 (Post Bozhidar Batsov)--L0--C0--February 06, 2020 08:28 AM

Emacs Redux: Still Here

I haven’t had much time for Emacs Redux lately, but I wanted everyone to know that I plan (hope) to go back to writing here at some point. I still love Emacs just as much as always, and my backlog of topics for blog posts keeps growing. I’m still maintaining all of my Emacs open-source projects, although probably not as well as I’ve been doing so in the past. I’m still convinced that:

  • Emacs is Magic
  • Emacs is Power
  • Emacs is Fun
  • Emacs is Forever

Lately most of my blogging has been happening over at Emacs Redux’s sibling blog Meta Redux. Recently I wrote there a few articles that I would have normally published here, if it weren’t for the Meta Advent blogging challenge I participated in. I assume that most of the Emacs Redux readers don’t follow Meta Redux, so I’ll list those articles here:

I hope you’ll find them enjoyable and useful! Until next time!

-1:-- Still Here (Post Bozhidar Batsov)--L0--C0--February 06, 2020 08:15 AM

Irreal: Thought of the Day

From Karl Voit, we have this bit of wisdom:

You can take this in two ways:

  1. Development of Emacs in ongoing and robust.
  2. Emacs is infinitely extensible so even in the absence of point 1, you can make it adapt to new situations.

Regardless, until there is a huge paradigm shift in computing, I expect Emacs will continue to be a relevant and useful tool.

Pouya Abbassi also has some appropriate words along the same lines:

-1:-- Thought of the Day (Post jcs)--L0--C0--February 05, 2020 06:12 PM

Irreal: Zamansky 65: Live Python

Mike Zamansky has another video up in his Using Emacs Series. This time the video is about the live-py-plugin. The link takes you to the master GitHub repository that has code for Emacs, PyCharm, and Sublime Text. There’s a tutorial by the author for using it with Emacs here.

The idea is that as you type Python statements, the results are shown in another window. What gets shown can be quite complex. For instance, the code

for i in range(5):
    print(i+1)

will show the result for each value of i. That’s not too surprising but

def factorial (n):
    if (n==1):
        return 1
    else:
        return n*factorial(n-1)

factorial(5)    

will show you the results of factorial(5), factorial(4),⋯, factorial(1) so it’s a nice way of seeing what your code is doing. Zamansky shows the factorial example and a slightly more complex case of the first example so you can see the live-py results in action. It’s a nice package and worth taking a look at if you’re a Python programmer.

The video is comparatively short—about 8 and a half minutes—so you should be able to fit it in easily.

-1:-- Zamansky 65: Live Python (Post jcs)--L0--C0--February 03, 2020 06:54 PM

Sacha Chua: 2020-02-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-02-03 Emacs news (Post Sacha Chua)--L0--C0--February 03, 2020 04:32 PM

Mike Zamansky: Using Emacs 65 - Live Python

The other day I stumbled upon Emacs's Live Coding plugin. It takes interactive coding up to the next level. Normally, when you code Python, if you're working in a REPL, every time you hit the line you just typed is evaluated. When you're working ina source file, you're just editing until you send the file into a Python interpreter. With this module, your file is continually evaluated as you type and it shows you the results in a side window.
-1:-- Using Emacs 65 - Live Python (Post)--L0--C0--February 02, 2020 05:13 PM

Marcin Borkowski: Encrypted Org-mode journal

I use the Org-mode capturing feature to write a daily journal, where I record various important events in the case I’m going to need the information about them. Some time ago it occured to me that encrypting that journal could be a good idea, so I decided to explore that possibility.
-1:-- Encrypted Org-mode journal (Post)--L0--C0--February 02, 2020 08:38 AM

Irreal: Keeping a Table Header Fixed While Scrolling

Bastien Guerry tweeted about a really awesome new Org-mode feature:

A little further down in the thread, Guerry notes that, “As of this morning, it’s now called M-x org-table-header-line-mode RET” so if you’re living on the edge, use that name instead.

He doesn’t say when it will be officially released but since it’s in Master the next release will probably have it. This isn’t, of course, a huge deal but it does eliminate one annoying aspect of working with tables. Now you can lock the header in place and be able see what each column means. Very nice.

-1:-- Keeping a Table Header Fixed While Scrolling (Post jcs)--L0--C0--February 01, 2020 05:34 PM

(with-emacs: (Almost) All You Need to Know About Variables

This is the start of a series of posts about Emacs Lisp concepts in which I will try to fill some gaps between beginner resources and some more advanced concepts. This post assumes that you are already familiar with common Emacs terminology and know how to read and evaluate basic snippets of Emacs Lisp code. Ideally you should also have heard of variable scope and how it works in some other programming language. The examples also assume you use a fairly recent Emacs version (v.25 or later).

Of course the Elisp manual will tell you everything there is to know but it is designed for people who already know what they are looking for (and it is really great for that). Therefore many people ask for resources explaining Elisp concepts at a higher level and reduce the information to the most useful bits. This is my attempt to bring readers in the position of having a good grasp of the basics so they can use them for their own configuration and have an easier time if they need to look up some detail in the manual.

Global Variables

User options defined via defcustom and variables defined via defvar or defconst are global. One important aspect about variables declared by defcustom or defvar is that reevaluating them won’t reset the variable if it is already bound. For example if you establish a binding for my-var in you init file like this:

(setq my-var nil)

Then evaluating the following form won’t reset the variable to t:

(defvar my-var t)

Note that there is one exception: If you evaluate the above declaration via C-M-x which calls eval-defun the value will be reset to t. This way you can enforce setting the value if you need to. This behavior is intentional: As you might know many features in Emacs are only loaded on demand (autoloaded). If the declarations in those files would reset variables to their default value this would override any settings you made in your init.

User Options

A user option is simply a global variable that was declared with defcustom. Unlike variables declared via defvar such a variable is configurable via the M-x customize interface. As far as I know most people don’t make much use of it because it feels clunky and once you know how to set variables in your init file there is no compelling reason to use it. One detail many users aren’t aware of is that setting user options via customize might execute code, which is sometimes used to run additional setup instructions:

(defcustom my-option t
  "My user option."
  :set (lambda (sym val)
         (set-default sym val)
         (message "Set %s to %s" sym val)))

If you evaluate the above piece of code and change the value using the customize interface via M-x customize-option RET my-option RET, you will see that the lambda gets called and the message in the echo area tells you the symbol and value of the option.

In case you use setq in your int file for changing the value of such an option the setter function will not run. To set such an option correctly via Elisp you need to use the function customize-set-variable. Alternatively there are various versions of csetq macros people use in their configs to automatically take care of this (you can use github code search to discover more sophisticated variants if you like):

(defmacro csetq (sym val)
  `(funcall (or (get ',sym 'custom-set) 'set-default) ',sym ,val))

If you are using use-package, the :custom keyword already handles this for you.

After putting the above code in your init file, you can use csetq to set variables in a way which respect any existing setter functions. You can prove this to yourself by watching the message in the echo area when using this macro to change the option defined above:

(csetq my-option nil)

Dynamic Binding and Lexical Binding

Even if you have already dealt with other programming languages you might never heard of dynamic or lexical binding. This is because most programming languages today use lexical binding and when you learn about variable scope/lookup there is no need to know the difference.

Emacs Lisp is a bit special in this regard because dynamic binding is the default and lexical binding needs to be enabled explicitly. This has historical reasons and in practice you should always enable lexical binding because it is faster and less error prone. To enable it you simply put the following comment line as the first line of your Emacs Lisp file:

;;; -*- lexical-binding: t; -*-

Alternatively you can call M-x add-file-local-variable-prop-line which will insert this line for you when you choose the variable lexical-binding with value t.

When a file with such a special formatted line gets loaded Emacs will set the variable accordingly, which means the code in that buffer will be loaded with lexical binding enabled. Interactively you can use M-x eval-buffer which will also take the lexical binding setting into account.

Now you know how to enable lexical binding let’s examine what those terms actually mean: With dynamic binding the latest binding established during program execution will be used for variable lookup. You can test this by putting the following code in an empty buffer and execute M-x eval-buffer:

(defun a-exists-only-in-my-body (a)
  (other-function))

(defun other-function ()
  (message "I see `a', its value is %s" a))

(a-exists-only-in-my-body t)

You may be surprised to see that the lookup of variable a in other-function will succeed.

If you retry the preceding example with the special lexical-binding comment at the top, you will notice that the code will throw a variable is void error because other-function does not know about the a variable. Coming from other programming languages this is the behavior you would expect.

With lexical binding the scope is defined by the surrounding source code. In addition to performance reasons, experience and time have shown that this behavior should be preferred.

Special Variables and Dynamic Binding

As you might know let is used to temporary establish local bindings:

(let ((a "I'm a")
      (b "I'm b"))
  (message "Hello, %s. Hello %s" a b))

Here is the thing: Variables declared via defcustom, defvar or defconst are so called special variables and those will continue to use dynamic binding regardless if lexical binding is enabled or not:

;;; -*- lexical-binding: t; -*-

(defun some-other-function ()
  (message "I see `c', its value is: %s" c))

(defvar c t)

(let ((a "I'm lexically bound")
      (c "I'm special and therefore dynamically bound"))
  (some-other-function)
  (message "I see `a', its values is: %s" a))

To see both messages in the example above you can switch to the *Messages* buffer using C-h e.

Local variables bound with let or function arguments will follow the lookup rules as defined by the lexical-binding variable, but global variables defined via defvar, defconst or defcustom can be changed deep down the call stack for the duration of the let body!

This behavior allows for convenient adhoc customizations and is often used in Emacs, which isn’t surprising given that Emacs Lisp started out with dynamic binding being the only option. Here is a common example showing how you can temporary write to some read-only buffer:

(let ((inhibit-read-only t))
  (insert ...))

Or another often seen example to perform case sensitive searches:

(let ((case-fold-search nil))
  (some-function-which-uses-search ...))

Dynamic binding allows changing the behavior of functions in ways which the authors of those functions may have never anticipated. It’s a powerful tool and it is a great feature for a program that is designed and used like Emacs.

There is one caveat you should be aware of: It may happen that you accidentally use a local variable name which is a declared as a special variable elsewhere. One trick to prevent such conflicts is to avoid local variables which have dashes in their name. In my current Emacs session this leaves only a handful of potential conflicting candidates:

(let ((vars ()))
  (mapatoms
   (lambda (cand)
     (when (and (boundp cand)
                (not (keywordp cand))
                (special-variable-p cand)
                (not (string-match "-"
                                   (symbol-name cand))))
       (push cand vars))))
  vars) ;; => (t obarray noninteractive debugger nil)

Buffer Local Variables

Each buffer can have a local binding for a variable. This means any variable lookup made while this buffer is current will reveal the buffer local value of that variable instead of the default one. Local variables are an important feature in Emacs, for example they are used by major modes to establish their buffer local behavior and settings.

You have already seen a buffer local variable in this post: The special comment line for lexical-binding which binds it buffer locally to t. In Emacs such buffer local variables defined in special comment lines are also called file local variables.

Any global variable can be shadowed by a buffer local one. Take for example the my-var variable defined in a previous section of this post which you can set locally like this:

(setq-local my-var t)
;; or (set (make-local-variable 'my-var) t)

my-var will be local to the buffer which is current when you evaluate the code above. If you call describe-variable on it, you will see that the documentation tells you the local value and the global one. Programmatically you can check the local value using buffer-local-value and the default one with default-value. To remove the local version you could invoke M-x kill-local-variable.

Another important property you need to be aware of is that once a variable is buffer local, any further uses of setq (while this buffer is current) will continue to set the local value. To set the default value you would need to use setq-default.

Because local variables are meant for buffer customization you will use them most often in mode hooks. A typical example would be something like:

(add-hook 'go-mode-hook
          (defun go-setup+ ()
            (setq-local compile-command
              (if (string-suffix-p "_test.go" buffer-file-name)
                  "go test -v"
                (format "go run %s"
                        (shell-quote-argument
                         (file-name-nondirectory buffer-file-name)))))))

This will set the compile command used by M-x compile for go mode buffers.

Another important aspect is that some variables are automatically buffer local. This means as soon as you setq such a variable this will establish a local binding for the current buffer. This feature shouldn’t be used often because this implicit behavior isn’t nice but if you want you can create such automatically local variables like this:

(defvar-local my-automatical-local-var t)
;; or (make-variable-buffer-local 'my-automatical-local-var)

The variable indent-tabs-mode is a built-in example of this. If you would use setq in your init file to change the value of this variable that wouldn’t affect the default value at all. Only the value for the buffer that is current while loading your init file would be changed. Because of that you need to use setq-default to change the default value of indent-tabs-mode.

Closing Words

I have tried my best to find a balance between details and a more high level overview. Hopefully this helps some souls out there feeling more confident when setting their variables in Emacs. Please leave a comment if you have any questions or suggestions.

-1:-- (Almost) All You Need to Know About Variables (Post clemera)--L0--C0--February 01, 2020 02:00 PM

Irreal: Spacemacs for Writers

Frank Jonen has an interesting GitHub repository to help non-technical people use Spacemacs for writing. Jonen says that his interest in using Emacs for writing and the resulting repository were inspired by Jax Dixit’s talk for the New York Emacs Meetup on Emacs for writers.

As you all know, I’m always interested in the way non-technical people use Emacs so of course I had to check it out. The previous examples of Emacs-for-writers that I’ve written about all involved using vanilla Emacs so this instance is noteworthy for advocating Spacemacs.

The repository consists mainly of Jonen’s .spacemacs configuration file and a README that’s part inspiration and part installation guide. The installation segment covers installing Emacs, Spacemacs, and Jonen’s configuration.

I don’t know if Spacemacs is a good choice for a new user—not a Vim immigrant, where it’s obviously a good choice—but, say, a Word immigrant. Irreal is fortunate in having some passionate Spacemacs users as readers so perhaps one of them can weigh in on whether Spacemacs is the optimal choice for a new, non-technical user. Regardless, it’s a choice that’s working for Jonen and may work for other writers looking to escape the yoke of Word and its evil siblings. If you’re a writer who would like to experience the joy of text-based editing that doesn’t insist you do things its way, take a look at Jonen’s README. Perhaps you’ll be inspired.

-1:-- Spacemacs for Writers (Post jcs)--L0--C0--January 31, 2020 04:22 PM

Irreal: Finding The Intersection of Two Lists

I recently saw an Emacs Stack Exchange Question on how to find the intersection of two lists. The questioner asked if there was a better way than the obvious solution of looping over both lists looking for matches, a \(O(mn)\) solution for lists of size \(m\) and \(n\). The “best” solution was to use the Elisp function seq-intersection, which accomplishes the task in one function call but that under the covers loops over both loops giving it \(O(nm)\) performance

My first thought when I saw the question was to use a hash table to capture the items in the first list and then check the second list against the hash. That would be a \(O(n+m)\) solution but, of course, the multiplicative constants would be much bigger for \(O(n+m)\) than for \(O(nm)\). My gut feeling was that the hash table solution would be a bit faster but as my experiments with palindrome predicates showed, my gut is not particularly reliable.

The only answer was to run some benchmarks. I wrote a bit a Elisp to generate a couple of random lists and a function to find their intersection using the hash table method. The hash-intersection function is pretty simple. It adds each entry of the first list to a hash table with a value of t. Then it checks each entry in the second list to see if it’s in the hash table.

(defun make-random-list (n)
  (let ((l nil))
    (dotimes (i n l)
      (push (random 1500) l))))

(defconst lst1 (make-random-list 1000))
(defconst lst2 (make-random-list 1000))

(defun hash-intersection (l1 l2)
  (let ((ht (make-hash-table :test #'equal))
        (acc nil))
    (mapc (lambda (x) (puthash x t ht)) l1)
    (mapc (lambda (x) (if (gethash x ht nil)
                          (push x acc)))
          l2)
    acc))

Then I ran benchmarks that called hash-intersection and seq-intersection 100 times on the two lists. The benchmark-run macro reports total running time, the number of garbage collections, and the time taken by garbage collection.

(benchmark-run 100 (hash-intersection lst1 lst2))
0.081114 0 0.0
(benchmark-run 100 (seq-intersection lst1 lst2))
8.2707 0 0.0

As you can see, there was no garbage collection. Surprisingly, the hash-intersection function was about 100 times faster, which is much faster than I expected. I thought there might be garbage collection with the hash table method but there wasn’t—perhaps there would be with larger lists.

Regardless of the garbage collection results, the hash table method certainly takes more memory. Even so, the speed results suggest that for most reasonable inputs, the hash table method is a good choice. With shorts lists of 8 elements, both methods took about a microsecond for a single run so there doesn’t appear to be a penalty for short lists either.

-1:-- Finding The Intersection of Two Lists (Post jcs)--L0--C0--January 29, 2020 05:35 PM

Irreal: Org Mode 9.3.2

Bastien writes that Org Mode 9.3.2 has been released. It’s a bug release so no new features but if you are experiencing problems with Org, you should consider upgrading. Even if you aren’t seeing problems, it’s probably a good idea to update.

Correction

In Sunday’s post on Undo Region, I said that selective undo did not appear to work with undo-tree. One of Irreal’s intrepid readers, hjmr, discovered that it did work in older versions of undo-tree and that in the latest version it still works but you have to enable it. I’ve added an update to the Undo Region post that gives the spell for making it work but because there appears to be a lot of interest in selective undo, I wanted to make sure all of Irrealdom knows that you can use it with undo-tree.

-1:-- Org Mode 9.3.2 (Post jcs)--L0--C0--January 28, 2020 05:19 PM

eRambler (posts tagged "emacs"): Iosevka: a nice fixed-width-font

Iosevka is a nice, slender monospace font with a lot of configurable variations. Check it out: https://typeof.net/Iosevka/

-1:-- Iosevka: a nice fixed-width-font (Post Jez Cope)--L0--C0--January 28, 2020 11:26 AM

Sacha Chua: 2020-01-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-01-27 Emacs news (Post Sacha Chua)--L0--C0--January 28, 2020 12:33 AM

Bastien Guerry: Org-mode features You May Not Know

When I meet fellow orgers, I occasionally use some of the features below and quite often, my interlocutor does not know some of them. Do you know them all? If you think of a secret Org weapon that is not listed here, please send me an email, I will consider adding it to the list. The features listed below are all available with Org 9.3 and later. Check your version with M-x org-version RET and please read Org's manual and browse Worg if you want to explore more.
-1:-- Org-mode features You May Not Know (Post)--L0--C0--January 27, 2020 12:00 AM

Irreal: Undo Region

Here’s an Emacs feature that I—and, apparently, many others—didn’t know about:

That’s a fantastic time and effort saver when you want to undo a change that’s not at the tip of your undo tree.

Sadly, as far as I can tell, it doesn’t work with undo-tree, a package that I’m not willing to give up. For those of you not using undo-tree, you should try this out. It’s built into the Emacs undo system so there’s nothing to install.

According to the Emacs Manual, if you aren’t in Transient Mark mode you will need a prefix argument to undo. If, like most people these days, you are using Transient Mark mode, you won’t need the prefix argument.

Update [2020-01-27 Mon 12:03]: Hjmr reports that it will work with undo-tree if you set undo-tree-enable-undo-in-region to t. I’ve verified that this works so we can have the best of both worlds: undo-tree and selective undo.

-1:-- Undo Region (Post jcs)--L0--C0--January 26, 2020 04:51 PM

Irreal: Makefiles for Elisp

Chris Wellons has another great post over at Null Program. This post discusses how he uses makefiles to build his Emacs packages. If you’re like most Elisp programmers, you probably write only small bits of Elisp to add to your init.el and, of course, that doesn’t require a makefile.

Wellons, on the other hand, is writing Emacs packages for others to use. The majority of those consist of a single file but there’s still a good reason to use a makefile. In the first place, Wellons has tests for his packages and he has rules to run those tests in the package’s makefile. That makes it easy to run the tests after every update. The other issue is subtler but still important. As Wellons says, the Elisp compiler may be dumb but it does do static analysis and it’s a useful way of finding problems before they manifest themselves at run time. Therefore, the default rule in his makefiles is to compile the Elisp files.

Most of the post documents the conventions that he uses in his makefiles. He shows the Makefile for each of his projects so you can see real examples of what he does. The other important point is that Wellons makes a point of writing portable makefiles. That means they will work with any make adhering to the POSIX make standard, not just GNU make. If you’re writing software that will be used in a variety of Unix/Linux systems, this can make your life a lot easier because you can use the system make rather than installing GNU make.

Besides serving as a good example of using makefiles for Elisp projects, Wellons’ post is also a nice tutorial on makefiles. If you don’t know anything about make, it won’t help you much but if you’re an occasional user, it’s an excellent reminder of the important points. If you’re a beginner, you should check out his make tutorial.

If you’re writing Emacs packages or you’re just in need of a booster shot for your make-foo, this post is definitely worth your time. As usual, Wellons presents useful information in an interesting way.

Update [2020-01-24 Fri 14:26]: find → finding

-1:-- Makefiles for Elisp (Post jcs)--L0--C0--January 24, 2020 04:55 PM

emacsair: Magit-Section as a stand-alone package

Magit-Section as now available as a stand-alone package.
-1:-- Magit-Section as a stand-alone package (Post)--L0--C0--January 23, 2020 08:00 PM

Raimon Grau: Latest Awesome Emacs Developments

In the last month or so, a great wealth of new Emacs stuff has been developing in both core and community.

We know that in free software projects (communities, that is) some branches might take a long time to develop, but some others

tree-sitter: Integrating this project opensourced by github. This could mean a new way of syntax highlight that doesn't drag, smarter indentation, and completions. Eli mentioned it in the emacs mail list and people are looking into it.

Yet another jitter, by Andrea Corrallo.  Another approach to make emacs' elisp code run faster.  There have already been many attempts to this (Guilemacs, "El Compilador", and others). Will this be the one?  From the highest level perspective, I like "el compilador" the most, because it's kinda smalltalkish, but hey,... I don't have the knowledge to hack on any of those, so whatever the wizards pick, I'm good with it. Also, see mailing list.

SystemE : Replace Systemd with runit? nope, geekier.

Emacs Application Framework because you can also have proper gui controls.
 
Animations in elisp (text)

OM. higher level org parsing

doct declarative org-capture templates.
-1:-- Latest Awesome Emacs Developments (Post Raimon Grau (noreply@blogger.com))--L0--C0--January 23, 2020 10:21 AM

Irreal: Karl Voit on Starting to Use Org-mode

Karl Voit has a nice post in his Using Org Mode Features series. It’s advice on how to start using Org-mode. Org-mode is large and complicated and can seem intimidating. That leads many people to start with someone else’s configuration. I did that and can testify that it’s a big mistake.

I was completely awed by Bernt Hansen’s Org Mode – Organize Your Life In Plain Text!. I thought it was brilliant and wanted to recreate his wonderful workflow for myself. It didn’t work out well. I had all these capabilities enabled and didn’t understand how to use any but the simplest.

That brings us to to Voit’s first point: start simple. I always advise people to start out with just headers, lists, and tables and to add other features as you find you need them. Whatever you need is almost certainly there but there’s no point in enabling it and adding the extra complexity until you really need it. Voit agrees with that and his own list of things to start with is similar to mine. The point, though, is to start with a minimal set of features.

Voit also suggests starting out with a single file. That’s really good advice. It’s easy to add new files later if you need them but it’s really hard to combine several files into one if you discover that’s your best strategy. This is in keeping with Voit’s advice to not overthink your file structure. It’s certainly going to change as your workflow does so your best strategy is to hone it as you go along rather than trying to get it perfect from the beginning.

Voit also discusses learning Org, discovery, and the Org-mode community. It’s a good post and definitely worth reading if you’re thinking about starting to use Org or are just beginning your journey.

-1:-- Karl Voit on Starting to Use Org-mode (Post jcs)--L0--C0--January 22, 2020 04:52 PM