Irreal: An Org Refile Workflow

Yiming Chen has an interesting post on his org-refile workflow. Before you read his post, though, you should (re)read Aaron Bieber’s Organizing Notes With Refile that I wrote about back in 2018. Bieber’s post gives you the background you need to follow Chen’s.

If you’re a little hazy on the Org-refile concept, the TL;DR is that you can move an Org tree node someplace else. Some like Matus Goljer use it to deal with items from Org-capture. Others use it to move items to a more appropriate place or as a sort of archiving operation. If you use Ivy or Helm, when you call org-refile you’re presented with a list of possible targets to which to move the node.

That list is completely configurable. A common choice is to include all the headers from all the Org files that make up your agenda, but that’s not the only possibility. You can add other Org files, including the current one, or as Chen demonstrates, you can add all headers in all Org files on your system. Most people probably won’t want to do that but it’s possible.

One of the reasons that Chen includes everything in his target list is that he likes to use it as a way of jumping to a specific Org node. You can do that by specifying the universal argument to org-refile. Take a look at his post for all the details. Org-refile can make many workflows easier so it’s worth taking a look at these posts to see if it can reduce some friction in yours.

-1:-- An Org Refile Workflow (Post jcs)--L0--C0--May 26, 2020 04:45 PM

Meta Redux: RuboCop Defaults Survey Results

A while ago we ran a survey with RuboCop’s users with a the goal to decide if some defaults needed to be updated before cutting RuboCop 1.0. 722 people took part of the survey, and while this number was somewhat disappointing, given the size of RuboCop’s user base, I hope the results are representative of the general sentiment of our users.

In this article I’ll briefly summarize the results from the survey and provide some personal thoughts on them. I’m too lazy to include some nice charts here (and it’s hard to share directly those generated by Google Forms), but I hope you’ll forgive me.

Single-quoted vs double-quoted string literals

This is without a doubt the favourite bike-shedding topic of the Ruby community. I’ve wasted countless hours of my life listening to the arguments of both sides, and I still remain convinced that it doesn’t really matter much which style you’re adopting as long as you apply it consistently. For the record - my personal preference has always been double-quoted string literals.1

The results on this question definitely surprised me:

  • Single-quoted strings - 58%
  • Double-quoted strings - 39%
  • Other (e.g. that they don’t care about this) - 3%

Before the survey I assumed this was going to be one default we might need to change, as for as long as RuboCop existed some (many) people were vocally complaining that RuboCop’s default (single-quoted string literals) wasn’t reflecting the actual preference of the Ruby community. It seems, however, that’s not the case. It’s possible that RuboCop influenced this over the years, I don’t know. At any rate now it’s clear that we’re not changing this particular default.

Maximum Line Length

Another question with surprising results (at least for me):

  • 120 characters - 48%
  • 100 characters - 21%
  • 80 characters - 18%
  • Other (e.g. 150, no limit) - 13%

I definitely didn’t see this coming and I expected some close contest between 80 and 100. Even though I feel that 120 is a bit extreme, your voice has been heard and this default has been adjusted in RuboCop 0.84. I didn’t go as far as recommending 120 in the Ruby Style Guide, but I’ve amended the line length guideline to be more permissive of longer line limits. I’ve also added there a bit of rationale why we shouldn’t go overboard with the line length.

Trailing Commas in Collection Literals

# no trailing commas
{ one: 1,
  two: 2 }

# only in multi-line literals
{ one: 1,
  two: 2, }

{ one: 1, two: 2 }

# always
{ one: 1,
  two: 2, }

{ one: 1, two: 2, }

I hope the code snippets above illustrate clearly the question. Here are the results:

  • I don’t use trailing commas - 64%
  • I use trailing commas only in multi-line collection literals - 27%
  • I use trailing commas in all collection literals (including single-line literals) - 1,5%
  • Other - 7,5%

Here the results are a bit messed up, as I split the question about “trailing commas” in two after launching the survey, based on some feedback I got that the original formulation was unclear as to whether it covered single-line literals or not. At any rate, “no trailing commas” won by a landslide and this default is going to stay the same.

and and or

The question of whether and and or are useful or should be totally avoided has long captivated the Ruby community. Here’s what RuboCop users had to say about them:

  • Don’t use them at all - 68%
  • Use them all the time - 4%
  • Use them for flow of control (e.g. do_something and return) - 29%

Despite the results, however, we opted to make RuboCop more permissive here and to allow and and or for flow of control, mostly because this style seems to be quite common in Ruby on Rails. Probably most people won’t even notice this change.

Double Negation (!!)

Double negation is one of those idioms that are both useful and confusing (especially to newcomers) at the same time. Let’s see what’s the verdict on it:

  • Only when I need to return a boolean (e.g. in a predicate method) - 53%
  • Don’t use it at all - 39%
  • Other - 8%

Once again your voice has been heard and double negation is now allowed in return context.

Spaces inside hash literals

# with spaces
{ batman: "Bruce Wayne" }

# no spaces
{batman: "Bruce Wayne"}
  • I use spaces - 71%
  • I don’t use spaces - 29%

No surprises here.

Parentheses around Kernel method arguments (e.g. puts, system, exit)

# no parens
puts "Hello, world!"
exit -1

# with parens
puts("Hello, world!")
exit(-1)
  • I don’t use parentheses - 80%
  • I use parentheses - 17%

No surprises here as well.

Do you find the Metrics cops (e.g. CyclomaticComplexity) useful?

  • Somewhat useful - 43%
  • Very useful - 29%
  • Useless - 19%
  • Other - 9%

Seems that’s one area that could be substantially improved. More about this in the next section.

General level of happiness with RuboCop’s defaults

  • Very happy - 15%
  • Happy - 47%
  • OK - 23%
  • Not happy - 8%
  • Very unhappy - 5%

Not great, but not terrible either. I hope the changes we made in RuboCop 0.84 and that we plan to make down the road will improve the overall satisfaction with the defaults.

General Feedback

This section of the survey was pure gold and we got a ton of great feedback there. Most of the feedback could probably be summarized as:

  • The value of many cops is somewhat subjective and it’d be nice if RuboCop had some cop preset with only really essential cops (e.g. Lint cops and those that map to the strongest conventions and idioms)
  • The value of the metrics cops is questionable. There were many suggestions to relax certain defaults there.
  • Many people seem to hate frozen string literals :-)

There was also the usual healthy dose of disagreement with some Layout defaults, but that was something totally expected.

At any rate - we’re definitely going to tackle the cop presets idea at some point and provide a smaller set of “essential” cops, alongside the current somewhat heavy-handed default set of cops.

Sidenote

When I saw that many people were complaining about the Metrics cops I added an extra question asking if people knew they can disable entire cop departments via .rubocop.yml. Turns out that 40% of the RuboCop users didn’t know that. Here’s how this can be done:

Metrics:
  Enabled: true

You can read more on the subject here.

Raw Data

Here’s the raw data from the survey for those of you who’d like to analyze it further.

I’d love to hear how others interpreted it.

Epilogue

Thanks to everyone who participated in survey! I hope this article and the changes we’ve made to the defaults in RuboCop 0.84 show you that we respect the opinion of our users and that your voice has been heard.

Right now the release of RuboCop 1.0 is imminent and we’re unlikely to do anymore last minute changes, but there will always be 2.0, 3,0, etc. Keep hacking!

  1. So much for the theory that RuboCop’s defaults are simply my subjective preferences. 

-1:-- RuboCop Defaults Survey Results (Post Bozhidar Batsov)--L0--C0--May 26, 2020 06:56 AM

Sacha Chua: 2020-05-25 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-05-25 Emacs news (Post Sacha Chua)--L0--C0--May 26, 2020 01:26 AM

Irreal: Eshell Demo

Protesilaos Stavrou is all in on Eshell. On the very rare occasions that he needs a “standard shell,” he fires it up in Emacs using vterm but mostly he uses Eshell because he considers it a superior solution. He’s posted an excellent video that shows how he uses Eshell in his workflow.

One of the things he likes the most about Eshell is that you can write and execute Elisp as well as traditional shell commands. That means you can have bits of Elisp to provide shortcuts that make your work easier. Stavrou demonstrates several of those in action and while he doesn’t show the code in the video, he does provide a pointer to them so it’s easy to use or adapt them in your own workflow.

If you’re an Eshell user or considering becoming one, be sure to take a look at Stavrou’s video. It shows you some of its built-in features as well as the helper functions that Stavrou built. The video is just over 23 minutes so you’ll have to schedule some time.

-1:-- Eshell Demo (Post jcs)--L0--C0--May 25, 2020 03:40 PM

Alvaro Ramirez: Preview SwiftUI layouts using Emacs org blocks

23 May 2020 Preview SwiftUI layouts using Emacs org blocks

ob-swiftui.gif

Chris Eidhof twitted a handy snippet that enables quickly bootstrapping throwaway SwiftUI code. It can be easily integrated into other tools for rapid experimentation.

Being a SwiftUI noob, I could use some SwiftUI integration with my editor of choice. With some elisp glue and a small patch, Chris's snippet can be used to generate SwiftUI inline previews using Emacs org babel. This is particularly handy for playing around with SwiftUI layouts.

We can piggyback ride off zweifisch's ob-swift by advicing org-babel-execute:swift to inject the org source block into the bootstrapping snippet. We also add a hook to org-babel-after-execute-hook to automatically refresh the inline preview.

If you're a use-package user, the following snippet should make things fairly self-contained (if you have melpa set up already).

Note: I like pressing C-c C-c to execute source blocks, so it's bound in the following snippet. I've also enabled org-display-inline-images when loading org files.

