Irreal: Generating Gantt Charts with Org-mode

Perhaps because I’ve always worked for smaller organizations, I’ve never had to deal with Gantt charts. I’ve always considered them yet another management fad but that may be due to ignorant prejudice. In any event, lots of people use them and find them useful.

The other day I saw a pointer to a recent video on generating Gantt charts with Org-mode. It turns out to be pretty easy. Once you get the start and end dates into an Org table it’s just a matter of invoking a bit of gnuplot code from a source block to generate the chart.

As I said, I don’t have much interest in Gantt charts but I do like reading about leveraging Org-mode to accomplish tasks that used to take dedicated applications. The video is 13 minutes, 11 seconds so it should be easy to fit it in. It’s worth taking a look at if only to see how versatile Org-mode and Emacs can be.

-1:-- Generating Gantt Charts with Org-mode (Post jcs)--L0--C0--November 15, 2019 04:18 PM

Irreal: Emacs Resources for Writers

Recently, James Gill tweeted about a collection of Emacs resources for writers that he’s curated into a GitHub repository. There are two parts to the collection:

  1. Tips and examples for writing with Emacs, and
  2. Writing a book with Emacs.

As you’d expect, most of the articles are about leveraging Org-mode for writing. That’s no surprise, of course, because Org excels at that. Indeed, almost any type of writing from memos or blog posts—such as Irreal’s—to journal articles or books is easily accomplished with Org. I’ve reached the point were virtually everything I write is done with Org-mode.

Sadly, the literary writing market runs on Word so if that’s your niche, you’re going to have to deal with conversion. Org, of course, has built in tools for that and if those don’t meet your needs, the excellent Pandoc almost certainly will.

If you’re a writer who’d like to escape from the pain that is Word and give Emacs a try, be sure to read the articles in Gill’s list. I’ve discussed several of them in Irreal previously but a few are new to me. A handful of the resources are videos but most are short blog posts or articles that are easy and quick to read.

It’s not always obvious how to use Emacs for writing effectively so the articles and videos collected by Gill, which distill a lot of hard won wisdom, can be a real help.

-1:-- Emacs Resources for Writers (Post jcs)--L0--C0--November 13, 2019 03:55 PM

Marcin Borkowski: Diffing buffer fragments

While working on a certain project, I needed to check the differences between two text fragments. We all know and love diff, but it operates on files, and what I had was two fragments of two files (or sometimes even of one file) which I wanted to compare. There are a few solutions to this problem, but they seemed too complicated for me.
-1:-- Diffing buffer fragments (Post)--L0--C0--November 11, 2019 06:49 PM

sachachua: 2019-11-11 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:-- 2019-11-11 Emacs news (Post Sacha Chua)--L0--C0--November 11, 2019 04:33 PM

Alex Bennée: dired-rsync 0.5 release

If you’ve been running from MELPA you will have had all these features already but it was certainly overdue a stable tagging. The commit history shows a lot of faffing around getting the CI working again. However there are a bunch of customisation tweaks exposed as well as support for remote-to-remote rsync support (with a very ugly port-forward hack). From the NEWS file:

  • Big CI clean-ups (dropped emake, added Cask)
  • smarter modeline status (show R:n% when one job running)
  • make dired-rsync process dest with expand-file-name
  • we now support remote to remote with an ugly port forward hack
  • prompt the user for a passphrase if we detect stall in process
  • add some basic ert tests
  • new customisation option dired-rsync-source-files
  • new customisation hook dired-rsync-failed-hook

Happy file syncing 😉

-1:-- dired-rsync 0.5 release (Post Alex)--L0--C0--November 10, 2019 07:42 PM

Raimon Grau: Emacsconf 2019!

Emacsconf last Saturday was a blast! I planned to attend for a couple of talks and ended up staying the whole day!

Quite interesting talks, made by passionate contributors, cutting BS to 0, and somehow the talks were broad enough to take something from each one of them.

Even digressions in the irc channels were also interesting. Of course, the tribe that joins a saturday on an irc channel and a video streaming of emacs stuff for 9 hours, we're more than ok to discuss about window managers, programming languages, and all sorts of emacsy geekyness not entirely related with the talks. There was a very good vibe there.

A couple of talks focused more on the meaning of emacs as an FSF flagship, and the political meaning of the project. Very important to note that in a gathering of emacsers. I sometimes forget that emacs is as much of a software artifact than a political statement.

Jitsi behaved ok for 70% of the time, but the first 30% was a bit worrisome.  Connection dropping and audio cutting was a bit frustrating. The organizers did a great job solving those (I can imagine the stress), and they had the "recorded lightning talks" card up their sleeve.  Kudos to them, and to JohnW who got most of the jitsi difficulties in his turn :/.  Luckily he was calm and patient enough to flyby those hiccups and the message went through ok.

Annnnd the closing keynote.  That one gave some food for thought...  Better html support, different implementation language (learning from Remacs?) different extension language, looking at vscode in depth, attracting contributors, bug reporting....

Thank you everyone involved in one way or another. Organizers, speakers and attendees.  I had a great Saturday :)
-1:-- Emacsconf 2019! (Post Raimon Grau (noreply@blogger.com))--L0--C0--November 06, 2019 11:41 AM

codingquark: EmacsConf 2019 - Distributed!

After 3 years of inactivity, motivated emacs hackers decided that it is time to revive the conference. And this time such that everyone could participate!

Jitsi was used to stream the talks, IRC was used to chat real-time and chaospad to share the notes. Thus, the entire conference was organised using libre software exclusively. Quite a thing!

This distributed approach had its positives and negatives. I would like to talk about both. Being online, it opens the doors to anyone who wants to participate. No physical and economical barriers. This also helps diversity. People from a vast background and knowledge can easily feel at home. It also allows for better moderation on how participants want to spend their time during the breaks & during talks they do not want to attend, not to mention administrative control.

With all these and more benefits, there are disadvantages. Our tech is not yet advanced enough that we can replace physical presence. This means you don’t actually feel like you’ve “met” anyone. Since nobody is actually “present”, it is easy to get distracted or take up parallel work. Let’s be honest, we don’t get to visit new places and have fun. The advantages and disadvantages - strike a balance for yourself.

During the conference, it was great fun to talk to people as the speaker was streaming over jitsi. So many people chime-in real time at various points! Speakers may or may not choose to follow IRC during the talk as well. Now, it can distracting to follow running discussions and talks at the same time, but it surely adds to the fun. I ended up /ignoreing a couple of accounts, but overall it was very nice.

As all software goes, jitsi kept bugging out. Organizers had to work extra hard to ease things out. One of the best moves in hindsight was to have prerecorded talks. If the speaker could not get their setup to work, organizers could simply stream the recorded talks. During the times when audience is waiting for jitsi to stop being a bitc crazy, lightening talks were streamed. This allowed people to stay engaged. IRC - as always - was flawless.

What can we do to improve the conference for the next year? Fix jitsi. Seriously. Then, have more satellite conferences so that people can gather locally. Volunteer for the team - never enough of those, eh? Although IRC was not too noisy, there were times when too many separate active discussions started taking place. Perhaps we can do something about that. We also need to find some way so that well-known public speakers don’t have to think twice before participating in online distributed conferences.

Lastly, thanks a lot to the organizers for their amazing work and the civil participants for making it a success. The speakers were fantastic, open to discussions & QA and patient. Thanks a ton!

