Emacs Chat 24: Omar Antolin Camarena
Posted: - Modified: | emacs, emacs-chat-podcast, emacs-chat: Updated transcript and added a link to Karthik's notes.
I chatted with Omar Antolín Camarena about Emacs, keyboard macros, temporary buffers, Embark, and other workflow tips.
View in the Internet Archive, read the transcript online, watch or comment on YouTube, download the audio or the transcript, or e-mail me.
Related links:
- Omar Antolín Camarena: a researcher at Instituto de Matemáticas, UNAM in Mexico City
- M-x apropos Emacs
- oantolin/emacs-config: My personal Emacs configuration · GitHub
- oantolin/placeholder: Emacs package to treat any buffer as a template with placeholders to fill-in · GitHub
- oantolin (Omar Antolín Camarena) · GitHub
- Omar Antolín (@oantolin@mathstodon.xyz) - Mathstodon
- u/oantolin on Reddit
- #Emacs #Embark with Omar Antolin, Ramin Honary and Kent Pitman #lisp and more #interview #lispyGopherClimate - toobnix
- Karthik's notes on Emacs Chat 24: Omar Antolin Camarena
You can add the iCal for upcoming Emacs Chat episodes to your calendar. https://sachachua.com/topic/emacs-chat/upcoming-emacs-chats.ics
Find more Emacs Chats or join the fun: https://sachachua.com/emacs-chat
Chapters
- 0:00 Ignore this part
- 0:18 Opening
- 0:46 How did you get into Emacs in the first place?
- 6:01 Repeating edits
- 7:28 dot-mode: repeating commands
- 9:24 block-undo: undo things as a chunk
- 10:29 Starting and stopping keyboard macros
- 12:15 Keycast and Embark
- 13:33 apply-macro-to-lines-of-paragraph
- 16:34 embark-on-last-message
- 18:06 tmp-buffer with a major mode
- 19:26 placeholder
- 20:38 enable-recursive-minibuffers
- 22:57 Overriding embark-select
- 23:32 quick-calc
- 26:30 Multiple cursors
- 27:40 Block-undo and regular undo
- 28:53 Cycling through Embark targets
- 31:39 Imenu for navigation
- 32:51 Collaboration
- 38:01 Technology adoption and Emacs packages
- 40:06 Personal packages and naming conventions
- 42:26 find-file-at-point and directory names
- 43:49 The value of using Emacs’s APIs
- 44:56 org-ql and usual files
- 47:06 Shortcuts for org-ql search syntax
- 47:43 Org TODO states: TODO, WAIT, DONE, NOPE
- 48:26 The inserter macro
- 50:05 luggage: generative art experiments
- 53:49 Teaching and Emacs
- 54:53 The print10 generator
- 56:23 arXiv
- 58:29 Toggle keymap
- 1:00:54 isearch-delete-wrong
- 1:03:14 isearch - continue from the beginning of the match
- 1:05:12 Using keymaps to remember sets of commands
- 1:06:04 Other things from the config
Transcript
Expand this to see the transcript and screenshots
c w, and then you change the word, and then that thing gets repeated. In Emacs, to change a word, it's not a single unit, right? You delete the word, and then you type in something new, and each character you type is running insert-char. dot-mode will coalesce all of that into a single keyboard macro that you can repeat, right? If you do some motion command that doesn't modify the buffer, and then you delete a word and type a new word, everything from the deletion to the end of the typing would be what dot mode repeats. The experience is actually very similar to using dot in Vim. In my opinion, a little bit better, because in Vim, I often had this problem. It gets you into this competitive video game mentality. How do I do the edit in a single repeatable command? I want to be able to use dot to do this again. So that you have to think ahead. It's kind of distracting. Of course, if a sensible person would not get caught up in that, it would just... do the edit whichever way they can, but I wanted to maximize the repeatability. dot-mode lets you be a little bit more relaxed. It still catches all of the thing that should have been a single edit. So yeah, I like it a lot. Sacha: So that's dot-mode.
Sacha: You also mentioned block-undo. Omar: That is a package of mine I can show you. That's the entire package. It just uses this with-undo-amalgamate command. Whatever you run inside with-undo-amalgamate undoes in a single step. I use it for executions of keyboard macros. A keyboard macro, if you run it all over the place, if you apply it to every line in a region, or you just repeat it a hundred times, that is a lot of tiny individual edits. If you undo that, you do not want to undo them one by one. This just makes them all undo in a single step, which is what Vim does, actually. This is one of the things that I said, no, Vim has this right. I need this in Emacs. Sacha: Okay, that makes sense. So dot-mode is more like implicit keyboard macro boundary definitions. This one is like the undo-ness of it.
Sacha: I saw in your config, you also have more convenient shortcuts for starting and stopping keyboard macros. It's like a modifier and the keystroke instead of two or like function keys, which are further away. I'm guessing you use keyboard macros a lot. Omar: Yeah, I do. When I got rid of dot-mode, it was an experiment to see if I could just remember to record keyboard macros. The thing that the dot-mode or the dot command in Vim solves is that you don't always have the foresight to record a keyboard macro. Sometimes you realize, oh, I need to do the same at some other places, but you didn't record it ahead of time. Then you wind up doing it once, realizing you need to do it a bunch of times, then recording the macro, then doing it again. I wanted to see if I could remember to record macros. I decided that I needed to make it as as frictionless as possible. This is the command that is bound by default to F3. I like it better than the thing that's bound to C-x ( because this kmacro-start-macro-or-insert-counter does both things. It could start a recording, or if you are recording, it will insert the keyboard macro counter. Sacha: For folks who are like, what? Macros? Counters? Yes, you can have your keyboard macro automatically add one to a number, for example. There you go.
Sacha: Hello, hello, hello.
Omar: I also activated keycast. I hope people can follow along. I have some small modifications to make embark transparent to keycast. If I use embark, you see embark-act, but then you also see what command I call. Sacha: I just stole that from your config. I wasn't entirely sure if I was using it correctly, but it definitely looked like something interesting and useful. Omar: If you don't use that change, then keycast doesn't see through embark and you don't get which actions you called. Sacha: Yeah, the opacity of some of these kind of key binding niceties... they hide a lot of stuff from the standard Emacs ways of doing things. That's one of the criticisms of transient and other tools. I'm glad that you're finding these ways to make these packages work well with other packages. Omar: I think this was by request. Somebody requested it. Maybe it was Prot. It's definitely a good idea. The code for that is on the Embark Wiki as well. apply-macro-to-lines-of-paragraph, which I
personally had not been using until I saw your config. And I was like, that is a thing. Omar: Yeah. Well, that's a command that I wrote. It’s a wrapper around apply-macro-to-region-lines, but it automatically uses the paragraph. That way you don't need to select it. I find that extremely convenient. What would be a good example of that? You want to wrap something. What should I do as an example of this? For some reason, I needed to convert these things to, say, unwrap the parentheses and turn them into an Org Mode table. Sacha: Yeah, that makes sense. Omar: I just apply it to the rest of the paragraph. Sacha: Magic. That's great, because I would normally just start executing the macro and hope I remember to stop at the end, but then I overshoot, and then I have to undo,
j and then it's a mess. Omar: Or you could select the paragraph and then just use the built-in apply-macro-to-lines-in-region. Sacha: Yes, yes, that's a possibility. Omar: It just saves you the step of marking the paragraph. I found that I most often when I used apply macro to lines in region, the region was exactly a paragraph. So I figured like there's no point in... Sacha: All right, all right. Omar: It's undone in a single step. Like the application. The thing I recorded as a macro, that is not coalesced. Yes, of course. Sacha: Because that's the actual recording of it. Charlie Baker in the chat says, "Definitely going to add the keycast transparency to my config. I've been wanting that for a while." These little demos of like, oh, this is what this thing in your config does. It's very helpful for people to be able to see its awesomeness. Omar: Where is that? Sacha: One of the other interesting things you mentioned was your placeholder package. I can see how the keyword macros help you with text that's already there. Then you've got these placeholders for informal snippets or quick snippets. Show us that. You use it a lot. Omar: Yeah, I do. Oh, that tmp-buffer is a command I have for popping up temporary buffers in specific major modes. Maybe I can quickly show that first. Yeah, yeah, yeah. So let's see. Oh, yeah. So let me... embark-on-last-message It just calls Embark on the last thing in the messages buffer. Often I want to act on the thing that is the last word in the echo area, so that's what this does. Sacha: Okay. Omar: The last thing in the echo area was this symbol embark-on-last-message so I can act on it directly. Sacha: Which is brilliant because I keep switching to the messages buffer to try to copy something, and by the time I switch, sometimes there are other messages, so it's great to just be able to do something. Omar: If there are other messages, then I also switch to the messages buffer, but if I want to act on the very last thing, I have that command for it. Sacha: Yeah. I'm saying this is faster, so I get the chance of just hitting the shortcut before another timer goes in and messes around with my messages. So yes, shortcuts. Okay, temp buffer. Tell us about that. Omar: You can configure single... Wait, where am I? Transcribing job. I ran Whisper by accident. Sacha: Which is another thing I wanted to check. Many things I want to talk to you about… Omar: The idea of using Whisper, I stole from you using it to dictate. I thought, oh, this looks convenient if the model is good. I tried it and it is very good.
Sacha: Temp buffer. Omar: Different major modes. It has a customizable list of bindings for specific major modes.
Omar: It also has an option to just prompt you for a major mode. It pops up a temp buffer in whatever major mode you chose. I use it all the time to make new scratch buffers. Sacha: Yeah, I can see that's useful. I switch to a buffer that's got a name that doesn't exist yet, and then I have to press more keys to get to the major mode. Omar: But if you're doing certain things, just type random letters to make a new buffer, this is much better. They might as well all be called temp. Sacha: Do you reuse the buffers, or it's always just the one buffer? Omar: New buffer, then I kill it. Sacha: Very temporary. Gotcha. Omar: By the way, kill-current-buffer doesn’t have a default key binding. I don't understand why not. OK. I bind it to C-c C-k, which normally, I think, is kill-buffer, but why would you want to kill a buffer that's not the one you're looking at? Wait, what was I going to show you? Sacha: You were going to show me placeholders. Omar: Right.
Omar: I often need to send several similar email messages. I'm going to invite you on some day of some month to give a talk, etc. That's the body of an email. I'll write it once. Here I’m using placeholder-insert to insert this
symbol. It appears in green, but it doesn't matter. It's just text. You could type that symbol yourself.
Omar: Then the placeholder-next and -previous commands will cycle among those and let you fill each one in. You don't have to fill it in right now. If you repeat the command, it restores the placeholder and moves you to the next location. Sacha: That's one of the things I liked about the implementation compared to yasnippet, because yasnippet, you’ve got to actually remember to fill in the fields before you move on to something else. If you get out of it, you can't tab to the next field. The placeholders will let you go and come back and look up some information and put that in and so forth. enable-recursive-minibuffers. The default value is nil. They don't let you use the minibuffer if you're already using the minibuffer. Emacs is supposed to be about freedom. Why is that the default value? So I set it to t, which is more sensible. That way you're not stuck in the minibuffer. Sacha: Actually, one of the things that I've been trying to figure out is when I'm in a minibuffer, sometimes I want to use Embark to insert something into the minibuffer, but then I end up inserting it into the buffer buffer. Omar: Yeah, there's no... Embark doesn't have any solution to that problem. It doesn't always do that. It does that if you're in the minibuffer in a completion session. If you're in the minibuffer in a non-completion session, then it acts as a regular buffer. So if you're in eval and here you had... You can use embark-insert in the usual way to duplicate stuff. Sacha: I have a workaround. I just use kill. I copy the text instead of inserting it and that works out fine. Omar: Yeah, I do too. The behavior of inserting into the previous buffer is so useful that I don't think I would want to change that. But yeah, it is unfortunate that for that specific instance, you can't use insert. Sacha: I appreciate that Embark allows us to have all of these key bindings that we can do stuff with. I noticed in your config, in addition to Embark, you also modify a lot of the standard key maps to add other shortcuts to rebind things that make sense to you. Key bindings are something that a lot of people struggle with, trying to figure out more places to put more shortcuts that make sense. What are the key shortcuts that work really well for you?
Omar: One thing I don't like about the default Embark configuration is that SPC is used for embark-select, which marks a target for later use. I hardly ever use embark-select, so I would rather SPCbe for marking the region, which is something I do pretty often, and have embark-select on C-SPC, which is not a
command I use very often. I swapped those. I think most of this is just adding new actions that feel specific to me.
Omar: quick-calc is the thing usually found to C-x *… calc-dispatch is the command. It’s C-x * q. That’s quick-calc. It's useful as an Embark action. If you have an expression and you... Wait, what am I doing wrong? I forgot what my binding to mark what Vim calls a word in capital letters, which means a consecutive stretch of non-space characters... If you mark this, I can act on it with =, get the result. Sacha: And specifically this embark-region-map is what you can add in the selected region. Incidentally, I've been playing around with using the Selected package for this because it also gives you the key map. Omar: Yeah, yeah. I love the Selected package and recommend it often. I don't use it myself just because the only thing it would save me is calling embark-act, because the commands I would put in the selected key map are exactly the commands I have in the embark-region-map. For me, Selected would only save me one keystroke, which is Embark Act, so I don't feel it's worth it, but it's a great idea. For example, I do use the rectangle keymap. Yes. So they're the only difference. It's equally good an idea as Selected is. The only difference is that the rectangle keymap comes with Emacs and Selected is an external package. I decided it's not worth installing an external package when I could just use Embark Act, which I do have to use because otherwise
I won't understand people's bug reports. But the rectangle mode there, that one is built in, so I just found a bunch of useful stuff in it. Sacha: Yeah, and I noticed you have also like you have a narrow-to-point so that you can use your rectangle commands to yank something into it, so I get the sense that you use rectangles a fair bit. Omar: You've really read my configuration very carefully. This narrow-to-point is subtle. I am very impressed that you figured out the reason for it. Sacha: I started digging through narrow-extras because I saw your narrow-or-widen-dwim and I said, yes, I need that in my life. Omar: I don't think... I took it from somebody. Endless Parentheses, probably. The issue with narrow-to-point, the reason you need it, is that if you insert a rectangle somewhere, try to insert it in a blank line, and it'll overlap with what was after it. But if you first narrow to the point and then insert the rectangle and then widen again, it gets its own blank lines. That's the reason I have it. embark-act three times for this kind of thing. How do you distinguish between lots of them when you're just going through it? Omar: I think that's the poorest part of the user experience with Embark Act currently. I don't really like it, but I don't have a good alternative. A lot of people like expand-region and I don’t like it because I feel like I have to hammer it off. I prefer to have a lot of… This is another thing I learned from Vim: have a lot of commands to mark specific things and just memorize all of them. But expand-region says, no, don’t memorize that. Just hammer on expand-region until you get the thing you want. Ffor me, even though it's objectively fast, it just feels very slow. It feels like I have to hit it four times whenever I want to mark something. I get the same feeling from cycling in embark-act. I don't really like it. But if we had come up with a better alternative, and I say we because I discussed this in the GitHub issues with with Daniel Mendler and Prot, and I think @hmelman was also in those discussions, and maybe Clemens Radermacher? I just couldn't come up with a much better alternative, so I put up with it. I don't need to cycle that much. I almost always want to act on the first target. Which is unfair, because I decided what the first target is in the default configuration, so it's sort of tuned so that I hardly ever need to cycle. I apologize if it means other people need to cycle a lot. Sacha: Nonsense. We can all modify our target list, so we can always tune it to what we want. Omar: I mean, it's a lot of work, right? I think the default Embark configuration is over half of the source code of Embark. The configuration is... Where does that start? Oh, I wish the autoload cookies were not in the outline. Sacha: If you do a space, oh, I guess it doesn't do that, right? Omar: Oh, yeah. For orderless, I use the escapable spaces, so I can do that. embark-act set up to expand in the same way expand-region does, but with Embark’s type
awareness, it's easy to add a contract function.” I guess maybe also some highlighting helps with that. Charlie also says, “I also have a completing read interface in the transient menu to jump directly to one of the many types under point that I'm seeking.” Charlie, you're going to share somewhere so I can steal that part of your config, right? Omar: I mean, that would be something I would consider adding to Embark itself. embark-live. There was this embark-live thing where you could pop up a buffer with the targets in the minibuffer, which just means a completion candidate. So you could use Embark as a kind of completion user interface. It was very slow, but it was very featureful. You could do a vertical list. You could do a grid. In the list, you could activate zebra stripes. Yeah, you can see that's been removed from Embark. But I kept saying to Daniel, I'll switch to Vertico if you add a grid view. He eventually did add the grid view. I kept my word and switched to Vertico, which is much better than the thing in Embark. I was just being stubborn by not switching earlier. But if I had switched earlier, maybe Vertico wouldn't have a grid view. Sacha: I think it's definitely a good example of a set of packages that has... So all this started in about 2020s or so. So we actually can see how people have gotten into using Vertico and all the other packages compared to, say, looking at more popular packages that have been around for a long time. "Of course everyone's been using Org Mode for a long time." It's there. It's part of the fabric. user-lisp directory. Sacha: I have actually successfully used use package to grab stuff out of your user-lisp directory and use them in my config. Yeah, it works. I just say, all right, my load path is here where I've checked out your source code. It defines these commands. Then I can bind your functions to my shortcuts. Although, because your functions are named the way that I would expect Emacs functions to be named, I've been defaliasing them so that I don't accidentally say, oh yeah, that's totally built in when it isn't. Omar: Yeah, I'm inconsistent with these little packages in my user-lisp directory. In some of them, I do stick to the convention that the package name is a prefix for all the functions, and for some, I don't. For some, I just try to name them the way exactly what you said. Like, what would these be called if they were built into Emacs? Which means they don't share a consistent prefix often. I should probably make that more consistently use the package name as a prefix so that they're easier to dot. Sacha: Or I have another suggestion. You could get apply-kmacro-to-paragraph or whatever that is into core Emacs. That would be great for everyone. Omar: Yeah, maybe that one is useful enough. Some of these I don't use anymore because I think I've substituted them with workflows with Embark. For example, eval-region-advice. It bothered me that none of the evaluate commands are “do what you mean” in the most common sense in Emacs. The most common sense of do what I mean in Emacs is if the region is active, use the region. Otherwise, do the normal thing. All of the evaluate commands should evaluate the region if the region is active. So that's what this does. But I don't use that anymore, because to evaluate a region, I usually use embark-act e. What
else is here?
Omar: Oh, some of these things are like tiny things that are almost invisible, like this. In Eshell buffers, By default, find-file-at-point doesn’t realize that if it sees the filename printed in an eshell buffer, it won't look at the prompt to figure out what directory it came from. If you type ls and you're in your current working directory, all of those listed files, the find-file-at-point guesses that they are files in the default directory, and that guess is correct. But if, further above, you had gone into a different directory, called ls there, then those files are no longer in what is now the default directory. So this just adds a little bit of smarts to find-file-at-point. It looks at the prior prompt to see what directory that was run in, and then tries to see if the files it sees there are in that directory. Of course, the only reason I want this is because I sometimes use embark-act on files I see written in the Eshell buffer. Sacha: I love this. I love how all these little bits of code show that at some point you were annoyed by a tiny, tiny problem and you're like, that's it, I'm just going to write some code and it's never going to be a problem again. find-file-at-point to guess what things are referred to files. I did this to improve the functionality of Embark in Eshell buffers, but what it really does is improve the functionality of find-file-at-point, which I hardly ever use directly. I almost always use it through Embark. Sacha: Send it upstream! Okay, so you use Emacs for working with a shell, working with your files, doing math, doing some programming as well. Are there unexpected things that you use Emacs for? Omar: I don't think so. Mostly I write. It's mostly writing prose. I think I was slightly misled about what a job in academia is like. I mostly write emails. That's the bulk of my job by the time consumed.
Sacha: You have some shortcuts around org-ql for managing your agenda or other things. Omar: This notion of the usual files. I was often using org-ql to search this set of files: every file mentioned in a refile target, every file mentioned in a capture template, and every file agenda file. Here it is. So I thought that's what I want to search. I want to search every file I mentioned in a refile target, every agenda file, and every file that I mentioned in some template. That's what this does. Sacha: I don't know if you trust your hiding things enough for us to try that. Since you put so much work into it... Or do you want me to hide the screen first and then you can let me know when it's safe to look? Omar: No, no, that's fine. I can show you the censorship process. What I thought I would do is I could show you the... Wait, what is this? Why is that not an action? Oh, library. Oh, I have not loaded this. Yes, now it's loaded. Oh, so this should be... Why is this not recognizing org-ql usual files as a variable now that this is loaded? Sacha: Oh, great. I'm also open to debugging demonstrations live because that is something that a lot of people do. Omar: Sorry, I think it just hadn't loaded this file. Now I ran a command from here and now I should have a variable. Yes, I have a variable. So we can go to Customize.
Omar: The ones that have sensitive information are tasks, home, health, Definitely work. Journal. I don't really mind people seeing my journal, but that's boring. There we go. Yeah. So now I got rid of all of the sensitive files. And so now I can show you. I usually just search through all of these files at once. So I had a list of things I wanted to tell you about. C-,has a little key map that will insert stuff like priority. Oh, I don't have, let me remove “Sacha”. Oh, yes, everything that I have with priorities is in one of the files I removed. I only use priorities for work. Sacha: Okay, gotcha. Omar: We could use to-dos.
Sacha: I love that you have a to-do state called NOPE. Omar: It's for things that are cancelled, but I don't want to delete them yet. Actually, it's mainly there because when I archive them, I want to know that I had that task at some point, but decided not to do it. Sacha: Well, it's so much less verbose than CANCELLED, so I think I might actually just... Omar: For a long time, I was using monospace fonts, so I wanted to have everything fit in four letters. So I have... Yeah, all of my, I have TODO, WAIT, DONE, NOPE, and they're all four letters long. Sacha: Nope. Gotcha. Okay. So that's org-ql and that's your inserting thingy.
Sacha: The other thing that I wanted to point out that your definition of the inserter was nice because it's a macro. So you have this thing that allows you to just define all these interactive functions. You can add it to the key map because the key map expects interactive functions. If people are watching, yeah, this is something you can do. Omar: I should tell you that there was actually a serious performance bug previously. What I had before this… This string is a keyboard macro that inserts those letters. It is extremely slow if you do it that way for some reason. I think org-ql searches after the T, after the O, after the D, after the O, after the colon. For some reason, that was extremely slow. So I switched to these lambdas that just call insert. That does it in a single step, and it's instantaneous. But my first instinct was, oh, well, this is a good use of keyboard macros. I'll just assign these to keyboard macros. It's not a good idea in this particular case. Sacha: I imagine there should be some kind of debouncing on org-ql to make it not do that if you're typing very quickly, but... I don't think there is. Omar: Let me see if... Maybe also do a longer one so it... Sacha: That's okay. I take your word for the bug that you ran into. Omar: I wanted to show you just because it just feels like a really long pause, but it didn't work right now and I don't know why not. That's okay. Sacha: Curse of the live demo. So that's inserter.
Sacha: One thing that I definitely want to make sure we had time for was your little generative art experiment, luggage, because you're having fun with Emacs. Omar: Yes. Yeah. There are some people doing amazing generative... Oh my gosh. I do not even have it installed. Yeah. Let's... I forgot that we were going to do that. That's okay. But it should be easy. How is :vc used? Sacha: (:vc (:url …)). Omar: I have to go to a previous example to figure out. Sacha: I'm surprised you don't have a consult-line and then just
embark-insert. Omar: I do that. I do that a lot. But I forgot this time. Sacha: Actually, looking at your config, I learned about consult-multi-occur because apparently there all these multi-buffer equivalents to the commands that I've been using. That is really useful for using stuff from buffers I'm not even looking at. Omar: Okay, load it. Sacha: Let's see if it actually can still do the thing. There we go. So you have some Emacs Lisp to generate this SVG. Yeah, and it's just got... Omar: And which other ones do I have? Luggage. There we go. Tubes. I think this one has some nice other color schemes. Classic? Classic is the one. Oh yeah, stained glasses is the one I wanted. Sacha: Nice. I wanted to mention it specifically because a lot of times people think, oh, Emacs is a text editor. But because it's also got support for SVG and other types of graphics, you can play around with it. Sometimes it's just doing it for fun like this, but also there might be some other visualizations that you can do with Emacs. That is actually pretty interesting. Omar: Yeah.
Omar: Have you heard of this program? Sacha: No, I haven't come across it. Omar: There's an entire book with this title. So it's a single line of BASIC. 10 print. Oh, I'm not, I don't know BASIC, but the idea is like you randomly pick either forward slash or backslash. Sacha: Oh, yeah, yeah, that makes sense now. Omar: I'm sure this is not correct BASIC, but, you know, something like that. Yeah, I get the idea. Yeah. And that's what this does. And then you GOTO 10. It's like... It makes these elaborate mazes. It's an extremely simple program. Sacha: So this is the kind of stuff you do for fun. I mean, you probably do lots of other things for fun, too. Omar: Yeah. But this... No, that's not the buffer I wanted. Where is... Did I kill it? I killed it. Yeah, one of these I did. What is it? Dominoes. Yeah, this I did for a math talk I gave. It just produces random domino tilings of the board. I gave that talk from an Org file using Prot’s Logos package. I usually use PDF slides, but that time I wanted to use an Org mode buffer because I was going to run code on the computer. Like this, for example, generating random domino tilings.
Omar: Oh, there it is. In the docstring, I have the correct program in BASIC. The backslash and the forward slash are consecutive ASCII characters. 206 and 207. You add a random number between 0 and 1 to this one and then round to the nearest integer. Sacha: All right. You can get surprisingly interesting patterns out of it. That is also very cool. Fun with Emacs. This could definitely be like a zone screensaver if you wanted to. Omar: Yeah. I just thought it was really nice that Emacs displays SVGs natively. Those are very easy to generate by text. Sacha: Are there other interesting corners of your config that might not be immediately obvious to people who are just reading the source code? What other workflow things are nice for you? Omar: Sorry, what were you saying? Sacha: I can also start just occurring through my config for all the things that I've stolen from your config in the last two days. Omar: I don't think I have any concrete idea of what to show now. I think we've covered most of the ones I wanted.
Omar: As an academic, I deal a lot with preprints on the arXiv, so I have a little library that will show me the PDF or copy the URL. I like personalized software because it does exactly what you needed to do. I noticed that there were a bunch of tags on Mastodon that related to archive papers. Often when I was in a Mastodon buffer, I wanted to do something to the paper mentioned at point. That's one of the acceptable inputs for my arXiv library. So, for example, this is an arXiv link and I can ask it to show me. So that's a bug. This should definitely have visual-line-mode activated. I can just quickly read the abstract without visiting the archive website.
Omar: Or I can open the PDF. Sacha: Very cool. Very convenient. Omar: Yeah, so. I like that in Emacs you can do all these personal things that you'll need but are not likely to be needed by many people. They're just easy to do. Vim is also very configurable, but the Vim script language is sort of awkward, so I never did anywhere close to the amount of configuration in Vim that I do in Emacs. That's why I would never go back to Vim now. I would miss all the stuff I've written.
Sacha: One of the little personal customizations that I liked reading in your config was the fact that you have a key map just for toggling various things like the mode line or the header, you know? Yeah. You want to tell us more about your awesome key map for that? Omar: You don't need them that often, so it's OK if it's under a long prefix. It's just tedious when you want one of them, to have to type the command name. It also helps me remember which things I commonly toggle. I often have to hit C-h here and see what I have available to toggle. I don't know why toggle is a category for commands, because obviously these are very disparate commands that do very different things. But they're things that you occasionally turn on or off, and it's convenient to have them all together. Choosing the letters here was very difficult. Everybody wanted to have the same letters. L was for visual lines. P for variable pitch mode because I think of them as proportional fonts. It took a lot of tweaking. I'm sure if I looked through the GitHub history, you'd see a lot of tiny changes just changing the binding of one of these. Sacha: I find it difficult to get the hang of new key bindings, especially for things that I'm not using often enough for the key bindings to stick. Omar: I often forget that I have a key binding for something. Sacha: So how do you deal with that? I mean, yes, you stick it in an Embark keymap and you just bring it up to the target. Omar: Yeah, I do use Embark bindings in keymap a lot to just explore keymaps and remind myself. I don't need to memorize a binding. I just need to remember that I have a binding. If I have a binding, I can find it later. But sometimes I don't remember that I have a binding, so when I'm looking at my configuration, I'll just re-scan what things I have bound from time to time. Mostly I stick with just… I know under what the start of the prefix is, and then I'll just use Embark to remind me of what I have there. Which is nice, because you can also see the docstrings.
Sacha: I like how you try to use some of the conventions to make it somewhat easier to remember. One of the key bindings that you have that I want to point out, because I think it's a useful technique, is you have an isearch-delete-wrong. Omar: Right. isearch keeps track of where the last portion of the search string that matched is. You can see it highlighted in the buffer, right? So this means it found up to “del”, and then it didn't find "tok". isearch-delete-wrong will just delete that entire part. Sacha: So that way, you can just restart from what actually exists. Combining that with the fact that you've got your search whitespace regular expression to be a wildcard means you can... Omar: Oh yes, this I stole from Prot. He recommends this. Sacha: Yeah, which means you can use isearch to find things, even if there's other stuff in between them. When you can't find something, you can restart. Omar: I'm not sure... I'm not sure if this is the best setting. I want to be able to search this way sometimes, and sometimes with whitespaces treated literally, so I should keep statistics on how often I actually have to turn this off. It might be that for me the better default is the other way around. You can turn it off with M-s SPC. Match spaces literally. isearch-toggle-lax-whitespace. I don't know. Maybe for me the default would be to treat whitespace literally, because I find that if I have a space in my search string, I often want to turn on the literal matching. But it's probably still this is the better default. I think I do it less than half of the time I have a space. But it's not that far from half, it feels. I don't have statistics. Sacha: How do you even collect statistics on this? Aside from making a little note every time you're like, oh, I didn't like this. Omar: I mean, I would instrument isearch somehow, but I haven't thought about that problem.
Omar: One nice thing I do with isearch is another one of those things I got from Vim. isearch, by default, leaves you at the end of the match. I almost always want to be at the beginning of the match, because that's what I got used to in Vim. I think it must be here. I have something exit at start. I tell isearch to exit at the beginning of the match. The way you use this is you install it as a hook, I believe. Is that right? Sacha: You seem to have options. Omar: Yes. Sacha: I see. So S-RET lets you exit at the end, and then by default... Yeah, which is Emacs default. Omar: But I find that the better default is to exit at the beginning. Yes, and that's the whole point of that. For example, if I want to mark until that parentheses, then I would search for the parentheses, and I don't want to include the parentheses. That's not a good example. But with a word, it's often like, I'm looking for a word, but I want to highlight up to the end of the word. It's just like, if you want to mark a region from point to some search term, with the Emacs default, what you have to search for is the thing that is at the end of the part you want to match. But often I want to say until like the thing that starts here. It's just my brain works that way. So for me, it's much better to exit at the start of the search. Which means I don't understand isearch on other people's Emacs. It just leaves the point in the wrong location all the time. If you're going quickly, you won't realize that it's just a mess. It does mean that I can only use isearch if it's configured this way. Sacha: Well, that's the thing about Emacs, right? Once you've got it set up, you've got to use your config because everything else just feels off. It just feels weird. Omar: Yeah, that's right. Sacha: All right. C-h screen, you can use completion even to select the commands from that subset. dired-open-externally, so it makes it very easy to open something in an external application. Omar: And it just calls Embark open externally. This function moved back and forth from different places. I think embark-open-externally used to be in consult. Daniel said he felt it didn't fit in with consult. Embark consult would put it in keymaps. He was right. Consult didn't have a very clear personality at the beginning. It was sort of like a grab bag of commands. Eventually, what gelled is that a command should be in Consult if there is a useful way to write previews for it. So, preview is the distinguishing feature of what is a good fit for Consult. Now, I hope Daniel would agree with that. That seems to be the criteria now. That's great. I absolutely love preview. That's one thing I miss a little bit with org-ql. I use org-ql mostly to search through Org files, but the preview is kind of manual in that I use Embark to do it. If I want to preview a command, I just use Embark to do what I mean. Sacha: Yeah, that's a good idea. I should try that. Omar: So any command that doesn't have a preview, I mean does, you can just use embark-dwim, it'll complete the command for you. Sacha: Okay, the kid has arrived, so I have to go off to lunch. But thank you so much for the quick peek into your config. I'll put the transcript together and then people can do that. But in the meantime, people can look at your config for all sorts of wonderful goodness. Omar: Thanks. Sacha: Thanks to everyone for hanging out. Looks like the isearch tip was popular, so you might see a lot of people getting that from your config. Anyway, thank you so much for this. I’ll see you around. Omar: Thanks, Sacha. This was fantastic. Sacha: Alright, nice.Chat
- takoverflow: Hello Sacha and Omar, thanks for this chat! :)
- CharlieBaker707: Definitely going to add the keycast transparency to my config! I've been wanting that for a while!
- gcentauri: i'm still a minibuffer noob - its been nil my whole Emacs life!
- CharlieBaker707: recursive minibuffers is amazing. biggest win for me is that it lets you select things and paste them in, like from a completing-read's history for example
- gcentauri: haha apparently i do have recursive minibuffers set to t, along with my Vertico config 🤔
- Zor_org: was there a time you wanted multiple cursors?
- Zor_org: if so, was there any workaround you thought of with embark or kmacro?
- gcentauri: keyboard macros are a fun mini-game
- CharlieBaker707: I have embark-act set up to expand in the same way expand-region does, but with embark's type awareness. It's also easy to add a contract function.
- CharlieBaker707: I also have a completing-read interface and a transient menu to jump directly to one of many types under point that I'm seeiking.
- CharlieBaker707: For sure!
- CharlieBaker707: I was going to create a tiny extension, but I can open a PR in embark!
- Zor_org: even more crazy with elfeed 4.0
- gcentauri: I found Orderless and Embark through Daniel's suggestions in his packages :)
- Zor_org: if emacs gets canvas patch soon, more things can be done in luggage (lik gifs and image frame as well)
- gcentauri: i am not lazy enough, i just M-x orderless consult find the thing i'm toggling
- PuercoPop: I didn't knew isearch had a built-in way to fix the isearch quirk. Now I can remove the snippet I use the implement it that I cribbed from the internets
- gcentauri: yeah adding something to a keymap you make does help recall
- PuercoPop: The isearch quirk is a common complaint from what I understand
- gcentauri: yeah i'm gonna use that iserach bit
































