(use-package  org
   :hook ((org-mode . org-display-inline-images))
   :config

  (use-package  ob
     :bind (:map org-mode-map
                ("C-c C-c" . org-ctrl-c-ctrl-c))
     :config

    (use-package  ob-swift
       :ensure t
       :config
      (org-babel-do-load-languages 'org-babel-load-languages
                                   (append org-babel-load-languages
                                           '((swift     . t))))

      (defun  ar/org-refresh-inline-images ()
        (when org-inline-image-overlays
          (org-redisplay-inline-images)))

       ;;  Automatically refresh inline images.
      (add-hook 'org-babel-after-execute-hook 'ar/org-refresh-inline-images)

      (defun  adviced:org-babel-execute:swift (f  &rest args)
         "Advice ` adviced:org-babel-execute:swift ' enabling swiftui header param."
        (let* ((body (nth 0 args))
               (params (nth 1 args))
               (swiftui (cdr (assoc  :swiftui params)))
               (output))
          (when swiftui
            (assert (or (string-equal swiftui  "preview")
                        (string-equal swiftui  "interactive"))
                    nil  ":swiftui must be either preview or interactive")
            (setq body (format
                         "
 import Cocoa
 import SwiftUI
 import Foundation

 let screenshotURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString + \".png\")
 let preview = %s

 NSApplication.shared.run {
   %s
 }

 extension NSApplication {
   public func run(@ViewBuilder view: () -> V) {
     let appDelegate = AppDelegate(view())
     NSApp.setActivationPolicy(.regular)
     mainMenu = customMenu
     delegate = appDelegate
     run()
   }
 }

 extension NSApplication {
   var customMenu: NSMenu {
     let appMenu = NSMenuItem()
     appMenu.submenu = NSMenu()

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

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

 class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
   var window = NSWindow(
     contentRect: NSRect(x: 0, y: 0, width: 414 * 0.2, height: 896 * 0.2),
     styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
     backing: .buffered, defer: false)

   var contentView: V

   init(_ contentView: V) {
     self.contentView = contentView
   }

   func applicationDidFinishLaunching(_ notification: Notification) {
     window.delegate = self
     window.center()
     window.contentView = NSHostingView(rootView: contentView)
     window.makeKeyAndOrderFront(nil)

     if preview {
       screenshot(view: window.contentView!, saveTo: screenshotURL)
       // Write path (without newline) so org babel can parse it.
       print(screenshotURL.path, terminator: \"\")
       NSApplication.shared.terminate(self)
       return
     }

     window.setFrameAutosaveName(\"Main Window\")
     NSApp.activate(ignoringOtherApps: true)
   }
 }

 func screenshot(view: NSView, saveTo fileURL: URL) {
   let rep = view.bitmapImageRepForCachingDisplay(in: view.bounds)!
   view.cacheDisplay(in: view.bounds, to: rep)
   let pngData = rep.representation(using: .png, properties: [:])
   try! pngData?.write(to: fileURL)
 }
 "
                        (if (string-equal swiftui  "preview")
                             "true"
                           "false")
                        body))
            (setq args (list body params)))
          (setq output (apply f args))
          (when org-inline-image-overlays
            (org-redisplay-inline-images))
          output))

      (advice-add #'org-babel-execute:swift
                   :around
                  #'adviced:org-babel-execute:swift))))

Snippet also at github gist and included in my emacs config.

Once the snippet is evaluated, we're ready to use in an org babel block. We introduced the :swiftui header param to switch between inline static preview and interactive mode.

To try out an inline preview, create a new org file (eg. swiftui.org) and a source block like:

#+begin_src swift :results file :swiftui preview
  VStack(spacing: 10) {
      HStack(spacing: 10) {
        Rectangle().fill(Color.yellow)
        Rectangle().fill(Color.green)
      }
      Rectangle().fill(Color.blue)
      HStack(spacing: 10) {
        Rectangle().fill(Color.green)
        Rectangle().fill(Color.yellow)
      }
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity)
#+end_src
#+results:

vstack.jpg

Place the cursor anywhere inside the source block (#+begin_src/#+end_src) and press C-c C-c (or M-x org-ctrl-c-ctrl-c).

To run interactively, change the :swiftui param to interactive and press C-c C-c (or M-x org-ctrl-c-ctrl-c). When running interactively, press "q" (without ⌘) to quit the Swift app.

comments on twitter.

Update

  • Tweaked the snippet to make it more self-contained and made the steps more reproducible. Need to work out how to package things to make them more accessible. May be best to contribute as a patch to ob-swift and we can avoid the icky advice-add.
  • Thanks to Chris Eidhof for PNG support (instead of TIFF). Also TIL Swift's print has got a terminator param.
-1:-- Preview SwiftUI layouts using Emacs org blocks (Post Álvaro Ramírez)--L0--C0--May 23, 2020 07:13 PM

Irreal: Elfeed Tweaks

On Thursday, Mike Zamansky published a video on some tweaks he made to Elfeed. As soon as I wrote and published a post about it, I found two more posts on hacking Elfeed to make it better fit the tweaker’s workflow. The first, by Álvaro Ramírez, was directly inspired by Zamansky’s post and shows a way of opening an Elfeed entry in a browser without losing focus. That’s convenient if you like to skim through the entries and open the ones you find interesting in a browser tab for later reading.

As Zamansky demonstrates in his video, Elfeed does allow you to open multiple entries but you lose focus to the browser. Ramírez’s method keeps you in Elfeed until you’re ready to change to the browser and read all the interesting articles.

The second post, by Karthins, considers several hacks to adjust Elfeed to his liking. These include:

  • Split pane for index and current entry
  • Navigating the Elfeed database with the space bar
  • Easier tagging
  • Using EWW on a per entry basis to display posts

If you use Elfeed—and if you’re an Emacs user, you should be—be sure to take a look at these two posts. You may or may not like the changes they implement but even if you don’t, they show nice examples of how easy it is to adjust Elfeed to your needs.

-1:-- Elfeed Tweaks (Post jcs)--L0--C0--May 23, 2020 04:21 PM

Cyberthal: How to melee shambler zombies

Man is the top of the food chain, and shambler zombies don't stand a chance.

personal armor

Melee fighters should have a bite-proof bracer and a combination hammer+pickaxe for grappling.

When bracer is grabbed, hammer the fingers to break the grip. Pickaxe the skull when bracer is bitten.

Shields are inadvisable due to shambler slowness, strength, durability, numbers, and short range weaponry.

It's heavy vs light infantry, and line combat favors heavy.

solo

A jogger can defeat infinite shambler zombies with a street and a hoe.

Kite them over the curb, making them trip. Then hoe the lamboid suture.

Motor control disabled. Repeat.

group

The clubman breaks shambler's hands, then knees, occipital.

The spearman jabs its eyes, then topples, pins.

Clubman and spearman carry identical loadouts for interchangeability.

  • polearm: a hoe with a spear point on the butt
  • midrange: a kali stick with a metal-flanged head
  • short: a pickaxe hammer

The skirmisher overwatches with gun and softens with silent ranged weapons.

-1:-- How to melee shambler zombies (Post Cyberthal)--L0--C0--May 22, 2020 07:39 PM

Irreal: Zamansky 72: Customizing Elfeed

Mike Zamansky has a new video up in his Using Emacs Series and an update on his last video (Zamansky 71: Openwith). Let’s deal with the update first.

As you’ll recall, the problem Zamansky was trying to solve was being able to open a file in Dired with an external application. He found a solution but then discovered that it interfered with his mail client, mu4e. It turns out that Dired already has a built-in solution although you can be forgiven for not knowing about it. It’s not on the Dired reference card for Emacs 26 and even knowing what it was and the name of the function implementing it, it was still hard to find.

The answer is to press W on a Dired entry to open the file in your default browser. Despite the name of the function, browse-url-of-dired-file, it will open any file that the browser can display. That’s exactly the behavior that Zamansky was looking for: problem solved.

The current video documents a change Zamansky made to the behavior of Elfeed and the process he went through to accomplish it. When I’m reading my Elfeed entries, I usually start at the top and go down the list by pressing n after I finish an entry. If the original post/article looks interesting or offers more information, I may press b to bring it up in my browser. That’s the default behavior of Elfeed.

Zamansky’s workflow is different. He likes to stay in the index and rather than reading the RSS entry, he presses b to open the entry in his browser. When you do that, Elfeed marks the entry as read but many times Zamansky just glances at the entry in the browser with the intention of reading it later. That means he has to mark it as unread so it doesn’t disappear from the index. He wanted to find a way of displaying the entry in the browser but not mark it read.

Most of the video shows the process he went through to discover how to do that. His point is that Emacs makes such discovery fairly easy. He did have a problem with an anaphoric it but solved that too with a little experimentation. The takeaway is that you don’t need to be an Emacs internals expert or even an Elisp expert to make Emacs suit your work flow.

Take a look at the video for all the details. It’s about 12 and a quarter minutes so plan accordingly. Also be sure to read his post if you want the details on the update.

-1:-- Zamansky 72: Customizing Elfeed (Post jcs)--L0--C0--May 22, 2020 04:38 PM

Alvaro Ramirez: Open Emacs elfeed links in the background

-1:-- Open Emacs elfeed links in the background (Post Álvaro Ramírez)--L0--C0--May 21, 2020 11:00 PM

Mike Zamansky: Using Emacs 72 - Customizing Elfeed

I made this video write after I made the openwith one so even though I don't mention anything in this video, I wanted to share some updates on dired and openwith. I got a lot of suggestions on alternate ways to achieve the workflow I was seeking - being able to open a file using an external viewer. One person noted that under newer versions of Emacs, the W key is bound to the command (browse-url-of-dired-file) which does exactly what I wanted.
-1:-- Using Emacs 72 - Customizing Elfeed (Post)--L0--C0--May 21, 2020 06:47 PM

Irreal: Advanced Usage of the Org Agenda

A great deal of my Emacs tube time is spent displaying the Org agenda. My use of the agenda is probably not standard: I use it mainly as a portal into my log type entries. There are some TODO entries but it’s mostly just the headlines from log/journal entries. Most people, I think, use the agenda as an agenda: as a list of appointments and things they need to do. If you’re one of those people, there are several things you can do to make the agenda more useful.

Vedang Manerikar is one of those people who uses his agenda to plan and run his day and he has spent some time making it as useful as possible. His video, Using Org-Agenda to run your life!, shows what his agenda looks like—spoiler: it’s not at all like the vanilla agenda—and some of the built-in shortcuts that he uses to interact with it.

The entire video is useful but what I found particularly useful (perhaps because of my abnormal use of the agenda) is the information he gives on entering dates and filtering agenda entries. I learned a few things that will definitely make my daily workflow easier. Even if you don’t use the agenda at all, the information on entering dates is worthwhile.

As for filtering agenda entries, it’s a much richer capability than I thought. You can filter on many different parameters, can combine multiple filters, and can refine filters by adding additional items. Take a look at the video to see how rich the capability is.

The video is 36 minutes 40 seconds long so you’ll need to schedule some time. It’s from a remote conference so there’s occasional distortion but it’s still worth watching.

-1:-- Advanced Usage of the Org Agenda (Post jcs)--L0--C0--May 20, 2020 06:44 PM

Cyberthal: Pubmind's "city" tiers -- from ranting notes to polished publication

Pretty path:
Pubmind | tiers | transformation | convenience | author vs audience

Pubmind's tiers measure the amount of transformation that has occurred from personal notes to public publication. Publication medium has some correlation to effort invested.

T1 = Finalized format. True publishing, in which format and thoroughness favor the reader at expense of the publisher's team. Most bestseller books and movies are T1. A mature website such as Wikipedia is also T1.

T2 = Edited text in a developing organization. E.g. polished blog posts arranged chronologically, when chronology isn't the canonical organization for the topics discussed. Hierarchical sites that evolve content for eventual publication in a different finished format. Scripted and edited video. Whether the author intends to improve the format or not, the possibility of doing so makes it T2 rather than T1. Format still conveniences the author rather than the reader, but not overwhelmingly.

T3 = untouched rough drafts organized chronologically. Dedicated rough drafts blog or vlog or a chat "scratchpad" channel are the best mediums for T3. Blog is for longform and chat is for medium-length. The author lazily spams his thoughts to gain the benefit of self-conscious improvement and maybe some immediate audience feedback, and to keep his audience roughly informed of his progress, without guaranteeing quality or accuracy.

A new zettelkasten with a few notes might be T1 if the author is carefully sourcing from a T2, or it might be a T2 if it's sourced from a personal knowledge base, or it might be a T3 if the author merely dumps his thoughts and timestamps them.

Think of Pubmind tiers as city tiers, the personal knowledge base as the countryside, and the thoughts as people. People travel from the countryside into cities. The more people concentrate, the higher the city tier gets. In the same way, thought density increases as Pubmind tier increases. At T1, myriad thoughtful organizational and presentation decisions have been made to facilitate communication of carefully selected and polished key concepts.

-1:-- Pubmind's "city" tiers -- from ranting notes to polished publication (Post Cyberthal)--L0--C0--May 20, 2020 05:56 PM

Cyberthal: org-roam's potential roles in Cyborganize

Pretty path:
Cyborganize | org-roam | potential roles | Pubmind T2-1

In Cyborganize, org-roam can be a T2 or T1 Pubmind. For example, a sci-fi author might use it for world-building notes for his novel. That would be a private T2 ZK.

On a computer, a Zettelkasten is always a Pubmind. Both word processors and wikis are closer to publishing than are text editors. The former are closer due to specializing in printed presentation, and the latter are closer due to a schema designed for online reader convenience.

ZK is not exactly a wiki, of course. But its original purpose of reshuffling polished fragments to make interesting academic papers is unmistakably a Pubmind T2 function.

The only medium in which a Zettelkasten can be a Textmind is physical paper. Then the notecards are the same as a text editor's files, because the "text editor" is a physics engine containing your hands plus office supplies.

Even then, a ZK is not sufficient, because Textmind also includes a chronological "rambling" journal.

To return to the hypothetical sci-fi author: He should write his rough drafts in Textmind and post them to a T3 private blog. Otherwise, if he writes them directly into his T2 ZK, he'll make a terrible mess. Mixing quality T2 posts with haphazard T3 trash makes for a difficult workflow. One ought not piss in aged whiskey.

-1:-- org-roam's potential roles in Cyborganize (Post Cyberthal)--L0--C0--May 20, 2020 05:28 PM

Cyberthal: org-roam's potential roles in Cyborganize

Pretty path:
Cyborganize | org-roam | potential roles | Pubmind T2-1

In Cyborganize, org-roam can be a T2 or T1 Pubmind. For example, a sci-fi author might use it for world-building notes for his novel. That would be a private T2 ZK.

On a computer, a Zettelkasten is always a Pubmind. Both word processors and wikis are closer to publishing than are text editors. The former are closer due to specializing in printed presentation, and the latter are closer due to a schema designed for online reader convenience.

ZK is not exactly a wiki, of course. But its original purpose of reshuffling polished fragments to make interesting academic papers is unmistakably a Pubmind T2 function.

The only medium in which a Zettelkasten can be a Textmind is physical paper. Then the notecards are the same as a text editor's files, because the "text editor" is a physics engine containing your hands plus office supplies.

Even then, a ZK is not sufficient, because Textmind also includes a chronological "rambling" journal.

To return to the hypothetical sci-fi author: He should write his rough drafts in Textmind and post them to a T3 private blog. Otherwise, if he writes them directly into his T2 ZK, he'll make a terrible mess. Mixing quality T2 posts with haphazard T3 trash makes for a difficult workflow. One ought not piss in aged whiskey.

-1:-- org-roam's potential roles in Cyborganize (Post Cyberthal)--L0--C0--May 20, 2020 05:28 PM

Irreal: Setting the Initial Visibility of Magit Sections

Like most Emacsers, I very seldom restart Emacs. When I do it’s usually because I just finished my weekly ELPA update. Despite my extensive configuration, Emacs starts up reasonably quickly for me but I still hate restarting it. The major reason is Magit. I love Magit but the first time I open the status page, the “Untracked Files” and “Unmerged Info” sections are expanded. For various reasons, these sections are fairly large in some of my repositories so I always have to close them. If I don’t do that, disaster is only a keystroke away when I accidental stage a large collection of untracked files and freeze Emacs for a minute or two and then another long wait when I undo the erroneous staging.

Obviously, this is a situation crying out for a remedy. The obvious approach is to look for some variables controlling which sections are displayed initially. It’s not hard to find it. The magit-section-initial-visibility-alist variable is an alist that controls whether a section is shown or hidden. That seems straightforward but the problem is discovering the names of the sections. They’re not the labels shown on the status page. I checked the source code but couldn’t find a list of the names. Finally, I dropped back to basics and RTFM. The manual has a section on matching section names. There I found the magit-describe-section-briefly function that displays information about the section under the point. The information is meant to help maintainers with debugging so it’s not very end-user friendly. However, part of the output is [XXX status] and the XXX is the name we’re after.

With that information at hand, I solved my problem by adding

(setq magit-section-initial-visibility-alist
        '((stashes . hide) (untracked . hide) (unpushed . hide)))

to my init.el. If you have other sections you’d like to control, you can use magit-describe-section-briefly to discover their names and add them to the alist. The available options are show and hide.

-1:-- Setting the Initial Visibility of Magit Sections (Post jcs)--L0--C0--May 19, 2020 04:48 PM

Sacha Chua: 2020-05-18 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-05-18 Emacs news (Post Sacha Chua)--L0--C0--May 19, 2020 12:25 AM

emacsninja: State of Emacs Lisp on Guile

Update: Added an extra set of benchmarks for Guile 3 in a Debian Sid Docker container.

Disclaimer: I don’t use Guile. I hardly know it. There are other Scheme implementations I know far better. But since Guile Emacs is a hot topic with much hopes and unproven claims, I experiment with it every now and then. All “benchmark” results here are to be taken with caution, they’ve been created using Guile 2.2.6 and Emacs 26.3 on a Thinkpad X230t running Arch Linux.

With that out of the way, laurus from #emacs[1] reminded me that one of the reasons why Guile Emacs was possible in the first place is Guile’s language tower, with Emacs Lisp being one of the supported languages. But what does that mean? How complete is the Emacs Lisp support? What can it be used for? These and a few other questions are the topic of this blog post.

In need of a spec

Standardized programming languages have the great benefit of being based on a specification one can consult whenever in doubt of how things are supposed to behave. This allows several competing implementations to be developed, with their own unique strengths and benefits. if you adhere to the standard, switching between implementations isn’t hard and can help shaking out bugs, for example when compiling your C programs with different compilers.

Things get considerably harder if your chosen language decided to forego this approach and the correct behavior is defined by it, yet this didn’t stop people from writing alternative implementations for programming languages such as Python and Ruby. Emacs Lisp got into a similar situation ever since Guile was extended to the degree of supporting Emacs Lisp as an additional language. Provided your version of Guile is new enough, you can evaluate trivial code in the REPL:

scheme@(guile-user)> (define foo 1)
scheme@(guile-user)> foo
$1 = 1
scheme@(guile-user)> ,L elisp
Happy hacking with Emacs Lisp!  To switch back, type `,L scheme'.
elisp@(guile-user)> (defvar bar 2)
$2 = bar
elisp@(guile-user)> bar
$3 = 2

So far so good. But how much of Emacs Lisp is supported? Not much apparently, many common functions like message and error are unbound. It doesn’t seem possible to do anything with buffers or files either. This greatly limits the possibilities of writing useful scripts in Emacs Lisp[2]. One way of determining what exactly is supported would be consulting the source code, but where’s the fun in that when you could instead test it programmatically, thereby creating an executable spec…

Generating the spec

The usual test approaches fail me. Reading test inputs via stdin with read-string? Accessing the arguments with argv? Reading from a file with insert-file-contents? Obtaining an environment variable with getenv? None of that is supported. At least you can print to stdout with princ. I went for a slightly different approach instead, obtain a list of functions/variables[3] in a minimal Emacs environment, then generating a test file that checks their existence and prints a test summary. Here’s the code generation part:

(defun printf (fmt &rest args)
  (princ (apply 'format fmt args)))

(printf ";; elisp spec adherence test
(defvar passed 0)
(defvar failed 0)
(defun test-sym (pred sym)
  (if (funcall pred sym)
      (setq passed (1+ passed))
    (setq failed (1+ failed))))
(defun test-fun (sym) (test-sym 'fboundp sym))
(defun test-var (sym) (test-sym 'boundp sym))\n\n")

(mapatoms
 (lambda (atom)
   (when (fboundp atom)
     (printf "(test-fun '%S)\n" atom))
   (when (and (not (keywordp atom)) (boundp atom))
     (printf "(test-var '%S)\n" atom))))

(printf "\n")
(printf "(princ \"Passed: \")\n")
(printf "(princ passed)\n")
(printf "(terpri)\n")
(printf "\n")
(printf "(princ \"Failed: \")\n")
(printf "(princ failed)\n")
(printf "(terpri)\n")

Assuming it’s been saved as gen-elisp-spec.el, the executable spec itself is generated with emacs -Q --batch --script gen-elisp-spec.el > elisp-spec.el. Here’s a test session using Emacs and Guile:

[wasa@box ~]$ time emacs -Q --batch --script elisp-spec.el
Passed: 9567
Failed: 2
emacs -Q --batch --script elisp-spec.el  0.10s user 0.02s system 99% cpu 0.117 total
[wasa@box ~]$ time guile --language=elisp elisp-spec.el
Passed: 137
Failed: 9432
guile --language=elisp elisp-spec.el  77.62s user 0.27s system 103% cpu 1:15.04 total

This is kind of surprising. I didn’t expect Emacs to fail its own test and didn’t expect Guile to implement this little either. Most surprising is the abysmal speed of the test[4], I’m looking forward to anyone being able to explain that part to me. Here’s one more test using the official Debian Sid Docker image with Emacs 26.3 and Guile 3.0.2:

root@d27668492764:/# time emacs -Q --batch --script elisp-spec.el
Passed: 9108
Failed: 2

real    0m0.104s
user    0m0.097s
sys     0m0.007s
root@d27668492764:/# time guile --language=elisp elisp-spec.el
Passed: 137
Failed: 8973

real    6m20.950s
user    10m32.294s
sys     0m7.846s

This is not exactly an improvement. At least the numbers are small enough to print out the offending symbols, for Emacs it’s atom and printf (which polluted the test environment), for Guile I’ve taken the liberty of annotating the list:

;; binding
let let*
;; functions
lambda apply funcall
;; evaluation
eval load eval-and-compile eval-when-compile
;; sequences
aref aset make-vector nth
;; sequencing
progn prog2 prog1
;; iteration
dolist while
;; control flow
if when unless cond
;; short-circuiting
or and not
;; explicit nonlocal exit
throw catch
;; exceptions
signal condition-case unwind-protect
;; input
read-from-minibuffer
;; output
prin1-to-string print princ send-string-to-terminal terpri
;; cxr
car cdr caar cadr cdar cddr
car-safe cdr-safe
nthcdr
;; associations
assoc assq
;; search
member memql memq
;; destructive list processing
nreverse setcar setcdr rplaca rplacd
;; other list processing
cons list make-list `
mapcar mapc
append concat
reverse
length
;; symbols
defconst defvar defun defmacro
get put
fset set setq setplist
symbol-function symbol-name symbol-plist symbol-value
intern make-symbol
fmakunbound makunbound
quote function
;; plist
plist-get plist-put
lax-plist-get lax-plist-put
plist-member
;; strings
string string-match substring
upcase downcase
;; predicates
zerop floatp stringp numberp integerp wholenump
boundp fboundp functionp symbolp
consp listp nlistp
atom null
;; math
1+ 1-
fceiling ffloor ftruncate fround float
abs
min max
;; comparators
> < >= <= /= =
eq eql equal
string-equal string=
;; numerical operators
+ - * %
;; misc
random

Some notable omissions and differences:

  • No division. Most likely incompatible with Scheme’s numeric tower.
  • Input is read with read-from-minibuffer, not read-string.
  • send-string-to-terminal is unusual to have, but most likely the primitive output function.
  • string-match is nice to have, but of limited use without match-string.
  • prin1-to-string exists, prin1 doesn’t.
  • print doesn’t add newlines and behaves like prin1 should.

To do anything outside of textbook exercises you’d need to define extra primitives. Guile’s module/language/elisp/boot.el shows how to apply a band-aid on some of the previous shortcomings:

(fset '/ (@ (guile) /))
(fset 'read-string 'read-from-minibuffer)
(fset 'prin1 (@ (guile) write))
(defun print (object) (prin1 object) (terpri))

You could write more of it to reach that goal of using Emacs Lisp as scripting language outside of Emacs, but need to write Scheme to get there. Why not just use Scheme? Why invent a new runtime? The effort would be comparable to what node.js did for Chrome’s JavaScript engine, except with a far weaker sales-pitch.

What does this mean for Guile Emacs?

What I’ve shown above is barely sufficient to bootstrap an Emacs on top of it. Guile Emacs requires a customized version of Guile and Emacs, then loads up the supporting Emacs Lisp files to do the rest. There are more incompatibilities, like called-interactively-p being stubbed out. Extending the presented rudimentary spec to contain actual tests would help with tracking progress and usability. It might even improve the overall quality of GNU Emacs itself, provided that the core developers are on board and believe in the idea. I’ve briefly searched emacs-devel for previous discussion on the topic, but only found bikeshedding about Guile Emacs itself, so anyone who feels strongly about the subject, feel free to start a discussion there!

With regards to Guile Emacs itself, the situation is trickier. The above repositories have not been touched for five years, with Robin Templeton being the sole contributor for two Google Summer of Code events. Even though the work is far from complete, it is impressive what a college student managed to do under supervision of Guile’s maintainer Andy Wingo. Further advancements require similarly motivated individuals to participate in the Guile community and become part of the effort, much like with other free software projects. It’s tempting to take a shortcut like donating to other developers, but unless they’ve figured out a way of converting that money into equivalent work, there will be little connection between what you give away and what they do in return. This again is a topic worth discussing, preferably with the people that can make a change.

[1]laurus did some research as well, you can find an interesting discussion on the #guile channel: http://logs.guix.gnu.org/guile/2020-05-16.log
[2]At least you could now solve SICP in Emacs Lisp with less footguns: You have bignums, lexical scoping by default and TCO!
[3]This isn’t exactly correct, what’s tested for is whether the symbol has its function/value slot bound which may contain other things, for example macros and keywords.
[4]Consider that people like to advocate for Guile Emacs with the argument that it will make for a faster Emacs. While this may hold true in the long term, it’s nowhere near close to that yet. Here’s hoping that Guile 3 will alleviate some of the pain…
-1:-- State of Emacs Lisp on Guile (Post Vasilij Schneidermann)--L0--C0--May 18, 2020 11:57 AM

Tory Anderson: Org view html

I export to HTML fairly often with orgmode. In this case “export and open” resulting in viewing the code is almost never what I want; it would be much more useful like the export pdf option, which doesn’t view to the LaTeX code but right to the PDF. Answer As per https://emacs.stackexchange.com/questions/2387/browser-not-opening-when-exporting-html-from-org-mode A setting change fixed this. M-x customize-variable org-file-apps and for files of type \\.x?html?\\' I specified firefox %s. Now it does what I want.
-1:-- Org view html (Post)--L0--C0--May 18, 2020 12:00 AM

Irreal: Roam Research

Those of you who have been paying attention know that I’m embarking on a project to implement a Zettelkasten to organize my notes and ideas. My current plan is to base this on Jethro Kuan’s org-roam. Org-roam is an Emacs package that attempts to replicate the capabilities of the Roam Research note taking application.

Given that the package I plan to use for the project is based on Roam, it’s worthwhile taking a look at Roam to get an idea of what it can do. Happily, Thomas Frank has a video that take a detailed look at the application. As you can see, Roam does an excellent job of implementing the Zettelkasten idea. It can even draw a graph of how your notes are linked. The program has already earned itself a cult following. All in all, it’s a great app.

Sadly, as with Notion, I can’t recommend Roam for the same reason I can’t recommend Notion: Your data lives on Roam Research’s servers and, as they say, they can terminate your account at any time for any reason. That doesn’t mean they will, of course, but the point of a Zettelkasten is to gather a lifetime’s collection of data and ideas and the last thing you need is to lose that data or even have your workflow destroyed. At least for the paranoid like me, an open source package that stores your data locally, as org-roam does, is a much safer bet.

Frank’s video is 14 and a half minutes long so you can probably watch it on a coffee break or at least easily find time to schedule it.

-1:-- Roam Research (Post jcs)--L0--C0--May 17, 2020 05:18 PM

emacsninja: State of Emacs Lisp on Guile

Disclaimer: I don’t use Guile. I hardly know it. There’s other Scheme implementations I know far better. But since Guile Emacs is a hot topic with much hopes and unproven claims, I experiment with it every now and then. All “benchmark” results here are to be taken with caution, they’ve been created using Guile 2.2.6 and Emacs 26.3 on a Thinkpad X230t.

With that out of the way, laurus from #emacs[1] reminded me that one of the reasons why Guile Emacs was possible in the first place is Guile’s language tower, with Emacs Lisp being one of the supported languages. But what does that mean? How complete is the Emacs Lisp support? What can it be used for? These and a few other questions are the topic of this blog post.

In need of a spec

Standardized programming languages have the great benefit of being based on a specification one can consult whenever in doubt of how things are supposed to behave. This allows several competing implementations to be developed, with their own unique strengths and benefits. if you adhere to the standard, switching between implementations isn’t hard and can help shaking out bugs, for example when compiling your C programs with different compilers.

Things get considerably harder if your chosen language decided to forego this approach and the correct behavior is defined by it, yet this didn’t stop people from writing alternative implementations for programming languages such as Python and Ruby. Emacs Lisp got into a similar situation ever since Guile was extended to the degree of supporting Emacs Lisp as an additional language. Provided your version of Guile is new enough, you can evaluate trivial code in the REPL:

scheme@(guile-user)> (define foo 1)
scheme@(guile-user)> foo
$1 = 1
scheme@(guile-user)> ,L elisp
Happy hacking with Emacs Lisp!  To switch back, type `,L scheme'.
elisp@(guile-user)> (defvar bar 2)
$2 = bar
elisp@(guile-user)> bar
$3 = 2

So far so good. But how much of Emacs Lisp is supported? Not much apparently, many common functions like message and error are unbound. It doesn’t seem possible to do anything with buffers or files either. This greatly limits the possibilities of writing useful scripts in Emacs Lisp[2]. One way of determining what exactly is supported would be consulting the source code, but where’s the fun in that when you could instead test it programmatically, thereby creating an executable spec…

Generating the spec

The usual test approaches fail me. Reading test inputs via stdin with read-string? Accessing the arguments with argv? Reading from a file with insert-file-contents? Obtaining an environment variable with getenv? None of that is supported. At least you can print to stdout with princ. I went for a slightly different approach instead, obtain a list of functions/variables[3] in a minimal Emacs environment, then generating a test file that checks their existence and prints a test summary. Here’s the code generation part:

(defun printf (fmt &rest args)
  (princ (apply 'format fmt args)))

(printf ";; elisp spec adherence test
(defvar passed 0)
(defvar failed 0)
(defun test-sym (pred sym)
  (if (funcall pred sym)
      (setq passed (1+ passed))
    (setq failed (1+ failed))))
(defun test-fun (sym) (test-sym 'fboundp sym))
(defun test-var (sym) (test-sym 'boundp sym))\n\n")

(mapatoms
 (lambda (atom)
   (when (fboundp atom)
     (printf "(test-fun '%S)\n" atom))
   (when (and (not (keywordp atom)) (boundp atom))
     (printf "(test-var '%S)\n" atom))))

(printf "\n")
(printf "(princ \"Passed: \")\n")
(printf "(princ passed)\n")
(printf "(terpri)\n")
(printf "\n")
(printf "(princ \"Failed: \")\n")
(printf "(princ failed)\n")
(printf "(terpri)\n")

Assuming it’s been saved as gen-elisp-spec.el, the executable spec itself is generated with emacs -Q --batch --script gen-elisp-spec.el > elisp-spec.el. Here’s a test session using Emacs and Guile:

[wasa@box ~]$ time emacs -Q --batch --script elisp-spec.el
Passed: 9567
Failed: 2
emacs -Q --batch --script elisp-spec.el  0.10s user 0.02s system 99% cpu 0.117 total
[wasa@box ~]$ time guile --language=elisp elisp-spec.el
Passed: 137
Failed: 9432
guile --language=elisp elisp-spec.el  77.62s user 0.27s system 103% cpu 1:15.04 total

This is kind of surprising. I didn’t expect Emacs to fail its own test and didn’t expect Guile to implement this little either. Most surprising is the abysmal speed of the test[4], I’m looking forward to anyone being able to explain that part to me. At least the numbers are small enough to print out the offending symbols, for Emacs it’s atom and printf (which polluted the test environment), for Guile I’ve taken the liberty of annotating the list:

;; binding
let let*
;; functions
lambda apply funcall
;; evaluation
eval load eval-and-compile eval-when-compile
;; sequences
aref aset make-vector nth
;; sequencing
progn prog2 prog1
;; iteration
dolist while
;; control flow
if when unless cond
;; short-circuiting
or and not
;; explicit nonlocal exit
throw catch
;; exceptions
signal condition-case unwind-protect
;; input
read-from-minibuffer
;; output
prin1-to-string print princ send-string-to-terminal terpri
;; cxr
car cdr caar cadr cdar cddr
car-safe cdr-safe
nthcdr
;; associations
assoc assq
;; search
member memql memq
;; destructive list processing
nreverse setcar setcdr rplaca rplacd
;; other list processing
cons list make-list `
mapcar mapc
append concat
reverse
length
;; symbols
defconst defvar defun defmacro
get put
fset set setq setplist
symbol-function symbol-name symbol-plist symbol-value
intern make-symbol
fmakunbound makunbound
quote function
;; plist
plist-get plist-put
lax-plist-get lax-plist-put
plist-member
;; strings
string string-match substring
upcase downcase
;; predicates
zerop floatp stringp numberp integerp wholenump
boundp fboundp functionp symbolp
consp listp nlistp
atom null
;; math
1+ 1-
fceiling ffloor ftruncate fround float
abs
min max
;; comparators
> < >= <= /= =
eq eql equal
string-equal string=
;; numerical operators
+ - * %
;; misc
random

Some notable omissions and differences:

  • No division. Most likely incompatible with Scheme’s numeric tower.
  • Input is read with read-from-minibuffer, not read-string.
  • send-string-to-terminal is unusual to have, but most likely the primitive output function.
  • string-match is nice to have, but of limited use without match-string.
  • prin1-to-string exists, prin1 doesn’t.
  • print doesn’t add newlines and behaves like prin1 should.

To do anything outside of textbook exercises you’d need to define extra primitives. Guile’s module/language/elisp/boot.el shows how to apply a band-aid on some of the previous shortcomings:

(fset '/ (@ (guile) /))
(fset 'read-string 'read-from-minibuffer)
(fset 'prin1 (@ (guile) write))
(defun print (object) (prin1 object) (terpri))

You could write more of it to reach that goal of using Emacs Lisp as scripting language outside of Emacs, but need to write Scheme to get there. Why not just use Scheme? Why invent a new runtime? The effort would be comparable to what node.js did for Chrome’s JavaScript engine, except with a far weaker sales-pitch.

What does this mean for Guile Emacs?

What I’ve shown above is barely sufficient to bootstrap an Emacs on top of it. Guile Emacs requires a customized version of Guile and Emacs, then loads up the supporting Emacs Lisp files to do the rest. There are more incompatibilities, like called-interactively-p being stubbed out. Extending the presented rudimentary spec to contain actual tests would help with tracking progress and usability. It might even improve the overall quality of GNU Emacs itself, provided that the core developers are on board and believe in the idea. I’ve briefly searched emacs-devel for previous discussion on the topic, but only found bikeshedding about Guile Emacs itself, so anyone who feels strongly about the subject, feel free to start a discussion there!

With regards to Guile Emacs itself, the situation is trickier. The above repositories have not been touched for five years, with Robin Templeton being the sole contributor for two Google Summer of Code events. Even though the work is far from complete, it is impressive what a college student managed to do under supervision of Guile’s maintainer Andy Wingo. Further advancements require similarly motivated individuals to participate in the Guile community and become part of the effort, much like with other free software projects. It’s tempting to take a shortcut like donating to other developers, but unless they’ve figured out a way of converting that money into equivalent work, there will be little connection between what you give away and what they do in return. This again is a topic worth discussing, preferably with the people that can make a change.

[1]laurus did some research as well, you can find an interesting discussion on the #guile channel: http://logs.guix.gnu.org/guile/2020-05-16.log
[2]At least you could now solve SICP in Emacs Lisp with less footguns: You have bignums, lexical scoping by default and TCO!
[3]This isn’t exactly correct, what’s tested for is whether the symbol has its function/value slot bound which may contain other things, for example macros and keywords.
[4]Consider that people like to advocate for Guile Emacs with the argument that it will make for a faster Emacs. While this may hold true in the long term, it’s nowhere near close to that yet. Here’s hoping that Guile 3 will alleviate some of the pain…
-1:-- State of Emacs Lisp on Guile (Post Vasilij Schneidermann)--L0--C0--May 17, 2020 12:15 PM

Chen Bin (redguardtoo): Hardcore spell checking in Emacs

This article is not introduction of Emacs spell checking basics. It requires deep knowledge of Emacs Lisp and Fly Spell.

You could read my article What's the best spell check setup in emacs for basic knowledge.

This article introduces new techniques to make Fly Spell more powerful and faster.

The CLI program aspell and hunspell can only parse plain text. They don't know any programming language syntax.

Fly Spell feeds the output of CLI program into its own Lisp predicate named flyspell-generic-check-word-predicate whose default value is nil.

When executing (flyspell-mode 1), the per mode predicate is assigned to flyspell-generic-check-word-predicate.

For example, you can run (get major-mode 'flyspell-mode-predicate) to get predicate of current major mode, (get 'web-mode 'flyspell-mode-predicate) to get predicate of web-mode.

The predicate is a simple function without parameter. Here is my predicate for web-mode,

(defun my-web-mode-flyspell-verify ()
  "Fly Spell predicate of `web-mode`."
  (let* ((font-face-at-point (get-text-property (- (point) 1) 'face))
         rlt)
    ;; If rlt is t, the word at point is POSSIBLY a typo, continue checking.
    (setq rlt t)
    ;; if rlt is nil, the word at point is definitely NOT a typo.
    ;; (setq rlt nil)
    rlt))
;; Attach my predicate to `web-mode`
(put 'web-mode 'flyspell-mode-predicate 'my-web-mode-flyspell-verify)

If you read code of flyspell-prog-mode, you will find it set flyspell-generic-check-word-predicate to its own predicate flyspell-generic-progmode-verify,

(defvar flyspell-prog-text-faces
  '(font-lock-string-face font-lock-comment-face font-lock-doc-face)
  "Faces corresponding to text in programming-mode buffers.")

(defun flyspell-generic-progmode-verify ()
  "Used for `flyspell-generic-check-word-predicate' in programming modes."
  (unless (eql (point) (point-min))
    ;; (point) is next char after the word. Must check one char before.
    (let ((f (get-text-property (1- (point)) 'face)))
      (memq f flyspell-prog-text-faces))))

As you can see, flyspell-generic-progmode-verify is very simple. If the word at point is not inside comment or string, the predicate returns nil which means the word is not a typo.

So in theory I can write my own predicate by following flyspell-generic-progmode-verify.

But in reality it's not as simple as it seems. The predicate is written in Lisp so it's slow. If it contains too much code, Fly Spell process might block other actions in Emacs. Emacs could be un-responsive when editing text.

The solution is not to start Fly Spell process too frequently.

The flyspell-mode starts checking when text in current buffer is modified.

My solution is not to turn on flyspell-mode. Instead, I manage the spell checking by myself using APIs from flyspell.

I only spell check when user saving current buffer. The interval between spell check should not be less than 5 minutes. Spell check is done by calling API flyspell-buffer

Checking the whole buffer is still slow. Instead, we can check the text region in current window by calling flyspell-region instead. The api window-total-height returns the height of current Windows. So I can use below code to get the region to check,

(let* (beg end (orig-pos (point)))
  (save-excursion
    (forward-line (- (window-total-height)))
    (setq beg (line-beginning-position))
    (goto-char orig-pos)
    (forward-line (window-total-height))
    (setq end (line-end-position)))
  (flyspell-region beg end))

I also need respect the predicate embedded in the major mode in my own generic predicate. Since per mode predicate has already checked the font face, I should skip the font face check in generic predicate if per mode predicate exists.

Above algorithms are implemented in wucuo. Here is its usage,

(defun prog-mode-hook-setup ()
  ;; (setq wucuo-flyspell-start-mode "lite")
  ;; (setq wucuo-flyspell-start-mode "ultra")
  (wucuo-start t))
(add-hook 'prog-mode-hook 'prog-mode-hook-setup)

If wucuo-flyspell-start-mode is "full" (default value), flyspell-mode is enabled. In this case, wucuo is only the advanced version of flyspell-prog-mode,

If wucuo-flyspell-start-mode is "lite", flyspell-buffer is used, checking is done when user saves current buffer.

If wucuo-flyspell-start-mode is "ultra", flyspell-region is used, checking is done when user saves current buffer.

-1:-- Hardcore spell checking in Emacs (Post Chen Bin)--L0--C0--May 17, 2020 06:20 AM

Toby 'qubit' Cubitt: Early-Years Science: Floating and Sinking

Setup time: ~5mins
Run time: 15-30mins
Age range: 3+

Goals

Investigate why things float or sink.
Introduce the idea of formulating and testing hypotheses.

You will need

  • 1 large, waterproof container. E.g. a bucket, basin, or watertight box. A bath or sink will also work fine.
  • A variety of objects of different shapes and sizes, and made out of different materials: stone, metal, plasic, wood. E.g. metal, plastic and wooden spoons of similar sizes; different size spoons; metal and plastic bottle tops; stones; corks; matchsticks.
  • Plasticine or play-dough.
  • A small plastic tub that fits in the big container.
-1:-- Early-Years Science: Floating and Sinking (Post Toby Cubitt (tsc25@cantab.net))--L0--C0--May 16, 2020 11:00 PM

Irreal: Emacs By Macros 6

Sahas Subramanian is back with another excellent episode of learning Emacs through keyboard macros. This video covers editing macros to correct or change a macro without starting over. If you have a long and complicated macro, that can be a real win.

He begins by showing how you can add some instructions to the last macro by simply calling kmacro-start-macro (usually bound to Ctrl+x ( or F3) with the universal argument. That can be useful but the real power comes from calling edit-last-kbd-macro. That brings up a buffer of the keystroke in the last macro and lets you edit them to correct errors or add or delete keystrokes. The nice thing about edit-last-kbd-macro is that there’s nothing to remember other than the name of the command so you can easily use it even though you probably won’t have the opportunity very often.

The video starts with Subramanian using occur to locate the function definitions in a C++ file. That’s tricky, of course, so the video provides an amusing real life example of building and correcting complex regular expressions. As I said last time, almost everyone watching Subramanian’s videos is going to bring experience with another editor with them so the idea regular expressions will be familiar and the video serves as a partial explanation of Emacs’ regular expression peculiarities.

-1:-- Emacs By Macros 6 (Post jcs)--L0--C0--May 16, 2020 03:49 PM

Irreal: Zamansky 71: Openwith

Mike Zamansky, freshly back from a bout with COVID-19, has a new video in his Using Emacs Series that considers the openwith package. The backstory is a long standing annoyance in Zamansky’s workflow: although he can open non-text files such as PDFs, PNGs, docx, and others, he can’t edit them and Emacs will choke if the file is too large.

What he wanted was an easy way to choose a file from Dired and open it with an external app—LibreOffice for docx, for example. That would save him from cluttering his desktop with a bevy of unneeded windows. The openwith package lets you associate an application with a list of file extensions and Emacs will use that application to open any files with that extension. In particular, if you type Return on a file in Dired, it will be opened in the external application instead of Emacs.

There is, I think, a problem with this solution: it’s all or nothing. Either the file is opened normally in Emacs or it is always opened by the external app. You can’t choose. Even if you open the file normally with find-file, the external application will be invoked. In some cases, it’s convenient to use the external app, and it others it’s more convenient to open the file in Emacs but with openwith you can’t choose. Zamansky also sees this as a problem but feels he can live with it and, of course, he can always turn off openwith. To be sure, that’s a pain but the need to use both Emacs and an external application on the same file type is apparently rare in Zamansky’s workflow.

In the comments, Zamansky offers an update saying that he’s discovered that openwith interferes with his mail client, mu4e. That’s a deal breaker and Zamansky will probably hunt for another solution. If you aren’t a mu4e user, you may find openwith a useful addition to your workflow.

The video is 14 minutes long so schedule some time. As usual with Zamansky’s videos, you won’t want to miss watching it.

-1:-- Zamansky 71: Openwith (Post jcs)--L0--C0--May 14, 2020 06:51 PM

Mike Zamansky: Using Emacs 71 Openwith

I spend most of my time in Emacs but still use the shell and browser for some things. One of the things I use my shell for is to launch libreoffice to view and edit docx files and spreadsheets, evince for pdf files and imagemagick for image files. Yes, I know I can view all of these in Emacs but there are a few limitations: Emacs chokes on large files I can't edit the docx file or the image So, I hop to the shell and launch the program I need on the files in question.
-1:-- Using Emacs 71 Openwith (Post)--L0--C0--May 13, 2020 03:45 PM

Eigenbahn: Auto-close Emacs interpreter buffers

Quitting a shell

On any other terminal emulator, typing exit or C-d would kill the shell process and the terminal window.

But Emacs doesn’t work this way.

When you exit a shell process, your shell buffer stays open:

$ ^D
exit

Process shell finished

And you’d have to C-x k-it manually1.

This can be annoying and we might want to change that.

But first we need to delve a bit in Emacs internals.

Emacs bestiary: shell, comint & process

The Emacs implementation of dealing with terminal emulation is divided in three API layers2:

  • the shell layer (dealt with previously on this blog: part 1 and 2)
  • the comint layer
  • the (inferior) process layer

The process layer deals with spawning inferior processes, be it synchronously (call-process and process-file functions) or asynchronously (make-process and start-process).

The comint is primarily comprised of a major mode (comint-mode) specifically suited for interacting with a special kind of processes: interpreters.

Finally, the shell layer is the higher-level set of APIs built on top of comint for dealing with shell interpreters.

Sentinels

The process layer offers to bind a sentinel to each spawned process: a callback function that gets run every time the process changes state.

Notably, it runs when the process dies.

So by crafting the appropriate sentinel, we can have the buffer close automatically when we exit its running process:

(defun my-kill-buffer-sentinel (process output)
  "Process sentinel to auto kill associated buffer once PROCESS dies."
  (unless (process-live-p process)
    (kill-buffer (process-buffer process))))

(let ((current-prefix-arg '(4)) ;; don't prompt for interpreter
      (shell-buffer (shell)))   ;; spawn shell and retrieve buffer
  (let ((process (get-buffer-process shell-buffer)))
    (set-process-sentinel process #'my-kill-buffer-sentinel)))

Generalizing

The previous example has 2 limitations:

  • some modes spawn comint buffers with custom sentinels, we don’t want to override them
  • me somewhat manually bind the sentinel to the shell buffer, something automatic would be better

First let’s deal with the first issue:

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

(require 'dash)

(defun add-my-kill-on-exit-sentinel ()
  "Replace current process sentinel with a new sentinel composed
of the current one and `my-kill-buffer-sentinel'."

  (let* ((process (get-buffer-process (current-buffer)))
         (og-sentinel (process-sentinel process))
         (sentinel-list (-remove #'null
                                 (list og-sentinel #'my-kill-buffer-sentinel)))
         (combined-sentinel
          (lambda (process line)
            (--each sentinel-list
              (funcall it process line)))))
    (setf (process-sentinel process) combined-sentinel)))

Calling add-my-kill-on-exit-sentinel creates a new sentinel from the one already bound to the buffer plus our my-kill-buffer-sentinel. Hence the original sentinel isn’t replaced but instead enriched.

Now for the second issue. Let’s automatically call add-my-kill-on-exit-sentinel on any new comint buffer:

(defvar my-kill-on-exit-comint-hook-has-run nil
  "Whether or not `kill-on-exit-comint-hook' has run or not.
We need this buffer-local var to prevent the hook from running
   several times, as can happen for example when calling `shell'.")

(defun my-async-funcall (function &optional buffer args delay)
  "Run FUNCTION with ARGS in the buffer after a short DELAY."
  (run-at-time (or delay 0.2) nil
               `(lambda ()
                  (with-current-buffer ,buffer ,(cons function args)))))

(defun kill-on-exit-comint-hook ()
  (unless my-kill-on-exit-comint-hook-has-run
    (setq-local my-kill-on-exit-comint-hook-has-run t)
    (my-async-funcall #'add-my-kill-on-exit-sentinel (current-buffer))))

(add-hook 'comint-mode-hook #'kill-on-exit-comint-hook)

We trig the calling of add-my-kill-on-exit-sentinel by registering a new hook callback to the comint-mode-hook.

The trick here is to wait for the comint derived modes to register their custom sentinel before enriching it. That’s why we use my-async-funcall.

Finally, comint-mode-hook can get triggered several times for a same buffer. To ensure we only apply our changes once, we define the state variable my-kill-on-exit-comint-hook-has-run with a buffer-local value.

Notes

  1. kill-this-buffer 

  2. Welp, there is also term-mode, a whole different beast ; volountarily omitted for the sake of conciseness. 

-1:-- Auto-close Emacs interpreter buffers (Post)--L0--C0--May 13, 2020 12:00 AM

Irreal: Better Emacs Configuration with use-package

Menno Finlay-Smits has an interesting post on using John Wiegley’s use-package package. It’s a fairly short post but Finlay-Smits makes a good case that the package make Emacs configuration cleaner and easier. As he also points out, it’s easy to arrange to have use-package defer loading of packages until they’re needed. If you’re the type of person who starts and stops Emacs a lot, that’s a win because it makes Emacs load faster. A feature that I really like is the ability to cause the installation of any packages not already present. I have my init.el set up so that I can create my entire Emacs environment just by loading a new Emacs with it. That’s great for moving to new machines.

Finally, although Finlay-Smits doesn’t mention it, another reason that I like use-package is that it’s a wonderful example of an Elisp macro. If you’ve used it, you know that use-package has many options that can operate in complex ways. If you want to see how a complicated macro is built, use-package is a good place to look.

-1:-- Better Emacs Configuration with use-package (Post jcs)--L0--C0--May 12, 2020 02:07 PM

Sacha Chua: 2020-05-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:-- 2020-05-11 Emacs news (Post Sacha Chua)--L0--C0--May 12, 2020 01:52 AM

Marcin Borkowski: Diffing and font-lock

I often work with diffs in Emacs. I usually do that within Magit, which highlights diffs in the usual way (highlighting deleted lines with reddish background, inserted lines with greenish background, and the deleted/inserted characters within these lines with slightly more prominent versions of the same colors). However, I sometimes use plain Emacs diff (e.g. to compare two fles not kept in Git), and I noticed an annoying thing: diff’s font-lock is applied on top of the usual font-lock, depending on the files’ syntax. While in general this seems resonable, in the case of LaTeX files in AUCTeX (where the font lock colors are especially diverse) this makes the diff completely unreadable. I was pretty sure that disabling the syntax font-lock would reduce the visual noise of the diffs.
-1:-- Diffing and font-lock (Post)--L0--C0--May 11, 2020 08:37 PM

Irreal: Zetteldeft

This is another entry in my series of posts on the idea of a Zettelkasten. Although I’ve mostly written about and am planning to use org-roam, that’s not the only possibility. Elias Storms built his own Zettelkasten by leveraging the Deft package and Org-mode. He built the system, which he calls Zetteldeft, for his own use but is sharing the code on GitHub.

Deft is a good starting point for a Zettelkasten because it stores each Deft note as a file in a flat hierarchy. That takes care of a lot of infrastructure for a Zettelkasten; the main thing that needs to be added is a way making and maintaining links between the notes.

Unlike org-roam, Zetteldeft does not maintain a database of backlinks. Instead, it has a function that will add a list of notes that contains a given search term. By calling this function with the ID of the current note, you can add a list of all notes that link to the current note. As far as I can tell, there’s no easy way to maintain this list other than deleting and rebuilding it.

Zetteldeft is written in a literate style so it’s easy to understand and hack on if you want to adopt it to your workflow. It’s a nice light-weight solution for implementing a Zettelkasten and provides an excellent starting point if you want to build your own unique implementation.

-1:-- Zetteldeft (Post jcs)--L0--C0--May 11, 2020 03:07 PM

Alvaro Ramirez: Enrich Emacs direds batching toolbox

11 May 2020 Enrich Emacs dired's batching toolbox

Shell one-liners are super handy for batch-processing files. Say you'd like to convert a bunch of images from HEIC to jpg, you could use something like:

 for f  in *.HEIC ;  do convert  "$f"  "${f%.*}.jpg";  done

Save the one-liner (or memorize it) and pull it from your toolbox next time you need it. This is handy as it is, but Emacs dired is just a file-management powerhouse. Its dired-map-over-marks function is just a few elisp lines away from enabling all sorts of batch processing within your dired buffers.

Dired already enables selecting and deselecting files using all sorts of built-in mechanisms ( dired-mark-files-regexp, find-name-dired, etc) or wonderful third-party packages like Matus Goljer's dired-filters.

Regardless of how you selected your files, here's a snippet to run ImageMagick's convert on a bunch of selected files:

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

(defun  ar/dired-convert-image (&optional arg)
   "Convert image files to other formats."
  (interactive  "P")
  (assert (or (executable-find  "convert") (executable-find  "magick.exe")) nil  "Install imagemagick")
  (let* ((dst-fpath)
         (src-fpath)
         (src-ext)
         (last-ext)
         (dst-ext))
    (mapc
     (lambda (fpath)
       (setq src-fpath fpath)
       (setq src-ext (downcase (file-name-extension src-fpath)))
       (when (or (null dst-ext)
                 (not (string-equal dst-ext last-ext)))
         (setq dst-ext (completing-read  "to format: "
                                        (seq-remove (lambda (format)
                                                      (string-equal format src-ext))
                                                    '("jpg"  "png")))))
       (setq last-ext dst-ext)
       (setq dst-fpath (format  "%s.%s" (file-name-sans-extension src-fpath) dst-ext))
       (message  "convert %s to %s ..." (file-name-nondirectory dst-fpath) dst-ext)
       (set-process-sentinel
        (if (string-equal system-type  "windows-nt")
            (start-process  "convert"
                           (generate-new-buffer (format  "*convert %s*" (file-name-nondirectory src-fpath)))
                            "magick.exe"  "convert" src-fpath dst-fpath)
          (start-process  "convert"
                         (generate-new-buffer (format  "*convert %s*" (file-name-nondirectory src-fpath)))
                          "convert" src-fpath dst-fpath))
        (lambda (process state)
          (if (= (process-exit-status process) 0)
              (message  "convert %s ✔" (file-name-nondirectory dst-fpath))
            (message  "convert %s ❌" (file-name-nondirectory dst-fpath))
            (message (with-current-buffer (process-buffer process)
                       (buffer-string))))
          (kill-buffer (process-buffer process)))))
     (dired-map-over-marks (dired-get-filename) arg))))

The snippet can be shorter, but wouldn't be as friendly. We ask users to provide desired image format, spawn separate processes (avoids blocking Emacs), and generate a basic report. Also adds support for Windows.

batch-dired.gif

BEWARE

The snippet isn't currently capping the number of processes, but hey we can revise in the future…

Update

Thanks to Philippe Beliveau for pointing out a bug in snippet (now updated) and changes to make it Windows compatible.

-1:-- Enrich Emacs direds batching toolbox (Post Álvaro Ramírez)--L0--C0--May 10, 2020 11:00 PM

Irreal: Zettelkasten Explained

I’ve finished reading Sönke Ahrens’ How to Take Smart Notes and, as promised, I’ve started exploring Jethro Kuan’s Org-roam as a way of implementing my own Zettelkasten. I’ve downloaded and installed Org-roam and am currently going over the documentation.

In the mean time, I’ve been doing some further reading on the Kettelkasten concept. I’m really excited about the idea and am looking forward to starting my own Zettelkasten. If you think the concept may be helpful in your own work or would like to find out, David B. Clear has an excellent article that explains the Zettelkasten idea and compares it to other ways of taking notes. He even shows you how to implement an index-card-based Zettelkasten similar to Luhmann’s original.

I don’t want to deep dive into the details of a Zettelkasten in this post but the idea that makes it work is the idea of linking notes that are somehow related. Rather than keeping the notes in some sort of hierarchy, they’re kept in a flat store and linked together by concept. Thus a given note might be linked to several other notes and the links might represent different concepts. The closest familiar idea is probably tags, which the Zettelkasten idea also supports, but tags are too coarse a discriminator. The goal is to start with an idea and be able to find all the notes that are relevant to that idea. You can think of the result as a graph where the notes are the nodes and edges are concepts.

That’s a simplified version, of course, so you should really take a look at Clear’s article if you want a more substantial explanation.

-1:-- Zettelkasten Explained (Post jcs)--L0--C0--May 09, 2020 03:45 PM

Tory Anderson: Improving my elisp by building an API to my YOURLS shortener

Until recently I was well-served by now-derelict url-shortener which worked well. It’s a cool library – very general, supporting a variety of shortening options. But when it broke, it was annoyingly complex to fix. Plus, I needed the excuse to sharpen my elisp skills a bit. The result is below. I learned a lot of good things (big thanks to the Reddit emacs community), including: Using defcustom to create customs groups for use in emacs’ nice customization tooling Utilizing url-build-query-string to build my… well, you know.
-1:-- Improving my elisp by building an API to my YOURLS shortener (Post)--L0--C0--May 08, 2020 12:00 AM

Raimon Grau: Recreational vimming


When I have to do some sort of development or file editing inside a container, I usually have vim there but not emacs. docker-tramp is very useful but sometimes I just want to edit there.
The .vimrc I have in my container has only one line (I can't function without it):
imap jk 
Let's say I'm editing a lua script. After I've saved and c-z and run the file several times, I realize what I want is to have is:
:nore ,rr :!lua %
Then I can test it much quicker. But I realize I'm always :w before,rr. Colon, up, and modify the line to:
:nore ,rr :w:!lua %
Accidentally I quit vim and realize I have to set that again, so I go to my vimrc and add this:
nore ,rr :w:!lua %
nore ,vimrc :e ~/.vimrc
nore ,so :source ~/.vimrc
With this I have a pretty nice way to iteratively finetune my config. After some lua editing, the only thing I need to do often (and not provided by the excellent vim default functionality) is to comment and uncomment code.
nore ,cc :s/^/--/
nore ,cu :s/^\( *\)--/\1/
This gives normal and visual comment/uncomment functionality, and enough interactivity to build your ad-hoc shortcuts as you go.
This is an example that just happened yesterday, and the nice thing is that it grows and flows from 0. I couldn't get to this amount of functionality from an emacs -Q in such a small time. It has such a different feeling to configuring emacs. It reminds me of my Perl days, it's fun and quick. And the language is very orthogonal, with very few abstractions. It's the APL of text editing.

This is my take on this reddit thread. 
-1:-- Recreational vimming (Post Raimon Grau (noreply@blogger.com))--L0--C0--May 07, 2020 06:08 PM

Irreal: Learning Emacs with Macros 2–5

After I wrote about the first Learning Emacs with Macros video, I kept an eye out for subsequent episodes because I really liked the first. I didn’t see any but in the latest edition of Sacha’s Emacs News I saw that Subramanian was already up to episode 5. I watched episodes 2 through 5 and can recommend them too.

At first, learning keyboard macros and Emacs at the same time seems odd. How can n00bs possibly understand macros at the same time they’re learning basic Emacs editing? That was my first thought but then I realized that most people learning Emacs are not like my Aunt Millie. Almost all of them are probably developers with experience using another editor and bring a certain sophistication to the endeavor. By combining elementary Emacs actions with keyboard macros, Subramanian helps the new Emacser understand one reason why learning Emacs is worthwhile: it makes it easy to perform complex actions.

These videos carry on with the same base file that the first one produced. Subramanian shows how to perform various transformations on the file using macros and the new Emacs commands that each video introduces. In Video #5, he shows how to generate the original file from scratch using macro counters.

If you’re an experienced Emacs user but you’re not used to using keyboard macros or use them only in an elementary way, you’ll probably learn some useful techniques from these videos. And they’re enjoyable to watch. Definitely recommended.

-1:-- Learning Emacs with Macros 2–5 (Post jcs)--L0--C0--May 07, 2020 03:41 PM

Eigenbahn: Fast Clojure dependency hot-reload

About Clojure

Clojure is great. I love it.

But like most great things it has its downsides.

One of which is the startup time.

There are workarounds to this1 but the lost common solution is to try avoiding as much possible to restart your process.

That’s not too much of an issue as Clojure was built with interactive development in mind (hello Mr REPL) and additional tooling (such as CIDER) push things a step further.

But there is one case when you still usually have to restart the REPL: when adding dependencies.

Pomegranate

Pomegranate is a library that allows to import dependencies without having to restart your process.

You of course first need to have it in your project dependencies:

(defproject pomegranate-test "0.1.0-SNAPSHOT"
  ;; ...
  :dependencies [[org.clojure/clojure "1.10.1"]
                 [clj-commons/pomegranate "1.2.0"]])

Then, let’s say you wanted to import clj-http. In your REPL, you just have to do the following:

(use '[cemerick.pomegranate :only (add-dependencies)])
(add-dependencies :coordinates '[[clj-http "3.10.1"]]
                  :repositories (merge cemerick.pomegranate.aether/maven-central
                                       {"clojars" "https://clojars.org/repo"}))

youWereExpectingMeToTypeAllThis.png

That’s a big hunk of text to copy paste…

What could we do to make our life easier?

Mhm, wait a second, we are using Emacs with CIDER, don’t we?

Let’s hack something quick in elisp!

Emacs helper command

(defun prf/cider/send-to-repl (sexp &optional eval ns)
  "Send SEXP to Cider Repl. If EVAL is t, evaluate it.
Optionally, we can change namespace by specifying NS."
  (cider-switch-to-repl-buffer ns)
  (goto-char cider-repl-input-start-mark)
  (delete-region (point) (point-max))
  (save-excursion
    (insert sexp)
    (when (equal (char-before) ?\n)
      (delete-char -1)))
  (when eval
    (cider-repl--send-input t)))

(defun prf/clj/pomegranate-dep (dep)
  "Format a Clojure Pomegranate dependency import for DEP."
  (concat
   (format
    "%s"
    ;; NB: this is clojure!
    `(use '[cemerick.pomegranate :only (add-dependencies)]))
   (s-replace-all
    `(("\\." . ".")
      ("mydep" . ,dep))
    (format
     "%S"
     ;; NB: this is clojure!
     `(add-dependencies :coordinates '[mydep]
                        :repositories (merge cemerick.pomegranate.aether/maven-central
                                             {"clojars" "https://clojars.org/repo"}))))))

(defun prf/cider/inject-pomegranate-dep (&optional dep ns)
  "Auto-import DEP in the current Clojure Repl using Pomegranate.
Optionally, we can change namespace by specifying NS."
  (interactive)
  (setq dep (or dep (read-string "Dep: ")))
  (prf/cider/send-to-repl (prf/clj/pomegranate-dep dep) t ns))

Now, from any project buffer (Clojure source file of REPL), we can just:

M-x prf/cider/inject-pomegranate-dep
Dep: [clj-http "3.10.1"]

And this should auto-switch to our running REPL buffer and let Pomegranate do its magic!

Notes

-1:-- Fast Clojure dependency hot-reload (Post)--L0--C0--May 06, 2020 12:00 AM

Alvaro Ramirez: Emacs: connect my Bluetooth speaker

06 May 2020 Emacs: connect my Bluetooth speaker

Connecting and disconnecting bluetooth devices on macOS is fairly simple: use the menu bar utility.

macos-menu.png

But could we make it quicker from our beloved editor?

Turns out with a little elisp glue, we can fuzzy search our Bluetooth devices and toggle connections. We can use Oleh Krehel's ivy-read for fuzzy searching and Felix Lapalme's nifty BluetoothConnector to list devices and toggle Bluetooth connections.

As a bonus, we can make it remember the last selected device, so you can quickly toggle it again.

(defun  ar/ivy-bluetooth-connect ()
   "Connect to paired bluetooth device."
  (interactive)
  (assert (string-equal system-type  "darwin")
          nil  "macOS only. Sorry :/")
  (assert (executable-find  "BluetoothConnector")
          nil  "Install BluetoothConnector from https://github.com/lapfelix/BluetoothConnector")
  (ivy-read  "(Dis)connect: "
            (seq-map
             (lambda (item)
               (let* ((device (split-string item  " - "))
                      (mac (nth 0 device))
                      (name (nth 1 device)))
                 (propertize name
                             'mac mac)))
             (seq-filter
              (lambda (line)
                 ;;  Keep lines like: af-8c-3b-b1-99-af - Device name
                (string-match-p  "^[0-9a-f]\\{2\\}" line))
              (with-current-buffer (get-buffer-create  "*BluetoothConnector*")
                (erase-buffer)
                 ;;  BluetoothConnector exits with 64 if no param is given.
                 ;;  Invoke with no params to get a list of devices.
                (unless (eq 64 (call-process  "BluetoothConnector" nil (current-buffer)))
                  (error (buffer-string)))
                (split-string (buffer-string)  "\n"))))
             :require-match t
             :preselect (when (boundp 'ar/misc-bluetooth-connect--history)
                         (nth 0 ar/misc-bluetooth-connect--history))
             :history 'ar/misc-bluetooth-connect--history
             :caller 'ar/toggle-bluetooth-connection
             :action (lambda (device)
                      (start-process  "BluetoothConnector"
                                     (get-buffer-create  "*BluetoothConnector*")
                                      "BluetoothConnector" (get-text-property 0 'mac device)  "--notify"))))

connect-disconnect.gif

comments on twitter.

-1:-- Emacs: connect my Bluetooth speaker (Post Álvaro Ramírez)--L0--C0--May 05, 2020 11:00 PM

Irreal: Minibuffer Help

Just a quickie today. Marcin Borkowski (mbork) has a useful post on providing help in the minibuffer. It turns out that you can always type Ctrl+h when responding to a prompt in the minibuffer. If you have some code prompting for input using read-string you can specify what that help will be, either as a string or some other form based on context.

Take at look at mbork’s post for the details. If you’re taking input from the minibuffer it’s a good thing to know.

-1:-- Minibuffer Help (Post jcs)--L0--C0--May 05, 2020 04:42 PM

Sacha Chua: 2020-05-04 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-05-04 Emacs news (Post Sacha Chua)--L0--C0--May 05, 2020 02:06 AM

Cyberthal: Pubmind's tentative T1 tool unveiled: Neuron Zettelkasten

After reading about the Neuron implementation of Zettelkasten, I've had a breakthrough. Zettelkasten (ZK) is Pubmind's preferred T1 publication format. ZK is liberated from the flat namespace of the wiki and the linearity of a strict hierarchy. It has better link permanence than a T2 Hugo site.

As for how to handle text flow from T2 to T1: the rule is DRY. Text gets promoted from T2 to T1 same as from Textmind to T3. Only blog posts are permanent, because they're chronological by nature. Categorical pages must be dynamic. The T2 Hugo is merely a development zone for eventual T1 ZK graph.

ZK is much easier to learn from than linear hierarchical instructional materials, because one can easily navigate to suit one's preferred learning path, without getting disoriented or missing key info. However, achieving this facility requires more work by the author and greater mastery of the material.

Thus it's ideal to attempt ZK authorship only after reaching the limits of the linear hierarchical medium in a T2 Hugo.

Neuron has an associated Emacs mode, so I hope that Treefactor will work for it as it does for Hugo.

-1:-- Pubmind's tentative T1 tool unveiled: Neuron Zettelkasten (Post Cyberthal)--L0--C0--May 04, 2020 05:12 PM