See you next year!

-1:-- EmacsConf 2019 - Distributed! (Post)--L0--C0--November 05, 2019 12:30 AM

Marcin Borkowski: Starting Emacs with custom configuration directory

The usual thing people are told to do when debugging/isolating Emacs problems is to say emacs -Q, that is, start Emacs without reading in any configuration. Sometimes, however, this may not be a good idea. When there is some problem with packages, however, we may actually want to load some things, like a minimal set of packages if we suspect they do not work together. Of course, what we don’t want is changing our configuration.
-1:-- Starting Emacs with custom configuration directory (Post)--L0--C0--November 04, 2019 08:12 PM

Grant Rettke: Some Pretty Good Configuration Options To Copy

Here are some pretty good configuration options to copy. Seriously they are pretty good and very objective. I tried to keep as little subjective preference in there. Although I definitely failed at least partly, there is good stuff in there. And it is super short anyway.
-1:-- Some Pretty Good Configuration Options To Copy (Post grant)--L0--C0--November 04, 2019 05:53 PM

sachachua: 2019-11-04 Emacs news

EmacsConf was a blast! Recordings may be available by next week – stay tuned. Thanks to everyone who helped make it happen!

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:-- 2019-11-04 Emacs news (Post Sacha Chua)--L0--C0--November 04, 2019 04:32 PM

Manuel Uberti: Thirty straight days

It’s already been a month since I moved from package.el to straight.el, and if it wasn’t for the constant fiddling with my Emacs configuration, I would have hardly noticed the differences in package management. A proof of the solid work behind straight.el, sure, but also a demonstration of how painless package management can be for someone who bypasses the provided UI and relies on use-package snippets to install and setup their packages.

However, with straight.el a new approach to updates is needed. First of all, I compulsively track the state of the packages I have installed, and I tend to update all of them every morning. This is an operation that follows the pulling of the latest developments on the Emacs master branch.

On the one hand, this approach could lead to breaking changes and tears of sadness. On the other hand, I like to report bugs as soon as I discover them, and hopefully help the great developers out there who make my text editing a wonder.

Considering how vital to my computing Emacs is, this may sound like complete madness, I know. In my defence, I mostly rely on stable and long-term support software on my computer. Emacs is just the special kind of madness that drags me to it in spite of the risks. Furthermore, as I wrote last time, straight.el makes it easier to revert to a previous unbroken version of a package, so I can find a functional environment without too much of a hassle.

In my package.el days, package updating was handled by Paradox. In a matter of a couple of key bindings, it took care of notifying me about new versions and installing the selected updates. straight.el is less fancy, though. It provides the necessary commands to install and update a package, as well as the big brother that will pull every package in, but all the UI it offers is the user’s completing-read framework—ivy-read in my case.

Well, like the first line of the README says, straight.el is a tool for the Emacs hacker, so let’s play with it. All I had to do to get a more interactive user experience when updating packages was devising a small wrapper around straight.el’s facilities.

(defun mu-straight-pull-or-prune (&optional prune)
  "Update all available packages via `straight'.
With PRUNE, prune the build cache and the build directory."
  (interactive "P")
  (if prune
      (when (y-or-n-p "Prune build cache and build directory?")
        (straight-prune-build-cache)
        (straight-prune-build-directory))
    (when (y-or-n-p "Update all available packages?")
      (straight-pull-all))))

