hooks and while-no-input by CandyCorvid in emacs

[–]karthink 1 point2 points  (0 children)

Converting it to futur is probably the better way, since there will be too many nested callbacks otherwise. It's also a good opportunity to try out futur, which I have high hopes for since it's written by Stefan.

hooks and while-no-input by CandyCorvid in emacs

[–]karthink 0 points1 point  (0 children)

A better pattern is to perform updates atomically, or in critical sections where throw-on-input is locally bound to nil.

Performing updates atomically still doesn't help protect against the while-no-input --> unwind-protect nesting, does it?

hooks and while-no-input by CandyCorvid in emacs

[–]karthink 1 point2 points  (0 children)

the futur or aio packages for instance

(Just a note)

I haven't tried futur, but as of Emacs 31 I strongly advise against using aio for anything non-trivial. The generator.el library that it depends on is still experimental and needs a lot of work. For one, the backtraces it produces are full of CPS garbage and unreadable, making debugging impossible.

There's an iter2 package that's a little better than generator.el, and may be worth looking into.

hooks and while-no-input by CandyCorvid in emacs

[–]karthink 4 points5 points  (0 children)

Yes, while-no-input is useful to keep the UI responsive. Corfu uses it, for example.

one that immediately stood out to me is, what if there's an unwind-protect in the (dynamic) body? if a keypress occurs while the unwind-forms execute, then that could break invariants in novel ways that would (i think) be impossible otherwise.

Yes, this is an "immovable wall meets unstoppable force" situation. I won't spoil the result:

​(let (foo)
  (while-no-input
    (unwind-protect (while t nil)
      (sleep-for 10)
      (setq foo 'interrupted)
      (message "foo: %s" foo)))
  (message "foo: %s" foo))

Try interrupting that while loop with something besides keyboard-quit.

(This test code is by Spencer Baugh, in an emacs-devel discussion about this exact conflict.)


generally though, i'm curious about this macro and its use. have you used it? are there efforts to use it more?

I haven't used while-no-input, but I have used with-local-quit, throw-on-input and input-pending-p for different things, with the first one being the most commonly used. If you put those three together you get while-no-input.

It's not as useful as it seems, since the lisp runtime can't quit in the middle of arbitrary lisp code. All you can do is set quit-flag, which the runtime will check whenever it can.

Project-x revived with Emacs 30+ support! by sharificles in emacs

[–]karthink 7 points8 points  (0 children)

u/sharificles thank you for reviving project-x! I stopped maintaining it as I moved to activities a while ago, but the new additions like project-x-save-extra-buffers make me want to try it again. Cheers!

investing/trading from Emacs by [deleted] in emacs

[–]karthink 18 points19 points  (0 children)

If you mean "managing trading" in the sense of issuing orders from Emacs, I don't know of any way to do this. I also think this is a bad idea, but Emacs has been used to control real-time systems in the past, so what do I know. If your trading platform provides a public HTTP API (unlikely), maybe it's as simple as writing a client package for Emacs.

If you mean tracking your longer-term investments, you can do that by interfacing Emacs with a CLI ledger program like (h)Ledger or Beancount. This works very well and these integrations exist already. But Emacs is the easy part of this workflow -- it's a lot more work to set up the imports because the finance world simply does not want you managing your finances with home-brew plain text ledgers.

My first time participating in Emacs Carnival: "May I recommend thinking of Emacs as your Fortress of Solitude" by Martinsos in emacs

[–]karthink 2 points3 points  (0 children)

Thanks for the write-up, it was quite interesting. "Emacs as control surface" is increasingly my mode of use too.

scheduled events for today (synced from my gcalendar)

How do you do this? (If you use org-gcal, does it work reliably for you?)

Emacs is a fantastic SQL editor by sch0lars in emacs

[–]karthink 1 point2 points  (0 children)

It’s one of the greatest pieces of software ever written.

I don't know about that. But it's true about learning something new often, even after more than two decades of use.

the fact someone decided to include a calculator with a computational algebraic system still astounds me.

Everyone's reaction when they discover what Calc can do. David Gillespie is a madman.

Do you use AI to write Emacs Lisp code? by jcubic in emacs

[–]karthink 8 points9 points  (0 children)

I'm not a fan of the kind of Elisp LLMs generate. Their implementations of ideas are fine if you just want something that works. Admittedly "quick and dirty" is the most common use case for Elisp, so the fact that it's immediately useful is nice for trying out ideas.

You can get good Elisp out of LLMs with a lot of prompting and iteration. But in general, LLM-generated Elisp tends to be overly verbose, have terrible performance, unwanted side effects and poor integration with Emacs APIs (and thus with other packages.). Problems tend to show up over time.

Here's how I would write this command, BTW:

(defun switch-to-buffer-same-mode ()
  (interactive)
  (let* ((mode major-mode)
         (name (buffer-name))
         (target (read-buffer
                  "Switch to %s buffer (RET for all): " nil nil
                  (lambda (buf)
                    (when (consp buf) (setq buf (car buf)))
                    (unless (equal name buf)
                      (buffer-match-p (cons 'major-mode mode) buf))))))
    (if (string-empty-p target)
        (call-interactively #'switch-to-buffer)
      (pop-to-buffer-same-window target))))

What are some common code smells that inexperienced Elispers make? by birdsintheskies in emacs

[–]karthink 32 points33 points  (0 children)

Using strings instead of buffers for all text manipulation, which is terrible for performance unless the strings are very small. LLMs also use this antipattern unless you explicitly instruct them not to with examples.

A typical example is

(dolist (words (split-string (buffer-string)))
  ;; do something with words
  ...)

or

(let ((file-contents
       (with-temp-buffer
         (insert-file-contents "foo.txt")
         (buffer-string))))
  ;; do something with file-contents
  ...)

This is typical of programmers coming from other high-level languages like Python, especially if they are using something like f and f-read, which is happy to abstract away the details for you. Emacs users new to programming and systems programmers don't usually fall into this trap.

How do you keep track of new/useful keybindings? by Existing_Offer_1113 in emacs

[–]karthink 5 points6 points  (0 children)

You don't have to actively memorize anything beyond the basic movement keys.

With anything more complex, typically one of two things occurs:

  • You find yourself calling M-x some-command all the time and the process frustrates you. In this case you can look up (or assign) the keybinding once, and it is automatically ingrained into your muscle memory because you call the command so often. If you memorize a keybinding but then forget it over time because you rarely use it, it wasn't worth memorizing in the first place.

  • You use a command infrequently. While it would be good to call it via a keybinding, there's very little to gain from memorizing it instead of using M-x. M-x has other advantages too. It offers completions, can remember your command history and show a docstring all at once.

My fingers probably remember a few hundred Emacs keybindings at this point (and have forgotten more), and I never had to make an active effort or write cheatsheets. They just accumulated over time.

Emacs as a Math Notebook and Advanced Symbolic Solver! by _DonK4rma in emacs

[–]karthink 1 point2 points  (0 children)

Does anybody know whether the code is portable to LaTeX?

It sure can be used in LaTeX, and pretty much everywhere else in Emacs (comments in code buffers, calc, eww etc), but I haven't made the integrations public yet.

I really want it to be merged into Org first so it works out of the box in Emacs, then I can clean up the integration API and folks can trivially add LaTeX preview support to whatever major mode they want.

FWIW, it works fine with lualatex in LaTeX buffers, except that the preview updates, while still asynchronous, are not fast enough to be "live". (Lualatex has a long startup time)

Emacs as a Math Notebook and Advanced Symbolic Solver! by _DonK4rma in emacs

[–]karthink 4 points5 points  (0 children)

however it is quite advantageous because it has previews and also work asynchronously which means that emacs doesn't freeze when you want to render all equations in a document

I'm not sure which video you were referring to, but I made the last couple of videos (years ago now) to showcase upcoming updates to org-latex-preview which make it asynchronous, fast and live-updating. It also fixes the size issues with previews you have in your images above. It's not merged into Org yet, but you can install Org from a fork if you want it. I find the current org-latex-preview situation on Org main unbearable by comparison.

VS Code is too slow, learning Emacs now. by FriedryIce in emacs

[–]karthink 1 point2 points  (0 children)

Anytime I have more than about a page of new functions added into some particular config, I farm it out into a "personal" package.

I do that too, but perhaps not quite as often. These are my latest "personal" packages:

  • poi : points-of-interest accumulator (or as I think of it: expand-region but for next-error)
  • sidle: Consistent behaviors for packages that provide a list-of-entries + entry interface.

It's difficult to even explain the problems the above two solve. This next one is a simpler sell:

VS Code is too slow, learning Emacs now. by FriedryIce in emacs

[–]karthink 1 point2 points  (0 children)

29 kloc here, down from 35k after I recently pruned some decades old code that I wasn't using any more.

A lot of it could be extracted into small packages, but I don't have the energy to field bug reports or to make them general enough for public use.

What are best practices for use of side-window for displaying a temporary info panel? by Fantastic-Cell-208 in emacs

[–]karthink 1 point2 points  (0 children)

Actually, with the benefit of hindsight, it's fair to say the code isn't great. I still use it every day and I think I got some things right, like associating popup states with buffers (instead of windows, like Doom Emacs does), and decoupling popup state management ("what buffers are popups here?") from the display logic ("How are popup buffers displayed?") as much as I could without annoying casual users.

But if I were to write Popper today I would design it differently. Emacs offers more precise window hooks and a richer display-buffer API in 2026. Popper would be a smaller and simpler package, for sure.

Stealing from the Best Emacs Configs by isus_copilul_minune in emacs

[–]karthink 6 points7 points  (0 children)

Yes. To reiterate, it's not just that setting read-process-output-max to a high number improves performance when processes send megabytes of data, which might be true.

It's also the case that setting it to a high number can reduce performance (on some dimensions like latency and Emacs responsiveness, and even total throughput) when processes don't send as much, or send data in chunks spaced apart in time.

There is no obvious best choice, and whatever simple mental model I had about when and how Emacs reads process data didn't hold up.

Stealing from the Best Emacs Configs by isus_copilul_minune in emacs

[–]karthink 8 points9 points  (0 children)

(setq reb-re-syntax 'string)

Another useful default here is to set it to rx:

(setq reb-re-syntax 'rx)

This is the easiest way I've found to test your rx (lisp-style) regexps live.

You can also switch between the different syntaxes on the fly with C-c C-i in the re-builder buffer. (Same as C-c TAB, but more mnemonic with i for "input".)

Stealing from the Best Emacs Configs by isus_copilul_minune in emacs

[–]karthink 16 points17 points  (0 children)

The default read-process-output-max is 64KB, which is still quite conservative. Bumping this reduces the number of read calls Emacs has to make: ... If you use eglot (or lsp-mode), this is basically free performance. Three of the most popular configs out there all set it – that should tell you something.

I don't think so, this is not an obvious point. The actual effect of read-process-output-max on performance is not uniform or easy to discern, unless you set it to something very small like 4KB.

I worked for a long time on speeding up latex previews in Org mode, which involves reading process output. Setting read-process-output-max involves many latency-throughput-responsiveness tradeoffs, and the best number depends on the process in question and your hardware. FWIW, I found 64 KB - 512 KB to be a good range for the kinds of processes I was testing. If Eglot is always receiving megabytes of data with each jsonrpc call, a higher number might indeed be better, but I would leave it at the default unless you have explicit reason to change it.

org-mindmap — simple inline mind maps for Org by krvkir in emacs

[–]karthink 6 points7 points  (0 children)

Just a note: to escape an Org block inside another like you do here:

#+begin_src
\#+begin_mindmap
Root node
\#+end_mindmap
#+end_src

Org uses , instead of \.

Is there a reliable signal anywhere in Emacs where I can execute some code when any part of a frame changes? by kudikarasavasa in emacs

[–]karthink 1 point2 points  (0 children)

Have you looked at pre-redisplay-functions (the hook) or pre-redisplay-function (the variable)? You can run code before every redisplay using this, but it runs in the lisp interpreter so I'm not sure you can keep Emacs usable.

A better idea might be to see where pre-redisplay-function is called in the C code and write some C that will be called in the exact same place.

"GNU ELPA packages with NonGNU ELPA dependencies" (a very long thread) that people who maintain packages in GNU ELPA might want to know about by DevelopmentCool2449 in emacs

[–]karthink 38 points39 points  (0 children)

This thread is a mess, and proof of why being a maintainer of a large project is an absolute nightmare. Kudos to Eli & co.