(bind-key* "<f7>" #'mu-straight-pull-or-prune)

Pretty straightforward, isn’t it? (Pun intended.)

-1:-- Thirty straight days (Post)--L0--C0--November 02, 2019 12:00 AM

Bryan Murdock: Playing With Pijul

I tried pijul out a while back, I can't remember how long exactly, and it was not ready for prime time. Today I tried it out again and I have to say, it feels pretty polished. I have a couple problems though.

One is, how do I un-apply patches? What I really want is the git equivalent of doing a git checkout  to go to an older revision (and from there build and test, or even just look around at the files). You could do a series of pijul unrecord and keep answering yes to all the patches you want to remove, and then do a pijul revert but that seems tedious and weird. I don't want to delete the patches, I just want to un-apply them for a bit. Is that possible?

The other problem I have is similar to this one. pijul promises better cherry picking than git, since it just records patches not snapshots of the repo. However, it has no cherry-pick command. It does have a patch command and an apply command that I've been trying to use to manually cherry-pick, but it's not working. For example, if I make 3 simple changes to a file (add three new lines, one after another), and record a patch for each change, is there a way to cherry pick a patch from the middle? It seems not because no matter what I try it complains that the patch in the middle is missing a dependency. I can't cherry pick just the first and third patches either. I can't even do it manually by creating traditional patches and using patch(1) because pijul doesn't output diffs/patches in normal pactch/diff format.

I feel like maybe I'm missing something here.
-1:-- Playing With Pijul (Post Bryan (noreply@blogger.com))--L0--C0--October 29, 2019 03:11 AM

(with-emacs: Prefix command completion

As a reader of this blog you probably know about which-key. It is a great package which helps discovering and remembering keybindings. One thing I miss, is the option to choose candidates via completion, which is the goal of this post.

When you press C-h after a prefix key, Emacs displays a buffer containing all the bindings under that prefix. The command which gets called is determined by the variable prefix-help-command. Which-key makes use of this variable, too. It uses the initial value as a fallback so the variable needs to be set before which-key-mode is activated:

(setq prefix-help-command #'which-key-M-x-prefix+)
(which-key-mode 1)

The code of this post makes use of internal which-key functions and is tightly related to it, so I will keep the which-key- prefix and add a + suffix. This approach is what I’m using for all my personal package extensions. Using the same "name space" has some nice benefits for search and completion and the unusual suffix avoids potential name clashes.

(defun which-key-M-x-prefix+ (&optional _)
  "Completing read and execute command from prefix-map.

This command can be used as `prefix-help-command'. The optional
argument is ignored and only for compatability with
`which-key-C-h-dispatch' so this command can be bound in
`which-key-C-h-map', too."
  (interactive)
  (let* ((evs (cond ((which-key--current-prefix)
                     (which-key--current-key-list))
                    (t
                     (butlast (append (this-command-keys-vector) nil)))))
         (key  (and evs (apply #'vector evs))))
    (which-key-M-x+ key)))

(defun which-key-M-x+ (&optional key)
  "Completing read command and execute it.

Only commands which are bound to keys are considered. If KEY is
given it should be the prefix-key for which commands should be
completed. Otherwise read command from top-level. "
  (interactive)
  (let ((cmd (which-key--completing-read-cmd+ key)))
    (when (commandp cmd)
      (which-key--execute-cmd+ cmd))))

(defun which-key--completing-read-cmd+ (&optional prefix)
  "Completing read command for PREFIX.

Read commands for PREFIX or top-level if PREFIX not given."
  (which-key--hide-popup-ignore-command)
  (let ((desc
         (completing-read
          (if prefix
              (format "Execute (%s): " (key-description prefix))
            "Execute: ")
          (mapcar #'which-key--completing-read-format+
                  (which-key--get-current-bindings prefix)))))
    (intern (car (split-string desc)))))

(defun which-key--execute-cmd+ (cmd)
  "Execute command CMD as if invoked by key sequence."
  (setq prefix-arg current-prefix-arg)
  (setq this-command cmd)
  (setq real-this-command cmd)
  (command-execute cmd 'record))

(defun which-key--completing-read-format+ (bnd)
  "Format binding BND for `completing-read'."
  (let* ((key (car bnd))
         (cmd (cdr bnd))
         (desc (format "%s (%s)" cmd
                       (propertize key 'face 'which-key-key-face))))
    (which-key--maybe-add-docstring
     (format "%-50s" desc) cmd)))

After adding the above code to your Emacs, you should be able to press a prefix key and invoke the command completion with C-h. If the which-key popup is already showing you need to press it twice, because it uses C-h for its own paging commands, too. You can also complete commands from top-level by calling the which-key-M-x+ command.

-1:-- Prefix command completion (Post clemera)--L0--C0--October 18, 2019 03:00 PM

(with-emacs: Prefix command completion

As a reader of this blog you probably know about which-key. It is a great package which helps discovering and remembering keybindings. One thing I miss, is the option to choose candidates via completion, which is the goal of this post.

When you press C-h after a prefix key, Emacs displays a buffer containing all the bindings under that prefix. The command which gets called is determined by the variable prefix-help-command. Which-key makes use of this variable, too. It uses the initial value as a fallback so the variable needs to be set before which-key-mode is activated:

(setq prefix-help-command #'which-key-M-x-prefix+)
(which-key-mode 1)

The code of this post makes use of internal which-key functions and is tightly related to it, so I will keep the which-key- prefix and add a + suffix. This approach is what I’m using for all my personal package extensions. Using the same "name space" has some nice benefits for search and completion and the unusual suffix avoids potential name clashes.

(defun which-key-M-x-prefix+ (&optional _)
  "Completing read and execute command from current prefix map.

This command can be used as `prefix-help-command'.

The optional argument is ignored and only for compatability with
`which-key-C-h-dispatch' so this command can be bound in
`which-key-C-h-map', too."
  (interactive)
  (let* ((evs (if (which-key--current-prefix)
                  (which-key--current-key-list)
                (butlast (append (this-command-keys-vector) nil))))
         (key (apply #'vector evs))
         (map (key-binding key)))
    (which-key--execute-binding+ map (key-description key))))

(defun which-key--execute-binding+ (map &optional prefix)
  "Completing read command from MAP and execute it.

If PREFIX is given it should be a key description which will be
included in the prompt."
  (let ((cmd (which-key--completing-read-cmd+ map prefix)))
    (when (commandp cmd)
      (which-key--execute-cmd+ cmd))))

(defun which-key--completing-read-cmd+ (map &optional prefix)
  "Completing read command from MAP.

Include PREFIX in prompt if given."
  (which-key--hide-popup-ignore-command)
  (let* ((desc
          (completing-read
           (if prefix
               (format "Execute (%s): " prefix)
             "Execute: ")
           (mapcar #'which-key--completing-read-format+
                   (which-key--get-keymap-bindings map 'all)))))
    (intern (car (split-string desc)))))

(defun which-key--execute-cmd+ (cmd)
  "Execute command CMD as if invoked by key sequence."
  (setq prefix-arg current-prefix-arg)
  (setq this-command cmd)
  (setq real-this-command cmd)
  (command-execute cmd 'record))

(defun which-key--completing-read-format+ (bnd)
  "Format binding BND for `completing-read'."
  (let* ((key (car bnd))
         (cmd (cdr bnd))
         (desc (format "%s (%s)" cmd
                       (propertize key 'face 'which-key-key-face))))
    (which-key--maybe-add-docstring
     (format "%-50s" desc) cmd)))

After adding the above code to your Emacs, you should be able to press a prefix key and invoke the command completion with C-h. If the which-key popup is already showing you need to press it twice, because it uses C-h for its own paging commands, too.

-1:-- Prefix command completion (Post clemera)--L0--C0--October 18, 2019 03:00 PM

Grant Rettke: Use all of Emacs’s modifiers on macOS with various keyboards.

When non-Emacs users observe Emacs users laboring over their key binding configuration their typical range of reactions include finding it to be interesting, surprising, remarkable, strange, weird, incredible, striking, bizarre, deviant, eccentric, freakish, monstrous, incomprehensible, inconceivable, incredible, unimaginable, and unthinkable. With that range reactions in mind it is self-evident that if you are reading this … Continue reading "Use all of Emacs’s modifiers on macOS with various keyboards."
-1:-- Use all of Emacs’s modifiers on macOS with various keyboards. (Post grant)--L0--C0--October 17, 2019 03:56 AM

emacspeak: Meta-Programming In Emacs Using Defadvice


Meta-Programming In Emacs Using defadvice

1 Introduction

This blog article Meta Programming In Python reminded me to write up
the equivalent for Emacs Lisp.
Decorators in Python enable you to modify the vehavior of existing
functions without changing the original function; Advice in Lisp
which traces back to the 80's enables similar functionality —
incidentally, Advice was the inspiration behind Aspect Oriented
Programming in Java.


2 Advice And Emacs Lisp

Advice came to Emacs lisp in the summer of 1994, when module
advice.el shipped as part of Emacs 19.23. A few weeks later, a
colleague at work (Win Treese) wrote up a simple example that added
a before advice to the vc-checkin functions of the time to create
an RCS subdirectory if one did not exist. This was such a neat
trick that all of us in our Lab adopted it — and having random
RCS*,v* files lying around in the working directory became history.


3 Emacspeak And Advice — Fall 1994

And then I decided to make Emacs speak to me.
Module advice.el provided the ability to add before, after, or
around advice. In brief, Emacspeak used these three classes of
advice as follows:


  1. Speak line moved to after next-line and previous-line — add
    an after advice that called function emacspeak-speak-line.
  2. Speak character being deleted — Add a before advice that
    speaks the character under point before it is deleted.
  3. Get various types of completion spoken — Add an around advice
    that remembers the current context, calls the original function
    being adviced, and finally speak the current context that now
    reflects the completion.

The rest of the story was written up a few years ago as Emacspeak At
Twenty
. Fast-forwarding 25 years, present versions of Emacs still
include module advice.el as well as an arguably simplified front-end
implemented by module nadvice.el that enables the definition of
custom functions that are then attached to existing code via advice.


4 References

  1. Emacspeak At Twenty, Looking Back, Looking Forward.
  2. emacspeak: The Complete Audio Desktop. Chapter from the book
    entitled Beautiful Code, OReilly.

-1:-- Meta-Programming In Emacs Using Defadvice (Post T. V. Raman (noreply@blogger.com))--L0--C0--October 16, 2019 09:33 PM

(or emacs: Ivy 0.13.0 is out

Intro

Ivy is a completion method that's similar to Ido, but with emphasis on simplicity and customizability.

Overview

The current release constitutes of 183 commits and 3 months of progress since 0.12.0. Many issues ranging from #2153 to #2278 were fixed. The number of people who contributed code as grown to form 148 to 160. Thanks, everyone!

Details on changes

Changelog.org has been a part of the repository since 0.6.0, you can get the details of the current and past changes:

Highlights

Many improvements are incremental and don't require any extra code to enable. I'll go over a few selected features that require a bit of information to make a good use of them.

New bindings

  • counsel-find-file
    • ~~ to move to the local home directory from remote or /sudo::.
    • / RET ~ achieves the same thing, but is longer.
    • M-o R calls find-file-read-only.
  • counsel-git-grep
    • C-x C-d to switch the current directory.
  • swiper-isearch
    • M-o w to copy the current line and go back to where you started.

New features

counsel-package

The idea of counsel-package is to install and remove packages with a single binding:

(global-set-key (kbd "C-c P") 'counsel-package)

But if the package contents weren't up to date, a separate M-x package-refresh-contents had to be triggered, which was an annoying overhead. Now counsel-package will look at the time stamps of the appropriate archive-contents files, and call package-refresh-contents if the timestamp is outdated by more than 4 hours.

counsel-M-x

Some commands are intended to be called only via their key binding. Make them disappear from counsel-M-x like this:

(put 'counsel-find-symbol 'no-counsel-M-x t)

counsel-rg

The default setting of ivy-case-fold-search-default is 'auto, which means:

  • the input "emacs" matches "emacs", "EMACS", and "Emacs"
  • the input "Emacs" matches only "Emacs"

This now also applies to counsel-rg: Ivy will pass the -i flag to ripgrep appropriately, based on ivy-case-fold-search-default. You should remove the -S flag from counsel-rg-base-command if you customized it.

ivy-update-candidates

This is a new API for asynchronous calls. To use it, pass to ivy-read: :dynamic-collection t, and a collection function that takes a user input string, starts some asynchronous process based on that input, and returns 0. The 0 return result tells Ivy that no candidates were returned; instead, ivy-update-candidates is used in the async callback.

See counsel-google for a reference implementation.

ivy-use-virtual-buffers

You can now choose between: recent files, or bookmarks, or both, or none. Don't forget that counsel-set-variable makes it very easy to set customization options.

New Commands

I have put these separately so they don't get lost in the crowd. Be sure to try them out.

  • counsel-buffer-or-recentf - list buffers visiting files (highlighted) then the recentf file list.
  • counsel-fonts - show a list of all supported font families for a particular frame.
  • counsel-google - asynchronously query the Google predictive search API.
  • counsel-major - switch major-mode.
  • counsel-slime-repl-history - browse SLIME REPL history.

Outro

Again, thanks to all the contributors. Happy hacking!

PS. Thanks to everyone who supports me on Liberapay and Patreon!

I am now also on Github sponsors, which is an interesting new effort by Github. The cool thing is that's more integrated with Github, there are less transaction fees, and Github matches every donation for up to $5000 for a whole year. Please consider joining there, since every $1 per month that you donate is doubled by Github.

-1:-- Ivy 0.13.0 is out (Post)--L0--C0--October 15, 2019 10:00 PM

Saurabh Kukade: Meta-programming In Python

“Perfection is achieved not when there is nothing more to add, but rather when there is nothing more to take away.” – Antoine de Saint-Exupery Recently I encountered with very fascinating concept which is “Meta-programming in Python”. I would like to share my findings about this topic in this article....
-1:-- Meta-programming In Python (Post)--L0--C0--October 13, 2019 06:30 PM

Timo Geusch: [HOWTO] Installing Emacs 26.3 on Ubuntu or XUbuntu 19.04

My previous instructions for installing a newer Emacs version on Ubuntu still work. Ubuntu (and in my case, XUbuntu) 19.04 ships with Emacs 26.1 out of the box. As usual I want to run the latest version – Emacs 26.3 Read More

The post [HOWTO] Installing Emacs 26.3 on Ubuntu or XUbuntu 19.04 appeared first on The Lone C++ Coder's Blog.

-1:-- [HOWTO] Installing Emacs 26.3 on Ubuntu or XUbuntu 19.04 (Post Timo Geusch)--L0--C0--October 13, 2019 04:19 PM

Manuel Uberti: Straight ahead

I have never found Emacs appealing without external packages. From the colour theme to the best Git UI one could ask for, I can’t imagine using Emacs without external packages. The built-in package.el has served me well for a long time. Configured with the usual package archives, it has offered me easy access to new packages and updates for the currently installed ones.

However, digging a little deeper reveals some of its shortcomings. For instance, downgrading has to be done manually, because package.el gives access only to the latest version of a package. This also means it is impossible to get a specific version of said package without getting the source and loading it by yourself.

As you install and configure more and more tools to enhance your Emacs experience, you are adding layers of complexity. Dependencies are pulled in and new releases could bring breaking changes: either you never upgrade your packages, or you learn to live on the bleeding edge. I love that edge as much as your next Emacs hacker, but to approach it with steadiness I need more control over the packages I use.

This is where straight.el fits in. I have to admit that Radon Rosborough played dirty with my feelings: by describing straight.el as purely functional he knew perfectly well a developer in love with functional programming could not resist. But there is more to it, of course.

First of all, I love the documentation. The effort put into explaining the rationale behind it, the comparisons with other package managers, and the basics to get started is simply amazing. Even the process of reproducing bugs is documented. It may seem like a lot to take in, but it’s clear and it’s something I want to know before changing one of the key features of my text editor.

Moreover, it takes a few lines of code to bootstrap straight.el. It would probably take fewer lines to set up package.el, that’s true, but straight.el is far more customisable. It also works seamlessly with use-package, so I didn’t have to reinvent my Emacs configuration just to try a new package manager.

Finally, you can freeze your package state at any time with straight-freeze-versions. This creates a lockfile with the current versions of your packages, meaning you can reproduce your exact configuration with a simple straight-thaw-versions. Stability is just a couple of commands away.

There must (should?) be a moment when the Emacs hacker knows they exploited their beloved editor as much as possible, the eureka light bulb leading the way through a thick fog of setq and defun. Valhalla is there, Emacs hacker, you know it. As for me, I decided to accept the murkiness for now, and look for the bulb that will get me out of here eventually another time.

-1:-- Straight ahead (Post)--L0--C0--October 04, 2019 12:00 AM

Anything goes: Fast Scrolling in Emacs

I work with some files that have some complex fontification rules. There is a significant lag when scrolling quickly through these files. Although I am using jit-lock-mode as my font-lock-support-mode, the lag is unbearable. One solution to this is to use fast-scroll. https://github.com/ahungry/fast-scroll. fast-scroll temporarily disables font-lock when scrolling. This has worked out nicely for me.
-1:-- Fast Scrolling in Emacs (Post tsengf (noreply@blogger.com))--L0--C0--October 03, 2019 07:26 AM

Raimon Grau: Migrating from vim (proficent) to emacs

In HN's thread about 26.3 being released (Congrats!), there's this guy  explaining that being already quite confortable with vim, it's too much of a commitment to move to emacs.

I remember the frustration when coming to emacs from an advanced vimmer POV: no "yyp"? no ":%s/foo/bar"? imap? But here's what I answered him:

As this is not an overnight conversion and you are quite proficent with vim already, my advice is to:
- Get used to type "emacs file.txt" instead of "vim file.txt" in your console.
- Have a function in emacs that opens the current file in vim for those moments where you just want your trusted environment. Writing it by yourself is a good focused learning experience.
This way you'll decide (and balance) how much you want to learn every day, and little by little you'll find yourself using that function less and less.

And I think this goes very well with my other "bootstrap your emacs lisp learning".

It's the same approach to most of my development (and life) efforts.  It's a function of how bad do you need it, how fast do you want it, the compound interest of starting early, and how much it slows you down (or blocks you for doing other things).
-1:-- Migrating from vim (proficent) to emacs (Post Raimon Grau (noreply@blogger.com))--L0--C0--September 03, 2019 12:06 AM

Chen Bin (redguardtoo): Aspell 0.60.8 will have direct support for camelCase words

Kevin Atkinso told me this good news.

Currently I'm using Emacs Lisp to check camel case words.

The new option --camel-case from aspell will definitely speed up the whole process.

Minimum Emacs setup,

(setq ispell-program-name "aspell")
(setq-default ispell-extra-args '("--sug-mode=ultra"
                                  "--lang=en_US"))
;; Make sure new aspell is installed
(when (string-match-p "--camel-case"
                      (shell-command-to-string (concat ispell-program-name " --help")))
  (push "--camel-case" ispell-extra-args))

Optionally, you could read What's the best spell check setup in emacs.

-1:-- Aspell 0.60.8 will have direct support for camelCase words (Post Chen Bin)--L0--C0--September 01, 2019 01:13 PM

Rubén Berenguel: SyncTeX and pdf-view-mode for emacs

Or, destiny is cruel
Back in the days of yore, when I was switching between my Windows machine and a Linux machine, I remember having SyncTeX active in my Windows machine. It was a wonderful experience: SyncTeX lets you click anywhere on a generated file from LaTeX and gets back to your editor, to the place generating where you clicked. This was extremely useful, specially later on when you need to adjust many formulas to fit and you need a bit of back-and-forth-ing.

Then I got a Mac, and since Preview is so handy I slowly forgot about SyncTeX. Time went on, and I merrily kept on editing LaTeX files as usual. I even managed to deliver my PhD dissertation a couple weeks ago, the formal speech will be in a month or two (come at your own risk). AucTeX’s preview saved most of the days, so I slowly even forgot SyncTeX existed. Shame on me indeed.

The other day I got an annotated PDF from one of my advisors, and I just couldn’t open the annotations. I tried all programs I had for Mac, and no luck: annotations weren’t showing, just saw the icons. Surveying for some command-line tool to extract annotations (just in case) I found pdf-tools, a replacement for DocView based on Poppler. It had the awesome ability of actually displaying annotations, with it it was pretty clear the annotations were broken in that PDF. I got a new set of PDFs from my advisor with the annotations in place, though. While waiting for it to arrive…

I saw SyncTeX was an option of pdf-tools. I had been using that, hadn’t I? So, I activated SyncTeX in AucTeX (it is TeX-source-correlate-method, see here) and indeed: I could have two frames, one with the actual LaTeX sources and the other with a PDF, and go from one to the other. Even hyperreferences in PDF work! See (well, click on the full-screen mode to see it larger or you won't see anything)!



Getting pdf-tools to work wasn’t incredibly tricky (given the hoops you need for some packages, sometimes). Just

brew install pdf-tools

and after reading

brew info pdf-tools

I was told to run

  emacs -Q --batch --eval "(package-install-file 
\"/usr/local/Cellar/pdf-tools/0.60/pdf-tools-0.60.tar\")"

and this does the trick (well, change emacs for your actual emacs, which likely is /Applications/Emacs.app/Contents/MacOS/Emacs) You’ll also need to add to your .emacs file (or temporarily in your *scratch* buffer)


(setenv "PKG_CONFIG_PATH"

(concat

"/usr/local/Cellar/zlib/1.2.8/lib/pkgconfig"

":"

"/usr/local/lib/pkgconfig:/opt/X11/lib/pkgconfig"))


(getenv "PKG_CONFIG_PATH")


and run

(pdf-tools-install)

as advised in the package’s README. And that's it, open a PDF and activate pdf-view-mode to check everything is in place. Well worth it!
-1:-- SyncTeX and pdf-view-mode for emacs (Post Ruben Berenguel (noreply@blogger.com))--L0--C0--August 15, 2019 09:15 AM

Sanel Zukan: ido-mode with eshell, shell, sql and more...

ido-mode doesn't provide completion for eshell, shell or sql-mode out of the box, and I wasn't been able to find any package with this option that is lightweight enough (Helm, I'm looking at you). So, after few attempts, here is the code for that:

(defun ido-eshell-comint-history ()
  "eshell & comint history with ido."
  (interactive)
  (if (or (member major-mode '(eshell-mode sql-interactive-mode))
          (derived-mode-p 'comint-mode))
     (let ((ring (if (eq major-mode 'eshell-mode)
                   eshell-history-ring
                   comint-input-ring)))
       (insert
        (ido-completing-read "History: "
                             (delete-dups
                              (ring-elements ring)))))
    (message "Unsupported mode")))

After evaluating the code, in eshell simply execute M-x ido-eshell-comint-history and magic will happen - you will get full eshell history managed by ido-mode. To make it more authentic, map it to C-c C-l, which is default sequence for completion in eshell.

The same can be applied for shell and sql-mode as well.

But, the things gets interesting here: (ido-eshell-comint-history) will pick up history for all modes inherided from comint-mode (shell is using comint-mode), so you will get history completion for python, lua, lisp and other inferior processes for free!

Just to add (commenting above code), although sql-mode is using comint-mode, it doesn't derive it so additional check is necessary. Also to enable history in sql-mode you will need to set variable sql-input-ring-file-name as well.

-1:-- ido-mode with eshell, shell, sql and more... (Post)--L0--C0--August 06, 2019 10:00 PM

Shae Erisson: Open Source Hardware Hearing Aid Part 1

Why pay thousands for a hearing aid when you could pay $300?
-1:-- Open Source Hardware Hearing Aid Part 1 (Post Shae Erisson)--L0--C0--August 03, 2019 12:00 AM

Alex Schroeder: Use of Emacs

Two Years With Emacs as a CEO (and now CTO) is the followup to A CEO's Guide to Emacs. The author talks about life with Emacs.

So many cool quotes in that article!

On using a tool that isn’t designed to do a task (an application) but on using a tool help you do your task. Emacs is a tool, not an app.

Emacs is a portal into the power of the computer itself, and that is a rabbit hole worth descending. Its idioms are paths to discovering and creating your own, and that for me is the definition of creativity. One of the sad things about modern computing is that it is largely made up of black boxes with shiny interfaces that provide momentary gratification rather than real satisfaction. This makes us into consumers rather than creators/makers of technology. I don’t care who you are or what your background is; you can understand your computer, and you can make things with it.

On not using Emacs for shared todo items and calendar stuff:

I gave up on using Org-mode for to dos and the like, as I have to coordinate many meetings and calls every day with dozens of people, and I cannot ask the rest of the world to adapt to my choice of tools, nor do I have the time to transcribe or automate moving things to Org.

On not using Emacs for takin notes during meetings because it’s often better to use a pen (unless the point of the meeting is to write a document).

I also use a plain old pen for note-taking during meetings, as I find laptop/keyboard use in meetings to be rude and limiting to my ability to listen and think.

Ah yes. At work, I usually joke that Emacs is just my IRC client... 🙂

Tags:

-1:-- Use of Emacs (Post)--L0--C0--August 02, 2019 10:09 PM

emacsninja: Code Conversion Language

Update: I forgot that I did a brief analysis on this many years ago, using ROT13 as example.

Update: Noam Postavsky pointed out on #emacs that CCL is not turing-complete after all as a full simulation (as opposed to just interpreting a single line) requires an Emacs Lisp loop. This loop cannot be done in CCL itself as it doesn’t allow feeding its output back in as input. The I/O restrictions most likely put it into the weaker category of finite-state transducers.

Emacs is most famously, a re-imagination of a Lisp machine, with the Emacs Lisp byte-code interpreter being at its core. A lesser-known fact is that there’s two more byte-code interpreters in its C sources, one for compiled regular expressions and another designed for encoding and decoding text, known as Code Conversion Language (CCL). This blog post will focus on the latter as it’s largely gone unnoticed and hasn’t seen too much experimentation.

The CCL implementation is split into the byte-code interpreter (ccl.c) and compiler (ccl.el) parts. There is no official documentation other than comments and docstrings found in these files. From this I’ve learned that CCL programs are represented as integer vectors and that there’s a higher-level language compiling to them, described in the ccl-define-program docstring. By reading that information I’ve deduced the following:

  • The VM has eight integer-sized registers r0 to r7 and an instruction counter ic
  • Register r7 is used as a status register and may be clobbered at any time by an arithmetic operation
  • A CCL program can either be run on a string and return a string, alternatively it can be run standalone for side effects
  • The former mode requires you to provide a nine-element status vector representing the registers and instruction counter, the latter an eight-element status vector representing the registers only
  • As a side-effect, the status vector contains the new state of the registers and instruction counter after executing the program
  • The VM supports the standard C arithmetic, comparison and assignment operators
  • The language translates several control flow statements to equivalent goto statements, such as if, branch (look-up table) and loop with repeat inside
  • Statements are grouped by surrounding them with parentheses
  • When operating on a string, they are read in and written out in a serial fashion, no random access whatsoever
  • It’s possible to do a look-up on an array, translation table or hash table
  • There is a call operator, but no stack to save/restore arguments to/from, so you’ll have to come up with a calling convention fitting the available registers
  • Each CCL program specifies a magnification factor which determines the ratio between output and input string size

Armed with that knowledge I wrote some boiler plate code for experimentation:

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

(require 'ccl)

(defvar ccl-status (make-vector 8 0))
(defvar ccl-status+ic (make-vector 9 0))

(defun ccl-init-status (status args)
  (let ((i 0))
    (fillarray status 0)
    (dolist (arg args)
      (aset status i arg)
      (setq i (1+ i)))))

(defun ccl-run (program string &rest args)
  (let ((status ccl-status+ic))
    (ccl-init-status status args)
    (ccl-execute-on-string program status string)))

(defun ccl-run-pure (program &rest args)
  (let ((status ccl-status))
    (ccl-init-status status args)
    (ccl-execute program status)
    status))

There will be some benchmark numbers, none of these are to be taken seriously. Do your own benchmarks before using mine for decisions.

Hello World!

For starters I’ll focus on processing strings. The easiest possible program that still does something useful reads in output and writes it out as is:

(define-ccl-program ccl-identity
  '(1
    (loop
     (read r0)
     (write r0)
     (repeat))))

(ccl-run 'ccl-identity "Hello World!") ;=> "Hello World!"

Let’s go through that program carefully. The S-Expression starts with a magnification factor of 1, meaning that the output buffer should be as large as the input buffer. If it were zero, no I/O would be permitted in the first place, whereas a factor greater than one would allocate enough space to produce a string larger than the input.

The magnification factor is followed by a s-expression that’s executed until it’s done or an error occurred, such as there being no more input. It may be followed by another s-expression that’s executed after the main one, no matter whether it failed with an error or not.

ccl-identity uses a pattern that will come up a few more times in this blog post. It enters a loop, reads a character into the r0 register, writes out a character from the r0 register and jumps to the beginning of the loop. If there are no more characters left, the read operation fails and terminates the loop. Let’s spice things up by adding an extra processing step before writing out the character:

(define-ccl-program ccl-xor
  '(1
    (loop
     (read r1)
     (r1 ^= r0)
     (write r1)
     (repeat))))

(ccl-run 'ccl-xor "Secret" 42) ;=> "yOIXO^"
(ccl-run 'ccl-xor "yOIXO^" 42) ;=> "Secret"

XOR is the bread and butter operator in modern cryptography. A text can be encrypted by replacing each character with the result of XORing it against a secret byte, similarly it can be decrypted by applying the same transformation again. To pass the secret byte as an argument, I’ve placed it in the r0 register and read the string into the r1 register instead. On each iteration of the loop r1 is set to r1 ^ r0 and written out again.

More on translation

In the real world translating characters isn’t as simple as applying some arithmetic to them. Suppose I wanted to challenge the upcase built-in:

(define-ccl-program ccl-upcase
  '(1
    (loop
     (read r0)
     (if (r0 >= ?a)
         (if (r0 <= ?z)
             (r0 -= 32)))
     (write r0)
     (repeat))))

The processing step is a bit more involved this time. If the read-in character appears to be between the a and z characters, transform it by subtracting 32. Why 32? Take a look at an ASCII table and you’ll see that this is the distance between uppercase and lowercase letters. Unfortunately this implementation cannot challenge upcase as it fails to translate non-ASCII characters correctly and is slower than the real deal:

(ccl-run 'ccl-upcase "Hello World!") ;=> "HELLO WORLD!"
(ccl-run 'ccl-upcase "Mötley Crüe") ;=> "MöTLEY CRüE"
(benchmark 100000 '(ccl-run 'ccl-upcase "Hello World!"))
;; => "Elapsed time: 0.165250s (0.072059s in 1 GCs)"
(benchmark 100000 '(upcase "Hello World!"))
;; => "Elapsed time: 0.119050s (0.072329s in 1 GCs)"

Let’s try again with a different text transformation where I actually have a chance to win, ROT13:

(define-ccl-program ccl-rot13
  '(1
    (loop
     (read r0)
     (if (r0 >= ?a)
         (if (r0 <= ?z)
             ((r0 -= ?a)
              (r0 += 13)
              (r0 %= 26)
              (r0 += ?a))))
     (if (r0 >= ?A)
         (if (r0 <= ?Z)
             ((r0 -= ?A)
              (r0 += 13)
              (r0 %= 26)
              (r0 += ?A))))
     (write r0)
     (repeat))))

This time the program needs to recognize two different character ranges to process, lowercase and uppercase ASCII characters. In either case they’re translated to their position in the alphabet, rotated by 13, then translated back to ASCII again. Surprisingly enough, this is enough to beat both rot13-string and rot13-region:

(ccl-run 'ccl-rot13 "Hello World!") ;=> "Uryyb Jbeyq!"
(ccl-run 'ccl-rot13 (ccl-run 'ccl-rot13 "Hello World!"))
;; => "Hello World!"
(benchmark 100000 '(ccl-run 'ccl-rot13 "Hello World!"))
;; => "Elapsed time: 0.248791s (0.072622s in 1 GCs)"
(benchmark 100000 '(rot13-string "Hello World!"))
;; => "Elapsed time: 6.108861s (2.360862s in 32 GCs)"
(with-temp-buffer
  (insert "Hello World!")
  (benchmark 100000 '(rot13-region (point-min) (point-max))))
;; => "Elapsed time: 1.489205s (1.017631s in 14 GCs)"

I then tried to use translation tables for a final example of a “Vaporwave” converter, but failed. Funnily enough this mirrors my overall experience with Emacs, it’s easy to write fun things, but the moment one tries to write something useful, you discover it’s not fun and sometimes not even up to the task. At least it’s possible to salvage the translation tables and use them with translate-region instead, the built-in used by rot13-string and rot13-region:

(defvar ccl-vaporwave-table
  (make-translation-table-from-alist
   (cons '(?\s . 12288)
         (mapcar (lambda (i) (cons i (+ i 65248)))
                 (number-sequence 33 126)))))

(defun vaporwave-it (string)
  (with-temp-buffer
    (insert string)
    (translate-region (point-min) (point-max) ccl-vaporwave-table)
    (buffer-string)))

(vaporwave-it (upcase "aesthetic")) ;=> "AESTHETIC"

Edging towards general-purpose computing

All examples so far have worked on text. If you limit yourself to numbers, you can solve some basic arithmetic problems. Here’s a classic, calculating the factorial of a number:

(define-ccl-program ccl-factorial
  '(0
    ((r1 = 1)
     (loop
      (if r0
          ((r1 *= r0)
           (r0 -= 1)
           (repeat)))))))

(defun factorial (n)
  (let ((acc 1))
    (while (not (zerop n))
      (setq acc (* acc n))
      (setq n (1- n)))
    acc))

While the regular version is more concise, the logic is nearly the same in both. Here’s some numbers:

(aref (ccl-run-pure 'ccl-factorial 10) 1) ;=> 3628800
(factorial 10) ;=> 3628800
(benchmark 100000 '(ccl-run-pure 'ccl-factorial 10))
;; => "Elapsed time: 0.069063s"
(benchmark 100000 '(factorial 10))
;; => "Elapsed time: 0.080212s"

This isn’t nearly as much of a speed-up as I’ve hoped for. Perhaps CCL pays off more when doing arithmetic than for looping? Another explanation is that the Emacs Lisp byte-code compiler has an edge over CCL’s rather simple one. Here’s a more entertaining example, printing out the lyrics of 99 Bottles of Beer on the Wall:

(define-ccl-program ccl-print-bottle-count
  '(1
    (if (r0 < 10)
        (write (r0 + ?0))
      ((write ((r0 / 10) + ?0))
       (write ((r0 % 10) + ?0))))))

(define-ccl-program ccl-99-bottles
  '(1
    (loop
     (if (r0 > 2)
         ((call ccl-print-bottle-count)
          (write " bottles of beer on the wall, ")
          (call ccl-print-bottle-count)
          (write " bottles of beer.\n")
          (write "Take one down and pass it around, ")
          (r0 -= 1)
          (call ccl-print-bottle-count)
          (write " bottles of beer on the wall.\n\n")
          (repeat))
       ((write "2 bottles of beer on the wall, 2 bottles of beer.\n")
        (write "Take one down and pass it around, 1 bottle of beer on the wall.\n\n")
        (write "1 bottle of beer on the wall, 1 bottle of beer.\n")
        (write "Take one down and pass it around, no more bottles of beer on the wall.\n\n")
        (write "No more bottles of beer on the wall, no more bottles of beer.\n")
        (write "Go to the store and buy some more, 99 bottles of beer on the wall.\n"))))))

(defun 99-bottles ()
  (with-output-to-string
    (let ((i 99))
      (while (> i 2)
        (princ (format "%d bottles of beer on the wall, %d bottles of beer.\n" i i))
        (princ (format "Take one down and pass it around, %d bottles of beer on the wall.\n\n" (1- i)))
        (setq i (- i 1))))
    (princ "2 bottles of beer on the wall, 2 bottles of beer.\n")
    (princ "Take one down and pass it around, 1 bottle of beer on the wall.\n\n")
    (princ "1 bottle of beer on the wall, 1 bottle of beer.\n")
    (princ "Take one down and pass it around, no more bottles of beer.\n\n")
    (princ "No more bottles of beer on the wall, no more bottles of beer.\n")
    (princ "Go to the store and buy some more, 99 bottles of beer on the wall.\n")))

This example shows a few more interesting things, generating text of unknown length is rather hard, so I’m using the standard magnification factor of 1 and estimate how big the buffer will be to create an appropriately sized input string. call is useful to not repeat yourself, at the cost of having to carefully plan register usage. Printing out the bottle count can be done if you’re limiting yourself to whole numbers up to 100, a generic solution is going to be hard without random access to the output string. The performance numbers for this one are somewhat surprising:

(let ((input (make-string 15000 ?\s)))
  (benchmark 1000 '(ccl-run 'ccl-99-bottles input 99)))
;; => "Elapsed time: 0.301170s (0.217804s in 3 GCs)"
(benchmark 1000 '(my-99-bottles))
;; => "Elapsed time: 1.735386s (0.507231s in 7 GCs)"

This doesn’t make much sense. Is using format that expensive? It’s hard to tell in advance whether CCL will make a noticable difference or not.

But is it Turing-complete?

My experimentation so far left me wondering, is this language turing-complete? You can perform arithmetics, there’s goto, but the I/O facilities, amount of registers and memory access are limited. The easiest way of proving this property is by implementing another known turing-complete system on top of your current one. I researched a bit and found the following candidates:

  • Brainfuck: A classic, however it requires writable memory. Registers could be used for this, but you don’t have many to play with. You’d need the branch instruction to simulate the data pointer.
  • subleq: Implementing subleq looks easy, but suffers from the same problem as Brainfuck, it requires you to modify an arbitrary memory location. I’ve found a compiler from a C subset to subleq that generates code operating beyond the handful of registers, so that’s not an option either.
  • Rule 110: It’s basically Game of Life, but one-dimensional and can be implemented in a serial fashion. With some tricks it doesn’t require random access either. The proof of it being turing-complete looks painful, but whatever, I don’t care. It’s perfect. There are more elementary cellular automata, so I’ll try to implement it in a generic fashion and demonstrate it on Rule 90 which produces the Sierpinski triangle.
(defmacro define-ccl-automaton (n)
  (let ((print-sym (intern (format "ccl-rule%d-print" n)))
        (rule-sym (intern (format "ccl-rule%d" n))))
    `(progn
       (define-ccl-program ,print-sym
         '(1
           ((r4 = 0)
            (if (r0 == ?1)
                (r4 += 4))
            (if (r1 == ?1)
                (r4 += 2))
            (if (r2 == ?1)
                (r4 += 1))
            (branch r4
                    (write ,(if (zerop (logand n 1)) ?0 ?1))
                    (write ,(if (zerop (logand n 2)) ?0 ?1))
                    (write ,(if (zerop (logand n 4)) ?0 ?1))
                    (write ,(if (zerop (logand n 8)) ?0 ?1))
                    (write ,(if (zerop (logand n 16)) ?0 ?1))
                    (write ,(if (zerop (logand n 32)) ?0 ?1))
                    (write ,(if (zerop (logand n 64)) ?0 ?1))
                    (write ,(if (zerop (logand n 128)) ?0 ?1))))))
       (define-ccl-program ,rule-sym
         '(1
           ((r6 = ,n)
            (r0 = 0)
            (read r1)
            (read r2)
            (loop
             (call ,print-sym)
             (read r3)
             (r0 = r1)
             (r1 = r2)
             (r2 = r3)
             (repeat)))
           ((r0 = r1)
            (r1 = r2)
            (r2 = r5)
            (call ,print-sym)))))))

(define-ccl-automaton 30)
(define-ccl-automaton 90)
(define-ccl-automaton 110)

(defun ccl-sierpinski ()
  (with-output-to-string
    (let ((line "0000000001000000000"))
      (dotimes (_ 20)
        (princ line)
        (terpri)
        (setq line (ccl-run 'ccl-rule90 line))))))

The macro may look scary, but all it does is defining two CCL programs. What an elementary cellular automaton does is looking at the two cells around the current cell, map them to a cell depending to a rule and emit it. There are two edge cases with this for the first and last cell, in my implementation the first cell assumes the previous one was a zero and the last cell uses the first cell. Since there’s no random access, it’s stored into a spare register at the beginning and accessed in a S-Expression after the main loop terminated due to no more input. The surrounding and current cell are stored in three registers and rotated every time a new cell is read in. The mapping is done in the print program by summing up the ones and zeroes, then using the branch instruction to apply the rule to it. If you find this hard to follow, here’s an Emacs Lisp version of it using random access and less limited arithmetic to do the job:

(defun rule--evolve (prev cur next n)
  (let ((acc (+ (if (= prev ?1) 4 0)
                (if (= cur ?1) 2 0)
                (if (= next ?1) 1 0))))
    (if (zerop (logand n (ash 1 acc))) ?0 ?1)))

(defun rule-evolve (line n)
  (let ((out (make-string (length line) ?0)))
    (dotimes (i (length line))
      (cond
       ((zerop i)
        (aset out i (rule--evolve ?0 (aref line i) (aref line (1+ i)) n)))
       ((= i (1- (length line)))
        (aset out i (rule--evolve (aref line (1- i)) (aref line i) (aref line 0) n)))
       (t
        (aset out i (rule--evolve (aref line (1- i)) (aref line i) (aref line (1+ i)) n)))))
    out))

(defun sierpinski ()
  (with-output-to-string
    (let ((line "0000000001000000000"))
      (dotimes (_ 20)
        (princ line)
        (terpri)
        (setq line (rule-evolve line 90))))))

One more benchmark run, this time with less surprising performance numbers:

(benchmark 1000 '(ccl-sierpinski))
;; => "Elapsed time: 0.365031s (0.071827s in 1 GCs)"
(benchmark 1000 '(sierpinski))
;; => "Elapsed time: 0.545512s (0.071829s in 1 GCs)"

If you want to see it in action, try evaluating (progn (princ (sierpinski)) nil) in M-x ielm.

Now for a big letdown, despite everything what I’ve demonstrated, this system is not turing-complete after all. While it’s capable of processing a single line of input, the proof of Rule 110 being turing-complete relies on feeding its output in as input over and over again, however that part has been done in Emacs Lisp as it’s impossible to do in CCL. I’m not 100% sure what CCL’s computing power is, Noam Postavsky suggested on #emacs that it’s most likely a finite-state transducer.

Final words

You may ask yourself now whether you should rewrite all of your slow code to CCL programs. I don’t believe that’s the way to go for a number of reasons:

  • Speedups vary wildly, somewhere between -40% to 450%. There’s no obvious way of predicting whether the optimization is worth it.
  • It’s hard to write an equivalent program or sometimes even impossible, especially if it requires you to use many variables or random access read/write operations.
  • It’s hard to debug a CCL program. While the compiler does a good job at catching syntax errors, runtime errors are far harder to figure out if you can only stare at the registers. Maybe a debugger could be built that uses the “continue” facility and instruction counter register…
  • It’s hard to maintain a CCL program. Not to mention, there’s hardly people who know how to write them. Most of the examples I’ve found online do text encoding/decoding. The only exception to this is pgg-parse-crc24-string which lives in a file marked as obsolete.
  • This leads me to my last point, CCL may be obsoleted as well. Granted, it will take time, but so far I haven’t seen people enthusiastic about it being a thing.

If you still believe that despite of this it’s worth giving CCL a try, please let me know, especially if you’re doing something non-standard with it, like advanced cryptography or number crunching. Likewise, if you’re not convinced that it’s turing-complete or that I could be doing some things far better than presented, send me a message.

-1:-- Code Conversion Language (Post Vasilij Schneidermann)--L0--C0--July 23, 2019 06:37 PM

Chen Bin (redguardtoo): Javascript code navigation in counsel-etags

Javascript code navigation is supported by counsel-etags out of box.

It can support new javascript syntax like arrow function easily because counsel-etags is just frontend.

It reads tags file created by backend CLI program Ctags. Ctags uses regular expression to extract tag name from source code.

But there are some syntax which regular expression could not help.

For example, json object path can't be extracted by regular expression.

Given an object a in file A,

var a = {
  b: {
    c: 3,
  }
};

File B has code let v1 = a.b.c;, how can we jump to the definition of the field c from json path a.b.c?

The solution is to use Lisp to parse code in file A and generate extra navigation data which could be appended to tags file generated by Ctags.

The algorithm is simple,

  • Traverse all the field of object a in file A. Use API js2-print-json-path from js2-mode to get json path of current field.
  • The json path could be regarded as tags name. We've already got file name and line number. So there is enough information to create navigation data for tags file. Here is tags file format.

Necessary utilities are already provided by counsel-etags v1.8.7,

  • After tags files is generated by Ctags, the hook counsel-etags-after-update-tags-hook is executed. Users can append tags file in this hook
  • (counsel-etags-tag-line code-snippet tag-name line-number byte-offset) return a line which could be appended into tags file

My current project uses a technology called styled-components which has an advanced feature theming.

It could dynamically change web application's appearance and is a critical technology for our application to support multiple customer. Application's theme is basically a file containing a huge json object. So it's important that developers can jump to the corresponding json object's field by json path.

Screencast

counsel-etags-plus-json-path.gif

Code

(require 'counsel-etags)

(defun my-manual-update-tag-file (code-file tags-file)
  (let* ((dir (file-name-directory tags-file))
         (path (concat dir code-file))
         curline
         jp
         tagstr)
    (unless (featurep 'js2-mode) (require 'js2-mode))
    (with-temp-buffer
      (insert-file-contents path)
      (js2-init-scanner)
      (js2-do-parse)
      (goto-char (point-min))
      ;; find all js object property names
      (while (re-search-forward "\"?[a-z][a-zA-Z0-9]*\"?:" (point-max) t)
        (when (setq jp (js2-print-json-path))
          (setq curline (string-trim (buffer-substring-no-properties (line-beginning-position)
                                                                     (line-end-position))))
          (setq tagstr (concat tagstr
                               (counsel-etags-tag-line curline
                                                       jp
                                                       (count-lines 1 (point))
                                                       (point)))))
        ;; move focus to next search
        (goto-char (line-end-position))))
    (when tagstr
      (with-temp-buffer
        (insert-file-contents tags-file)
        (goto-char (line-end-position))
        (insert (format "\n\014\n%s,%d\n%s" code-file 0 tagstr))
        (write-region (point-min) (point-max) tags-file nil :silent)))))

(defun counsel-etags-after-update-tags-hook-setup (tags-file)
    (my-manual-update-tag-file "frontend/theming/themes/darkTheme.js" tags-file)
    (my-manual-update-tag-file "frontend/theming/themes/lightTheme.js" tags-file))
(add-hook 'counsel-etags-after-update-tags-hook 'counsel-etags-after-update-tags-hook-setup)
-1:-- Javascript code navigation in counsel-etags (Post Chen Bin)--L0--C0--July 22, 2019 12:07 PM

Shae Erisson: Hyper and Super on my keyboard?

Stranger Strings or the new-ish way to redefine keyboard layouts in the X Window System
-1:-- Hyper and Super on my keyboard? (Post Shae Erisson)--L0--C0--July 21, 2019 12:00 AM