Categories: geek

RSS - Atom - Subscribe via email

2024-02-05 Emacs news

| emacs, emacs-news

[2024-02-05 Mon] Added link to org-link-github.

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Hacker News, lobste.rs, kbin, programming.dev, lemmy, planet.emacslife.com, YouTube, the Emacs NEWS file, Emacs Calendar, and emacs-devel. Thanks to Andrés Ramírez for emacs-devel links. Do you have an Emacs-related link or announcement? Please e-mail me at sacha@sachachua.com. Thank you!

View org source for this post

2024-02-04 Yay Emacs: community plumbing, streaming setup, Emacs News highlights, transcript export

| yay-emacs, emacs

Note: I kept saying cl-flet, but it's actually cl-letf, which is the one that lets you affect functions that are called by the function you're calling. =)

Next livestream will be at [2024-02-11 Sun 07:30] EST: https://yayemacs.com.

  • 0:07: Overview: Hello and thank you for joining me for another episode of Yay Emacs. I'm Sacha Chua and today is February 4, 2024. I'm going to use this as an opportunity to brain dump an upcoming lightning talk for LibrePlanet. I want to talk about community plumbing. If there's time, I'd like to share some of the little snippets that I've added to my Emacs configuration this week. Okay, so community plumbing.

Community plumbing

  • Emacs:
  • Other projects:
  • Sources:
  • 0:34: Community plumbing: I wanted to put together a lightning talk for LibrePlanet, which happens to have the theme of building communities. I'm really interested in the kinds of communities that people build around the things that they care about,: Emacs for me, but also lots of other free software projects out there that people build their communities around. Not just, of course, geek stuff, but also even interest-based things. I want to show people that it doesn't take a lot of effort to do the community plumbing that helps information flow better. Anybody could do it. You could do it too. I want to see if I can make a 5-minute talk that shows what we do with Emacs and encourages people to go try this out for their own communities. If you think about the flow of ideas in a community, there are little things you can do to help things flow better. You don't have to be an expert in order to do them. You don't have to be someone who's really famous in the community, or advanced in their usage, or whatever else. You can just do little things to help make those ideas flow better. If we're going to use this analogy of pipes and flowing, you don't even have to fill the pipes yourself. You don't have to be the one coming up with interesting content regularly or whatever you want to think of it as, you can just help share what's already out there. So I want to share some of the things that we're doing in the Emacs community to help things flow better. I want to convince people (you, specifically, if that's possible!) that doing this kind of community plumbing is fun, it's easy, and it actually has a great effect on making things better. This is fantastic because if you can help things flow better, then that enthusiasm spreads. When people connect with other people who are fascinated by the same things, they can bounce ideas off each other and share what they're working on. All of that is goodness.
  • 2:45: Blog aggregators: In the Emacs community, it actually mostly started with having a blog aggregator. Most blogs will have some kind of RSS feed that lets people subscribe for updates. With a tool like Planet Venus, which is a blog aggregator, you can collect the updates from lots of different blogs in one place to make it easier for people to just scroll through that and see what's new. For us, it's Planet Emacs Life, which is actually the second incarnation of this. It used to be planet.emacsen.org on Tess O'Connor's server, but then that server died and was hard to restore. Anyway, we're back up now on planet.emacslife.com. And this is pretty much automated. I just do a little bit of updating every so often when people say, oh, I have this new blog, lere's my RSS feed. I put it in the configuration file. And then, every hour, that the program just goes and fetches the new updates from all the blogs, giving people one place to go, which is great because it saves people time. They don't have to go to all these different blog posts themselves. So that's fantastic. Blog aggregator: if your community doesn't have one yet, it's very easy to set up and it's very convenient.
  • 4:02: Social media: Of course, there are lots of other things that aren't put on blogs. People post videos on YouTube and PeerTube and other places. They might have posts on Reddit or Hacker News or Lobsters. They might have toots on Mastodon. There are lots of other places where people share things. So if you have a way to go to these places and just keep an eye out for interesting news in those areas, then you can start collecting that as well and help those ideas flow better.
  • 4:32: Newsletter: We have a weekly newsletter which I put together. It really just takes me an hour or two each week to go through this, you know, these updates from Reddit and from Planet Emacs Life and all those other things and select the ones that I want to include. I like putting them into categories, which I think it actually takes takes me the most time, because then I like to read things to get a sense of what they're about, and then I get distracted by all the cool Emacs snippets that I want to put in my configuration. It's a newsletter. Doesn't have to take a lot of time, and it doesn't have to be very fancy. I find that I still don't have the time to write a lot of commentary for it, so my newsletter is really just a categorized list of links and that seems to be all right. It's useful enough for people to subscribe to it and share it with other people and so on.
  • 5:21: User groups: Among the things that I include in this newsletter are upcoming events from different user groups. People sometimes like to meet each other, both online and in person, and talk about the things they're interested in, which is fantastic. Many of these user groups have some kind of calendar that I can subscribe to, to get the event updates. If your community has something like this as well, see if you can use that to automate the updates that might go into your newsletter. Some of them don't have a calendar, but they'll tell me about the regular meetings. Then I can create an entry in my own calendar and incorporate that into the newsletter. I used to check all of these posts manually, but I've since then built a little bit of infrastructure so that all of these things can be included in the Emacs calendar. Then I can use the iCal from that to put them in the newsletter so that I don't have to do the timezone conversions myself.
  • 6:23: Conference: Of course, an extension of the user group idea is to have some kind of conference. It turns out to be fairly inexpensive to organize your own conference for something. So for example, with EmacsConf, we get about maybe 200 people watching it live, and the whole thing can be done on less than $50 US of hosting costs. A whole load of awesome speakers, We get to two tracks, and lots and lots of talks. There are volunteers who come and help with the captioning the talks beforehand, so that's a nice bonus as well because the text makes it easier to search and skim through afterwards. Conferences are a great way to get people who are passionate about something to come together and connect and have those conversations. Then those videos become things that inspire people throughout the rest of the year. So there, just all these very, very small things that can be put together to keep the ideas flowing in a community.
  • 7:26: Pieces working together: The amazing thing about that is that the pieces help each other. For example, I mentioned how the blog aggregator can help with a newsletter, because it gives you stuff to put in the newsletter. It makes it easy to just go through the list. I actually have the RSS feed automatically included in my newsletter, and then I can just categorize it from there, so I'm not even copying the links manually. So you've got a blog aggregator feeding the newsletter. People start looking at the newsletter and writing blog posts about the interesting things that they come across because of the newsletter. Likewise, I've seen a lot of the user groups start to refer to the newsletter as a way to fill in any extra time, so it makes it easier for people who might otherwise be a little nervous about standing there by themselves or with a few other people… There's a lot of dead space and silence because nobody knows what to talk about. Now they can just pull up the newsletter and go through it and see what spikes people's interest. Then all of that again inspires people, brings people together, and turns into ideas for conference talks and so on. This is an example of how a little bit of community plumbing helps ideas go around faster. It helps ideas circulate. I think that this is something that lots of people can do in their own communities, even if you don't feel like an expert, you don't feel like you have much to add, even if you don't feel like you have much time. I have very little computer time. This is basically it. I have maybe 5 minutes here, 10 minutes there. I can scroll through Reddit on my phone and upvote the posts that I want to include in my next newsletter. I can look on Mastodon for toots that I want to share to my Orgzly so that I can take notes and then include that in the newsletter. This is something you can do with very little time.
  • 9:25: Fun: It is a lot of fun. One of the things I really look forward to every week is being able to see, in the process of making Emacs News, all the cool stuff that people have come up with. It's something that's personally very useful for me, and it happens to be useful for other people. That's a nice bonus, but really I'm getting a lot of selfish benefits out of it. I think that if you put together a newsletter for the stuff that you're interested in, then you'll also get a lot of benefits out of that too. So, it'll be fun.
  • 9:55: Building processes and tools: Building processes and tools is a great help, of course, to make it easier for you. Instead of copying things manually, maybe you can automatically get a list of things. Then you can just delete the ones that you don't like. A little bit of automation. Doesn't have to be built all at once. You can do a little bit and then try it out, add more to your newsletter. For example, I've got this section on new packages. I am definitely not keeping track of that by hand. I just have a bit of code that gets all the packages from all the archives and then compares it with a list that it saved last week. So as you get into figuring out what you want your community plumbing to look like, you can build the tools to make it easier for you to do this and to save time so you don't have to do the tedious stuff. You can focus on the fun stuff instead.
  • 10:50: Let people help: The last tip that I want to share in terms of community plumbing is that once you get the ball rolling, sometimes people want to help out. They'll send you interesting links that you can include. In the case of emacs-devel, the mailing list is too hard for me to follow because they're talking about all sorts of things, there's a lot of volume, and I'm just scrolling through things on my phone. But people like Andres Ramirez send me notes on the different threads that have been going on, so that becomes something that can quickly include. People are out there who can help. Might not get things started on their own or might want to just contribute to something that already exists, but once it's out there, then they can come and contribute to it. So it's community plumbing: very easy to do, doesn't take a lot of work, can be a lot of fun, and there are little pieces that you can build that get things flowing faster. Blog aggregator, newsletter, calendars, little things that you can do to help people find stuff. In the show notes I have a list of links to the stuff that we have for the Emacs community such as the blog aggregator, planet.emacslige.com, the Emacs News newsletter, different searches that I like to use to find stuff on YouTube and Reddit and Hacker News and all these other places. Mastodon, there's a lovely little Emacs focused instance [emacs.ch]. People also talk about all sorts of other things, but there's actually like an Emacs instance for Mastodon, which makes it easy to bump into other people. So I think that's awesome too. Emacs News file, different package archives, the emacs-devel mailing list, the [EmacsWiki:]Usergroups page. I actually keep this up to date with upcoming events too. It makes it easy for people to see what's coming up. EmacsConf.org.
  • 12:45: Other projects: In addition to the Emacs stuff, I also have links to other projects, planets, and newsletters, so that you can get an idea of how other people do things. I think it's fantastic that there's such a wide range. A lot of the planets use Planet Venus as well–the same aggregator that we're using. It's pretty old. Hasn't been updated in like more than a decade. But some of them use more recent tools. Newsletters, there are a whole bunch. There are some that are weekly, there are some that are monthly, some with a lot of analysis, and some that are just also a list of links. You can check that out for ideas. Linux Weekly News has a calendar that they keep of conferences, so that's another way to check out what other people are doing conference-wise. And of course, there are lots of user groups. So, if you're involved in some kind of interest community, please consider doing some of that community plumbing because it makes it easy to discover interesting things and connect people to each other. It doesn't take a lot of work, it doesn't take a lot of expertise, and it is a lot of fun. So that's my quick brain dump. I'm going to find a way of condensing the 15 minutes of that brain dump into a five-minute talk.

Other little Emacs tweaks

  • 14:02: Using Yay Emacs for braindumps: One of the things that I want to do with this time for Yay Emacs is start to take some of these sketches and ideas, and flesh out the words around them. Speech recognition is really surprisingly awesome at turning that kind of a brain dump into words that I can then edit. As I mentioned, I don't have a lot of computer time, so I am going to use this to do the writing and the thinking and all of that stuff out loud. Other things I wanted to include here, just in case I have time before the kiddo wakes up, are little things that I tweaked in my Emacs configuration this week.

wdiff: word diff

  • wdiff - word diff
  • https://www.gnu.org/software/wdiff/
  • 14:45: wdiff TODO: So, word diffs. I actually had, for a little time now… When I edit the captions for Emacs Conf docs, sometimes I want to compare them with a script. I added a little thing to subed, which is a major mode for editing subtitles, for using the word diff, wdiff command line tool. It turned out to be super useful, and I wanted to keep using it for other things as well. So normal diff will show you the difference between a file or your buffer in terms of lines. Let's do that with some lorem ipsum text here. So let's say that, yeah, this text here. And I can M-x diff-buffer with-file. Oops, where am I? Diff-buffer-with-file. If we look at this here, it will show you the lines that have changed in green with a plus on them. M-x diff-buffer-with-file will compare your unsaved buffer with a file that's on your hard disk or SSD or whatever–whatever has been saved. But it works with lines. So here, for example, you've got that line over there. If you have another line, you can save that. If I make a change here– let's say, for example, if I put a hello world here– diff-buffer-with-file will show me that the entire line has been removed and the entire line has been changed. There's a little bit of highlighting to show me which words have specifically changed, but it's a little harder to tell. So I have this my-wdiff-buffer-with-file function. What it does is: it shows me that diff, and it just highlights the specific part that has changed. What the wdiff command line tool does is it takes the diff output and then it refines it to show just the words that have changed, and then you can highlight that specifically. Now, how does this work? Here's a little bit of Elisp wrapping around a shell command. So I've got here a my-wdiff function that takes an old file and a new file. The interactive call asks for the file name so I can compare two different files if I wanted to. All it does is it calls the process wdiff. It's a command line tool you can install. It's the one that does all the hard work of figuring out the actual words that have changed. Then a little bit of font-locking or highlighting it with different colors: going to the beginning of the buffer output and then looking for that regular expression to look for where the additions or deletions have occurred, and adding either the diff-removed or the diff-added face. So if there are command line tools that have some kind of useful output, and you want to color them differently in Emacs, it's fairly easy to write an Emacs Lisp function that will do that for you. I think that there's probably a package out there that does this kind of talking for wdiff and calls it and everything, but it's super short and I can just… It's easy enough to just write the function instead of looking through the packages. Anyhow, so that's wdiff. It's really helpful for prose because if you're writing lots of words, sometimes, it doesn't make sense to do them as separate lines. In fact, when I do transcripts, when I'm looking at word differences for transcripts, I have it squish everything on one line so that I don't have to worry about any white space changes. So wdiff, useful thing.

Touch gestures

  • touch - touch-screen
  • https://kitchingroup.cheme.cmu.edu/blog/2014/08/31/Using-Mac-gestures-in-Emacs/
  • 18:52: Touch gestures: Another interesting thing that I found out this week was that actually my laptop's touchscreen works with multi-touch gestures. This is the first time I've gotten around to trying it out. So I can two-finger-scroll and it does the scrolling thing. I can do a pinch to zoom. Let's see if it works. Oh, I have to make sure I'm in the right area here. Whoops, okay, so yes, it does do it eventually, when it kicks in. Let me see if I can zoom back. Yeah, so that's me like using my pinch gestures to mess around with that, which is slightly less useful. I wanted to share a snippet that I've borrowed from somebody else's configuration. John Kitchin shared these using Mac gestures in Emacs. In this post, he shared that you can use this to slow down the swipe: to set up swiping so I can swipe left and swipe right to go to the previous and next buffer, but to slow it down enough so that it's useful instead of just go whooshing through all these buffers. So if I swipe very carefully, I can just use two-finger swiping left and swiping right in order to make that change, which now makes me think, okay, how do I play around with this?

Thinking about strokes

Might look into strokes.

  • 20:30: Thinking about strokes: There's a strokes package. So strokes lets you control Emacs using mouse strokes. My laptop comes with a stylus, which I've been using to split words in transcripts because I like my captions to be a certain length. When I'm doing subtitles, I like to split them at about 60 characters if we're displaying them on screen and maybe a little less than that if we're displaying them in the regular video player on a webpage versus broadcasting it in EmacsConf. I use a stylus a lot during that part because it's easy to just tap on the word that I want to split at. Now that I'm playing around with touch more, I'm very curious about whether I can use the strokes package to do the pile sorting idea that I mentioned previously on one of these Emacs live streams. So, pile-sorting or card-sorting is when you take a pile of things and you sort them roughly into piles. You might say, okay, this stuff goes over here, that stuff goes over there. I'm thinking this might be an interesting way to think about sorting my inbox, because I don't necessarily want to go through all the steps of refiling something. Refiling takes a little while on my computer, even with a subset of refiling targets that I've been playing around with. But if I can sort them into piles, I can say, okay, this pile will eventually get refiled into this project, and this pile will eventually get refiled into this other place, and so forth. So, if I can make, like, 1, 2, 3, 4, 5, 6, 7, 8 piles, then maybe I could use this swiping or stroke idea, mouse gestures, to just fling something into the appropriate pile, whether it's northwest or north or northeast or south or all those other cardinal directions. That might be a future thing to play around with. I don't usually use the mouse when I'm using Emacs, but it might be fun to do that. It might also be fun to think about it using touchscreens as well. Can I swipe left and swipe right to do something interesting with org subtrees? We'll see. So that's what I've got for that section.

Yay Emacs streaming setup

  • 23:12: Yay Emacs streaming setup: Last little bit of thing that I can probably squeeze in before the kiddo wakes up. Someone was curious about my Yay Emacs streaming setup. it's basically this. This is my current setup, where I've got this external monitor, which is now the one I'm actually sharing so that it's higher res than the kind of really tiny monitor that I… Well, not really tiny, but the X230T is a small computer, so resolution is 720p when I'm streaming, At least this one will get us a bit bigger. The actual computer that's running everything is the X230T because it's very comfortable. I like it. It's already all set up and everything. Since it doesn't have the horsepower to do OBS streaming itself, I am using Video Ninja to share it to the Surface Book. The Surface Book is the one that uses OBS to then send everything to YouTube. There's a Blue Yeti over there that's plugged into the Surface Book. There's a webcam that's plugged into the Surface Book, so that allows me to start doing hand gestures. There's a light, and all that stuff. So I mentioned I don't have a lot of computer time. The kiddo gets screen envy. If I'm on a screen, she's gotta be on a screen too, so it's hard for me to squeeze in screen time, like programming time during the day, because then she's like, "I want to keep watching YouTube videos." Which is okay when I need to bribe her with screen time, but I shouldn't let her do it for too long because then I feel guilty as a parent. Drawing, on the other hand, I can get away, with because she doesn't get too envious about that. When I'm waiting for her or when I'm walking around or doing chores or whatever, else, I can use Google Recorder to do brain dumps. I can use speech recognition, usually through the Deepgram API, so I can use OpenAI Whisper without overloading my computer. All that stuff goes into Org Mode in Emacs, where I prepare notes and turn the transcript into something more coherent. It goes into the Eleventy static site Generator. It goes out to my website. Lately I've slowly figured out the workflow for converting the YouTube videos into our own WebM archive things, and then doing the speech recognition in that one, and posting that up on the web. So now, for example, for the show notes for last week, it's synchronized to the transcript timestamps and everything. Little steps forward. Next steps, I'm getting better at not doing the, "OK, are we live? Is this on?" that sort of thing; the trust that when it says it's live, it's live. I decided to move my posts out of the stream notes so that they're just on my blog, and then there's a link to the stream notes so people can go find the previous episodes. Working on smoothening that WebM conversion so that I don't have to think about it, it just happens. Timestamp synchronization happened, hooray. The next step is I want to be able to extract the media files, turn them into podcast enclosures, and set up the iTunes channel information and all of that stuff so people can also listen to it as just a podcast. I'll try my best to remember that sometimes people will not be able to see what's on my screen. That's another thing that people have wanted me to explain, so that's there.

More about piles

  • 26:58: Piles and e-mail: Charlie mentions that the pile thing sounds like the stack method of getting through email, which I would love to hear more about. I will go look that up later. My current approach to getting through email is that I don't. But that's okay because I'm just trying to keep my life low-commitments. Again, not much computer time. I'd rather spend it coding or writing than responding to emails sometimes. I'll accept that most of my email replies will be top-posted and done from my phone. But stack method sounds very interesting and generally… Pile sorting in general is very useful in real life when you're trying to go through a lot of stuff. I'm trying to look for ways to make that happen on the computer as well.

Emacs News highlights

  • 28:03: Looking at Emacs News: So, great. Now I get to do the thing which I just talked about, which is I haven't actually had a lot of time to code today. Well, code this week. So, code wise, I don't have fascinating blog posts to show but there's always the Emacs News to go over and share the interesting things that people have been sharing over this past week, so I can point you to other other cool stuff. Feel free to ask questions in the chat so I can go back to any previous topic or bring up more detail. I don't know. So in last week's Emacs news, we had a bunch of things in different categories. For Emacs configuration, it was interesting to see two posts on digging into Emacs performance or problems with Emacs configuration. There's "Why is my Emacs slow?" And there's "Debugging Emacs", kind of just trying to find the problem points. The profiler is very helpful for finding slowness. Bisecting your Emacs configuration can help with finding errors and things that run but don't do what you want them to do.
  • 29:21: bug-hunter: So it brought to mind the fact that there's a bug-hunter package. It's been a while since I've used this, but it might be useful to other people as well. What bug-hunter does is it does that bisection for you. Bisection is the idea of commenting out half of your Emacs configuration or whatever else and then seeing if that works. First, you comment out the second half and you run your configuration and you see if you're getting the problem. And if that works, then you split the second half, and you try to find the problem there and so forth. You're always cutting things in half and you're working with smaller and smaller pieces until you can identify the specific expression that's causing you problems. It depends on what kind of error I'm looking for. Sometimes I will just open up my tangled Emacs Lisp configuration and then record a keyboard macro that goes forward one expression and then executes the last expression. The keyboard macro is very easy to keep repeating until there's an error. But if there's something more complicated, like I have to do a lot of steps in order to reproduce the problem, then bug-hunter is helpful for that because it does that kind of splitting up for you, and then it'll ask you. It'll either allow you to specify an assertion (something that can automatically check if the error is present), or if there's an interactive thing that you need to do in order to find out whether you're a problem, then it can also prompt you. So that's the bug-hunter package. Highly recommended when weird things are happening with your Emacs configuration.
  • 31:07: Emacs Lisp: All right, Emacs Lisp, Mike Zamanski has released another episode of learning Emacs. He dives deeper into how to use Emacs Lisp to build a thesaurus. And then there's another post on using cl-letf [oops, not cl-flet] to override a function. Sometimes you'll want to run something, but you want to tweak the way that it works. Sometimes you can do that by using a hook if the authors of the code had the foresight of including the appropriate hooks. Sometimes you can do that with advice. But if you're only doing it temporarily, like you don't want your change to happen all the time, but just for this particular call, and you're trying to modify something that's not directly in that function, but maybe like a layer or two down it, then [cl-letf, not cl-flet] allows you to… It's like the way you can use let to change the value of a variable while when you call a different function. [cl-letf] lets you override a function just for the calls that you're going to make. And it does it not just for this direct call, but also for the functions that that function called and so on and so forth. So [cl-letf] lets you change the function that is being used. Simon Dobson's post goes into a lot more detail. It is very hacky when you need to use it, but sometimes that's what you gotta do.
  • 32:41: ert-results: ert-results, there's a package here that allows you to get more views. So if you're writing tests for your Emacs Lisp, ERT is a popular package for doing so. There is a package for displaying the results in different ways, which I haven't looked into, but it looks useful when you're dealing with a lot of tests. There's been some further
  • 33:11: Appearance: discussion on this "I just wanted Emacs to look nice." I think Hacker News had a big thread on it recently with over 170 comments. In addition to this thread, I think there was one like a few days ago that talked about how terminals are complicated. Then there's more stuff in colors and transparency.
  • 33:36: Window configuration: I often need help focusing, as you can probably tell. So, somebody posted this tip for maximizing buffers, but saving the window configuration, and then somebody else pointed out that if you've got winner-mode, you get that for free. I'm still getting the hang of using winter mode myself, just getting my brain used to the idea of going back to a window configuration. Actually, maybe that's a good use of swiping: instead of using the swiping to shift buffers, which I can do fairly comfortably with C-x b, I can just use the swiping as my touch gesture for switching window configurations. Worth a try.
  • 34:33: Org Mode: Org mode, lots of people sharing their workflows, workflows for writing a book in Emacs and Org Mode. There's a YouTube video on that. Workflows for for studying vocabulary. If you're not quite at the level of writing books, you're still learning lots of words, that's okay too, Org Mode's got something for you. Using a checklist to keep track of your shopping list. This post was about using Orgzly with a checklist to do the grocery list. Somebody else in the comments said that they basically export something that uses JavaScript to give them a checkable checkbox, which is another interesting technique. And yeah, so more Org Mode in real life. Basic Citations in Org has another post, so if you're interested in writing scientific papers and other things like that, Org Mode has citation support to make that easier for you.
  • 35:38: Completion: Ah! So, a couple of interesting resources for completion. This one, I think, is… This one is more about Ivy and counsel, which you don't see as many posts about these days. If you do use Ivy, then that's definitely worth checking out. That's Martin Fowler's post "Improving my Emacs experience with completion."
  • 36:02: Compile: Coding: there was a long video on compile and other things you can do with a compile command, including setting file-specific compile commands, which is helpful. Not just compile in the traditional way we think of (you have some source code, you compile it into a program), but also compile as in, "I always want to run these commands after I edit this file." It could be a configuration file and then your compile command could restart the service that uses that configuration file, for example. So that's "Compile with confidence: a deep dive into compiling code with Emacs," which is 15 minutes and worth checking out.
  • 36:54: Window configurations: Going back to the window configurations: Kalman already shared using registers, which is the same technique as discussed in the Reddit post. The function in the Reddit post about window configurations–sorry, temporarily maximizing your windows, the Reddit thread was called. The function saved the window configuration to a register to make it easier to restore. That's definitely a useful technique. A couple of LSP related things.
  • 37:28: Attaching files: Oh, and there was this interesting one about "Have you ever sent an email with a file attachment that is located on a server?" Where Christian did was use Dired to look for a file that was remote, because you can easily work with files on different computers by using Tramp. Yeah, okay, so Christian used Dired to get to a server over SSH, find the file, and then use Embark to attach the file to a mail composition buffer, which is fascinating. It made me start thinking about if whether you could maybe use the org-store-link mechanism as well. So you store the link, and then instead of inserting the link somewhere else, you might just have an attached file from a stored link, and it would figure out the location to attach. That way, you can go back to the mail buffer that you want to insert it into, and you can insert that there. Yeah, so this function uses Gnus, but it's fairly easy to do that with just a regular mml-attach-file as well. So you don't have to use Gnus for this. If you're using notmuch, you can use that to insert it. Because Emacs lets you use Tramp to work with files on remote systems as easily as you do on your system, attaching something from somewhere far away is actually fairly straightforward.
  • 39:10: Reading comic books: Cool stuff. Oh, "GNU Emacs as a comic book reader" is in the fun category. This got picked up a bit in Mastodon as well. I saw some people tooting about it because… Fun! So comic books are often packaged as archives that have the image files in them. Emacs can understand archive files and Emacs can understand images. You can just put that together with a little bit of help in like flipping the pages. Apparently, you can read comics inside Emacs, which makes me start thinking about okay, well, what else can we do with images in Emacs? A little bit later in this blog post actually… There's a magnifier in a recent blog post, I think, adding a magnifier to the thing. Where is that? So there's a little magnifier over here, which I am going to go look into how that's happening, because that sounds like a fun thing to do for my sketches as well. I'd like to be able to say, okay, I'm talking about this sketch, but highlight a section for easier looking at. Community-wise, FOSDEM– was going on? Is going on? People are posting stuff about having enjoyed it. So it's either currently going on or it's done. FOSDEM is a big free and open source software conference, plus a lot of community stuff. There is a community track. So if you're curious about the community plumbing thing that I mentioned at the start of this live stream, you can go check that one out. Apparently there are lots of interesting talks. So that's my Emacs news highlights. You might have slightly different Emacs news highlights. Totally cool. Everybody gets something different out of it. So let me switch back to the chat, and then I can start saying hello to other people who have dropped by. Hello DJ Cthulhu and Data Monoid and and everybody else who's watching. It's very strange. The kiddo is not waking up yet, so I guess I can just keep taking advantage of this time.

Recent additions to my Emacs configuration

  • 42:01: Org-modern: Okay, where was I? I'm experimenting with org modern and variable pitch, but I'm not sure if I'm doing this entirely well. At least the headlines are bigger now, so we're going to see if that changes things in making my Org files a little bit more manageable when I am wandering around.
  • 42:27: Recent additions to my Emacs configuration: Let's see. Oh yeah, we can find out what else I've added to my configuration recently. I just have a bad habit of forgetting to add things.
  • 42:49: Exporting captions in Org Mode: So, captions. I very much like having captions and transcripts, partly because I'm using these live streams as an opportunity to braindump text for blog posts and presentations and things like that, right? If I look at my recent post, for example, for Yay Emacs, I'll take you through the source code for it behind the scenes. Now I have these caption links. I'm playing around with it first. This will export a section of my captions without my having to do any more manual fiddling around with it. Okay, I need to actually load this up. So this is a subed file. (Why is it not subed-mode? I think my configuration only partially loaded.) So subed allows you to edit the captions while having the video right beside it, which is handy because then I can jump around and correct things and so forth. The thing that I added to it recently was being able to export a section of the transcript with the times so that I can synchronize them. So that's fairly straightforward now. And then if I want to edit the text a bit more, then I can also have a function that specifies the start and the end, and then exports that part of the text with the timestamps on it, at least for the paragraphs. What that does is it makes this… Let me bring up a blog post… It makes this part over here so that I can click on–theoretically, I will eventually be able to click on something in order to jump to that specific point. Or at least in the meantime, you can look at the times and go to it. There's something that needs fiddling with for the JavaScript to have that synchronized, but, step by step, right? This part over here… When I publish a blog post about my live streams, I want to be able to include the video. I want to include the transcripts. I want to have times on the transcripts so that people can jump to the specific section if they want more details. I also want to be able to have my own structure around it. So, for example, I might want to have headings, or I might want to have lists, or something like that. If I have both the ability to put in extracts from the transcript, as well as use Org Babel to evaluate the code that gives me the transcript so that then I can fiddle around with it, I can copy and paste into a separate section and do my own editing, then I think that's pretty cool. That's another thing that I worked on recently for that. The reason I do that is because I have very little patience when it comes to going through things. (Aforementioned not having a lot of computer time.) I like skimming through transcripts. I like finding text in them. I like jumping to specific sections. I want to make that as easy as possible as well for other people who are watching this stuff, which gives me then the freedom to blather on about stuff while knowing that if there's something interesting, people can go find it again afterwards. So the process of getting the automatic speech recognition version, it's fairly easy. I can just use my my-deepgram-recognize-audio command to do it. Then I can turn that into a blog post with very little editing. Then people can go figure out, you know… Eventually this can be polished into something that makes more sense, because I tend to go off in tangents and repeat words and use filler words and all that stuff. So, that is a thing that is in my config now.
  • 47:44: Committing the changes to my config: Okay, so that's another change. Yeah, okay, so those are all the changes I did for this week. Hooray, I should remember to add that. This is touch. Okay, don't panic. All right, Compile. Create commit. Yes, I want all the commits. Okay. Diffing changes. Okay, okay. So, this was touch gestures. This is good. This is, you know, This is a good reminder for me to go actually commit things. Video export. I think that was it.

Other questions, finding help

  • 48:31: Question about Org tables and vocabulary: The question here is, trying to use the org table as a vocabulary manager. What do you do if you have multiple languages for each column, such as English, Tamil, and Mandarin, and you're having problems with misalignment? I'm not sure whether… Oh, good, other people have the same question. Okay, I'm not sure whether specifying the column width is going to be enough, or maybe like different column widths. Do you know that you can, okay, so if you have… If you have a table, column 1, column 2, column 3, you might have really long… Now, if you can specify, I think, the width this way… It's not working. Okay, I C-h i m Org mode Table Column width and alignment… Okay, Let's see if we can get that to work. So theoretically this should have aligned it, but maybe it doesn't. C-c C-c should have split it up. I wonder if Org Modern is playing around with this. I am not entirely sure. That might be a good question for the Org Mode mailing list. They are very helpful over there. So unlike emacs-devel, which can sometimes be a little terse, I guess, Org Mode is specifically set up so that the Org mailing list has help and development questions and everything in one place. It tends to be the place to go for questions because they are cool. There's also an orgmode subreddit where sometimes people have shared questions like that and tips like that too. I would recommend, if you write about what you've done so far and where you're getting stuck, either the Org Mode mailing list or the Org Mode subreddit, which is at reddit.com/r/orgmode. Those might be two good places to ask Org-Mode specific questions, because chances are, no matter what workflow you are trying to figure out, someone out there has the exact same itch and has figured something out. Okay. All right. How to find…
  • 51:18: OrgMeetup: Ah, yes. There is also an Org meetup. I should point that out because it is awesome and because Ihor writes such lovely notes. So there is an OrgMeetup which I think he actually tries to organize about monthly. And it's always great fun. Then he has like really, really detailed notes, including bug reports or interesting features that people are playing around with and so on and so forth. So OrgMeetup is a third place to go if you want help with org things, and they are very lovely. Yes. And then Data Monoid points out that there's a matrix room and Yandar, one of the org maintainers, is around there too, so you can ask. There's also an #org-mode channel on Libera chat. So, yes, places to ask for help.
  • 52:27: Finding help in Emacs: There's a question here about how to find help in Emacs. So of course, you can find documentation inside Emacs itself using the info manual, like the way you saw me look things up right there too, and C-h f, which is describe-function. But let's say that you need help going beyond that. There is the help-gnu-emacs mailing list, and people ask a variety of questions there. If you're starting with a starter kit like Doom Emacs, then you'll also want to check out the community that's specific to that starter kit, because starter kits come with thousands of lines of code that modify the Emacs experience. It can be challenging for people who are using vanilla Emacs or a different configuration of Emacs to figure out where you're starting from, if you're using a starter kit that's different from theirs. If you're using a starter kit, check out the starter kit's community as well. As I mentioned, there's an Emacs subreddit and I see a lot of people asking questions on that too. It's very helpful. People often post snippets and say, okay, this is what I figured out so far, but I'm getting stuck. Or they ask questions on how to do things. That's all good stuff. Just slightly annoying, ads-wise, but you can skip past them. There are the IRC channels on libera.chat. There's an #emacs channel and there's #org-mode and I think there's an #emacs-beginners one as well. Those tend to look like they're off topic most of the time because people are chatting, but sometimes if you come in with an Emacs question, then people will go and answer them if somebody knows the answer. It can be a little hit or miss because you don't know whether someone who's got the same interests is on at the same time, but if you're looking for kind of a quick back-and-forth, that's another place to drop by. Other places to ask for help… Posting on the mailing list or in Reddit. There's also an Emacs Stackexchange. I don't know how active it is. Sometimes I see links to posts on it. so that's another place. But yeah lots of places to go find somebody who has a similar kind of thing.
  • 55:19: Why is Emacs fun for you?: Speaking of finding things, finding someone who's got a similar kind of thing, there is a conversation about what is it that makes Emacs fun for you, which I was going to point out in the upcoming Emacs news because it's interesting to see the kinds of things that resonate with people. So that's one of the discussions that is out there on the Emacs subreddit. Okay, my voice is starting to give out, so in maybe 5 minutes I'm going to wrap up. Plus also, I want to make sure that the transcript isn't so long that I end up with this mile-long blog post afterwards. Data Monoid says that Emacs Stack Exchange is actually fairly active and they got some clarification on display line numbers mode. So there's another place to go and ask questions.
  • 56:23: Sharing your notes: Long-term, I highly, highly recommend using Emacs to write your notes about Emacs learning, and then posting that as a blog because (A) it'll help you as you think through the stuff that you want help with and (B) if it's up there, then people can come across it and they can be helped by your notes as well, which builds good karma. When you write about something, inevitably someone will come along and say, oh yeah, there's a better way to do that. It's happened to me numerous times. I get very excited about something clever I figured out, and then someone points out that it's a built-in package for it. So I highly recommend taking notes and sharing them. Again, you don't have to be an expert. In fact, it's really good to do this as a beginner starting out. Org Mode makes it very easy to do so. You can post to a WordPress blog or you can publish your site directly from Org Mode. Then you can take advantage of Org Mode's literate programming support to have your code and your notes all together. That helps you remember things, and that helps other people understand the context. Who knows maybe they'll get inspired by what you're doing and they'll go back through your archive and share even more tips and so on. It's all very good stuff. Highly recommend if you are asking for help. In addition to sharing what you've been doing so far in your Reddit or mailing list post or whatever, once you figure these things out, please take your notes and put them somewhere, ideally somewhere public, so that when people are searching for the same kind of question in the future, they can find your notes. That will be awesome. Thank you very much. Then you can tell me about it so that I can put it in Emacs News and we can keep those ideas flowing.
  • 58:19: Help on help: Oh yes, so a comment points out there is help on help. Question mark gives you… So C-h is the typical command shortcut for help. It might be different depending on your Emacs starter kit setup or whatever, but C-h is what it is in mine. The question mark here shows you more of a menu, which you can use SPC to scroll through. There's also a quick help, so that just stays around. C-h C-q is quick help. This just gives you a very quick cheat sheet. This is actually configurable, and I was playing around with tweaking it, but I'm waiting for them to figure out kind of other ways to add more stuff to it so I can have my mode-specific help on it more easily. Yes, so there's a lot of help, which is great. Sometimes you don't even know what to look for, and that's where talking to other people about Emacs is very helpful. Because help is great if you know what you're looking for, and reading through the manual is another way to learn the words to look for, but sometimes you're just like, "I want to do this thing and I'm getting stuck. What do I need to do?" That's where you go. Yes. Oh, and as Kalman pointed out, looking at the source code is often also very helpful. In my previous Yay Emacs thing, I went into how you can use helpful to look at the source code of something when you're just looking at the function description. I highly recommend that.

Edebug

  • 01:00:28: Edebug: I also highly recommend using edebug to slowly work your way through a function. Once you've started to get the hang of Emacs Lisp, edebug is super helpful. If you don't know what edebug is yet, I can very quickly squeeze in a quick, demonstration. Let's take a look at that lorem ipsum thing that I just used. That should be fairly straightforward since it just inserts things. Okay, so here, if you use… I don't even know what the menu way to do it is. Okay, M-x edebug-defun, which is I think, [C-u] C-M-x. Then when you call it… so let's say for example, I say [M-x lorem-ipsum-insert-paragraphs], then it will allow you to interactively step through things by pressing SPC. This is edebug. It lets you walk through a function and see where it's actually going. You can press e to evaluate things. So for example, if I want to see what num is, I can press e, type num, and it'll show me the value, which is 4 at the moment, because I called it with a universal prefix argument. So I said, insert 4 paragraphs, please. And it will show you the values of things, assuming you don't accidentally get out of the thing. Mystery. [dealing with some weirdness] This is undo tree. Undo tree is going to help me get back to where I was. All right. This is the buffer that I wanted to revert. Yes. That's the thing that I wanted to run. Sometimes I have a problem where when I'm edebugging, it switches for some reason into insertion, but now it's working. You can see there, I'm stepping through it properly now that I am not panicking. That's how it works. Interestingly, this one does it recursively. How strange. Okay, all right.
  • 01:03:42: Using the menus to explore: So that's edebug. The other thing that you can do while you're edebugging, by the way, is take a look at this menu. A lot of people turn the menus off because it saves them that little fraction of screen real estate, but it's actually very helpful to use it, especially when you're exploring something new for the first time, because then you can see the kinds of functions that people recommend checking out, like you can do step with space, which is what I was doing, and t automatically runs through things. It's called trace. Trace fast does it faster. Also, you can start to look at the different sub menus here. So for example, you can jump to a specific section. It'll tell you what the keyboard shortcuts are for it as well. You can use breaks. So one of the things I played around with a few months ago, was setting a conditional breakpoint. I knew there had to be a way to do it. I just wasn't sure what to call it, but looking through the menu helped me find it. That's another way to find words for things. If you want to look at the backtrace, you can use d for backtrace. If you want to evaluate something, then you can do that. Yeah, so that's edebug. Hey, there's an option for test coverage. I should go check that out. So, edebug is very helpful. And when you're done with edebugging, you can press g to just keep going. And then you can evaluate everything again to take off the edebug instrumentation and just run it as a normal function.

Wrapping up

  • 01:05:19: Wrapping up: So. All right, I really should wrap up because my voice is starting to say, "You're not used to this much talking in one go." But thank you very much for joining me. I will try to get this transcript up and edited sometime within the next few days, and next week let's see if I can manage to squeeze in a little bit of time for coding. It's unlikely because as I previously mentioned, the kiddo gets screen envy, so I'm probably going to be focusing on things that I can sneak in with a drawing. Fortunately, lots of other people are doing great Emacs tutorial videos. You should go check them out if you haven't yet. Protesilaos Stavrou, you've got System Crafters with David Wilson, Emacs Elements… There's a whole bunch of Emacs channels. I include links to those videos in Emacs News, which comes out usually Mondays, sometimes Tuesdays, if things are very busy. Go check them out. I am probably going to be focusing on the things that I can do without necessarily looking up code or writing lots of expressions, because again, very limited computer time. I don't know what that looks like. What is podcast-friendly (so I'm not assuming people can see my screen), and what is my-life-friendly? I'm going to assume that I'm not going to be at the computer figuring out the code… We'll figure it out. It's probably going to involve more drawings. We'll see. Eventually, someday I'll have more computer time, but that time is not yet now. So thank you for joining me. And we might see you again next week. We'll see. Bye-bye! Thank you.

Next livestream will be at [2024-02-11 Sun 07:30] EST: https://yayemacs.com.

View org source for this post

2024-01-29 Emacs news

| emacs, emacs-news

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Hacker News, lobste.rs, kbin, programming.dev, lemmy, planet.emacslife.com, YouTube, the Emacs NEWS file, Emacs Calendar, and emacs-devel. Thanks to Andrés Ramírez for emacs-devel links. Do you have an Emacs-related link or announcement? Please e-mail me at sacha@sachachua.com. Thank you!

View org source for this post

2024-01-28 Yay Emacs: closed captions and synchronized highlights for audio clips; exploring Emacs Lisp functions

Posted: - Modified: | yay-emacs, emacs

<2024-01-28 Sun 07:30-08:15>

  • [2024-02-02 Fri]: Now with our own copy of the video! Synchronized timestamps too.

You can also watch it on YouTube.

00:00:08.519: All right, hang on a second while I get everything back on. Okay. All right. It is 7:30 and let's see. I think we are live. Thank you again for joining me for another Yay Emacs! session. It is January 28th, 2024. This week has been a weird week, so let me just talk about whatever we've got to talk about. I didn't actually get to run to the things that I said I'd work on last week, like soundex, approximate sound matching, or all that other stuff. But I did figure out how to get audio clips from these Emacs livestreams and get them all synchronized with closed captions and sketches and other things in my blog. The other thing that I wanted to cover today was how how to explore Emacs Lisp functions using things like eldoc and helpful and elisp-demos.

Closed captions and synchronized highlights for audio clips

Transcript for this section
  • 1:13: Synchronizing audio clips with closed captions: So, last session, I talked about my evil plans for this thing. I wanted to extract the clip of that section and turn it into a narrated blog post. I didn't want to always post videos because sometimes, as in the case of that one, it's just a sketch and the audio. It's a lot more efficient to just post the SVG as well as the audio recording rather than a video where the visual doesn't change as much. The other nice thing about trying to figure out how to do this with audio is that I can then make it more interactive, in the sense that I can highlight the transcript, or I can let people click on the SVG and get it to jump to the right places instead of just watching. I could use that to get a video to do the right thing too. At some point in my life, I will figure that out, but for now I figured it was good to start simple with some audio. So this is what I ended up doing. I've got this blog post somewhere here. Hang on, I have it in one of my windows. Was it this way? Ah, here it is.
  • 2:36: The output: So I'll show you the result first and then I'll talk a little bit about how I made this happen behind the scenes. This is an audio clip about 5 minutes from the previous thing. If we play this… "If I do this out loud, other people can help out with questions and comments like the way that you're all doing now, which is great, fantastic. And of course, those are all very selfish reasons. So I'm hoping other people are getting…" So while that's playing, I'm displaying closed captions over here so that there's something to look at. Sometimes it's easier for people to understand when there's text. I tend to watch all my movies with subtitles these days. I like that part. This also gets highlighted depending on what the current section is. The way that it works is it listens to the cue change. There's a track that has the VTT file, the captions file, which I slightly edited from the automatic transcripts that you can get out of OpenAI Whisper. So that's a VTT file, which I'll show you in a bit. It listens to the time based on those cue changes, and it highlights the relevant section. For example, if I jump to the middle here, it says, "you learned something from that process." This is the section that it's in, and this is the highlight in the SVG. I think I've made it so that you can click on the times and then it'll jump to the appropriate section. I think you can actually… I'd previously gotten it to work so that you could actually also click on the SVG. Oh, actually, that worked! See, look at that. I can click on the SVG, and it will jump to the right spot as well.
  • 4:29: The Org source code: So how does that all work? Well, with Emacs of course. I have my Org Mode post for this here. Yes. So this is my… This is my blog post for my evil plan for Yay Emacs. And I have a bunch of divs with classes, just to start trying to target different things. In Org, you can basically just say #+begin_ and then anything, and it'll turn that into a class, sorry, into a div with that class wrapping around your begin and end. I have a custom audio link type here. What it does is: it exports the audio player. If you specify a captions file, which, also, I've added to this– this isn't built in–then it will read the captions file and output the track information. You can see that here if you look at audio export. So in audio export… I'm still learning how to work with this variable pitch thing. I would like my code to be fixed pitch, so I will play around with that someday. Okay, so if you've got a captions parameter in the thing here, it will now output this <track kind=subtitles label=captions and so on and so forth. Let me turn my highlight mode back on so you can see that. Then, if you have captions, it also includes this little bit of JavaScript. You can't really get around using JavaScript for this one, but it should degrade well, so that if you're viewing it on Planet Emacs Life or in elfeed or some other viewer that doesn't have JavaScript, then it should just not show anything. You can play the audio, you can read the text transcript that's included below it, but you won't get any of this confusing behavior. But if you do have JavaScript enabled, then it will display the active cue or the active caption in the captions div for that audio. That's how the closed captions appear. And now I can just add that very easily by including that. Actually, come to think of it, I should make sure that I automatically determine the vtt from the file name, because I usually put them in the same directory and name them the same way. Okay, so that's how the track element gets added.
  • 7:17: Adding a transcript at the bottom: But what about the transcript at the bottom? I have a little bit of code here that takes the subtitle list from the subtitles. So I've got here subed-parse-file, which just reads the VTT using subed and returns a list of a list of subtitles with a start and end times. It's pretty long, but you know, it's all there. This is the ID. This is the starting timestamp. This is the ending timestamp. This is the text of it. And if there are any comments, then the fourth element, well, element number 4 will have it, actually number 5, but people are strange and count from 0 in this world. So it gets me that, and then I have a little function here that groups them according to the section they're in. Let me show you what sections those are. I'm using find file at point. This is that one. In order to mark out the chapters, I just add NOTE comments here. That way, I can group the different subtitles by those sections. That makes it easier to read the transcript, when things are divided. Then printing it out is a matter of going over that with map-concat and including this audio time with the data start and a data stop. This gives me this kind of list. Now, I've put that as an Org Babel result, so that if I wanted to change how this is set up, maybe organize it differently, maybe indent some things or promote things to headings instead of bold list items, then it would be easy for me to remove it from the results drawer and edit it. So then this gives me this span class, audio time, data start and data stop, which my JavaScript code can take a look at and highlight whenever the time reaches that. That's handled by this bit of HTML export. Notice that I'm using… So there's that div that I mentioned earlier that has a special class on it. That allows me to target that specific section with some CSS. I can say, all right, for the SVGs in this one, if it's highlighted, then use this color as fill. Position the sticky top thing so that as you scroll down, the audio is always visible for this blog post, which allows you to have the narration read to you while you're scrolling through. I don't want to auto scroll because that feels a little bit too much. I want to give people more control over that. But it's a nice compromise, because then at least, you can always pause or keep track of the captions while you are looking at the sketch. It's starting to turn into a tiny little presentation. The way that it works is very much like the closed captions JavaScript. For every audio time span there is, we're going to turn that into a button so that we can jump to that specified time. Whenever the closed captions change, look for the span of audio time that we want to highlight.
  • 11:00: Highlighting the SVG: We also use pretty much the same code to highlight the SVG. What I've done with the SVG is I went through the process that I outlined previously in, when I talked about animating things. Yeah, so I have a blog post here, "Animating SVG topic maps with Inkscape, Emacs, FFmpeg, and reveal.js," where I talk about how to take an SVG file and start to simplify it so that it makes it easier to animate. I've refactored the code a little bit so that it's easier for me to animate a sketch with just the highlights changing. That's what I used here to identify the different paths and then start setting them up. The image started off as a PDF. I now have a little bit of code that allows me to give a color scheme. I like to highlight most of my sketches with yellow highlighter–pretend yellow highlighter. The actual device only outputs gray, so black, white, and two shades of gray, but it can be fun to distinguish the sketches about technology versus the sketches about parenting versus the sketches about everything else. So that when I'm looking in my sketchbook, sketches.sachachua.com – when I'm looking in my sketchbook, then I can see this is the balance of things and so forth. I can now select that color scheme. I usually select it based on the file name, but I wanted to be able to select the color scheme from Emacs Lisp as well when I'm recoloring sketches. So that's all cool. Now I can also just match on a specific sort of thing. So here I'm matching only on the gray things, and I want to turn those into, instead of one big path, I want to break them up into smaller paths. Afterwards, I identified the paths to assign IDs to them. I got the IDs back, and then I made a table with a start and end times. I currently just manually copy and paste these times from the VTT. So what I did was I looked at the VTT file and I copied the start time into the section over here. For example, this one is we bounce ideas around. The ID that I assigned it is h-bounce. So we copied it over. Then I use this little bit of code to edit the SVG file itself so that I can add the audio time classes to the SVG elements and the data-start and data-stop attributes directly. Alejandro has a question: if this is configured specifically for this org file, or is it for all org files? I'm still experimenting with this code, so I don't know what I want it to be yet. All of these things are just for this particular file. If I find that I'm using this technique a lot, then it'll be something that I can pull out into a function that I can easily call, or maybe even into my standard JavaScript file. But because you can export little bits of HTML inside your Org subtree, it's easy to make something that just targets this specific post by adding a special class around it. Then I can run it through my whole Org 11ty export process. I'm going to drink some water first. So the end result is I have this SVG. Actually, let me see if I can open it up here. You can take a look at the markup itself. This SVG has path elements that represent the highlights. They start off with a regular sort of blue. My JavaScript looks for the audio time classes and looks at the start and stop. If the current time of the audio being played back is within those times, then it will add a class to it that highlights it in a different way. The nice thing about all of this is that because I can work with Org tables in order to specify this, I don't have to think about the markup or think about the times as I'm trying to edit the SVG element, hoping that I don't mess up the syntax, because if I have a typo, then the whole image won't display. So hooray for Emacs Lisp! That's how the whole thing came together. As I mentioned, it's an interesting technique to have narration be synchronized with closed captions as well as highlights in both this text transcript and a sketch. So I think I might use that for future posts, in which case I might make something that allows me to just give it the sound file, which I've extracted from the video, using the transcript as the basis to get that sound file, then it will do all of this stuff for me. If I don't need to do anything fancy with the transcript highlighting and I just want that kind of list, then it could be super straightforward to make something like this for the cases where I'm talking about a sketch. You can also extend the idea to talk about a screenshot. One of the things that I want to make it easier to do is just look at something in more detail while having the narration come to you, so that you're not trying to remember the image as well as scroll down. I'm trying to figure out how this works in terms of the screen layout since I want the images to be nice and large, but I also want the text to be easy to get to while you're looking at the image or whatever. Audio narration might be an interesting compromise where you can be just just be looking at the screenshot or the video–well, if it's a video, it will have that automatically, but it could be an animated GIF or a series of images–and have that audio narration talk you through it so that you don't have to scroll. And so that you can jump around as you like. So that's that. Then of course, since I wanted it to break down to– not so much break down, but I wanted the RSS to still make sense. I wanted to make sure that it looked okay and behaved okay on things like Planet Emacs Life or Elfeed. So as an aside, I ended up digging into how to get that working.
  • 18:27: Planet Emacs Life and mix-blend-mode: It turns out that Planet Emacs Life… So Planet Emacs Life uses this very old RSS aggregator called Planet Venus, which hasn't been updated in more than a decade and didn't actually handle SVG mix-blend-mode which I use so that the highlights… The highlights here are sometimes specified on top of the text. If I just leave it as a regular SVG element, they will cover it. And I want to just use mix-blend-mode: darken so that the highlight and the text can both be visible at the same time, and I don't have to worry about the order of elements in my SVG. But they didn't display well in Planet Emacs Life. And since I run planet.emacslife.com, I can fiddle with it until I get it to work. This is how it originally looked in Planet Emacs Live. And then I had to dig around in it, which is more of a Python thing than an Emacs thing, but I did start to learn how to use PDB to interactively debug Python code, which was kind of fun. Eventually, I figured out how to update the sanitizer so that it would allow me to use the SVG attributes that I wanted to use. I mean, the SVG CSS that I wanted to use. Then it worked there.
  • 19:52: Elfeed and SVGs: Then I also wanted to get it to work for elfeed because I know a lot of people use elfeed to read RSS feeds in Emacs. I didn't need to have all the fancy audio closed captioning work in elfeed because that's too much, but I did want the SVGs to display. In elfeed, the SVGs sort of work in that mix-blend-mode works, but it was too big. So I said, okay, how do we fiddle with this? It turns out that the shr library that elfeed uses to render HTML ignores the cases. It lowercases all the HTML tags because it uses libxml-parse-html-region, which doesn't pay attention to the case sensitivity of tags. Normally, you don't want case sensitivity for HTML tags, but SVGs have case-sensitive tags. I had to rummage around in there in order to find out what to fix. It turns out that most other parsers just special case the SVG tags to get them back to the correct cases for it. So I have this defconst which defines all those attributes, and this recursive function, which goes through this DOM tree and corrects the case of those by using the setcar function. Then shr-tag-svg can use that to fix SVG tags so that then they will properly listen to width and height and viewBox. Well, width and height always work, but it would ignore the viewBox, which is kind of annoying. So now the view box will work, which I like. I've submitted that patch to emacs-devel, so they will go and talk about it and figure out whether it makes sense to them or not. That's the rabbit hole that I end up going through just because of this "Oh, let's use SVGs more." So, Emacs. At least we can tinker around with these things. libxml-parse-html-region just calls a C library that does the actual parsing, but there is a layer on top where you can fiddle with the Emacs Lisp functions that call that in order to get the right output. That's a detour that I went on in order to get this stuff to work. But I'm very tickled that I now have closed captions for audio and synchronized sketches, and things sort of look okay on Planet Emacs Life, even if you don't have JavaScript enabled. So, where, oh yes, yes, yes, okay. Where are we now?

Exploring Emacs Lisp functions

apropos

2024-01-28_16-03-21.png
Figure 1: M-x apropos

00:24:41.380: So how do you find functions in Emacs? Well, there's an apropos command, which is spelled A-P-R-O-P-O-S because the S is silent. Apropos lets you search for something. For example, if you're looking for, let's say, anything related to finding a function, describing a function, function help, maybe. Then it will show you a list of those functions where the documentation matches those keywords or the name of the function matches those keywords. This is one of the things that I often do when I'm trying to find something that… There's probably a function out there to do what I want to do, so I start looking for it.

orderless

(use-package orderless
  :ensure t
  :custom
  (completion-styles '(orderless basic))
  (completion-category-overrides '((file (styles basic partial-completion)))))
2024-01-28_16-05-28.png
Figure 2: Orderless: match completions in any order

00:26:39.280: Orderless is a package that works very well with different kinds of completion if you use this little snippet over here, which sets your completion styles to use orderless. So I'm using eval here to just evaluate that bit. Then I can say M-x and function here will now find things where the match isn't at the beginning. It can be in the middle. It can be somewhere else. You can even specify matches out of order. So, for example, if I know something is related to functions, I might start typing func, function or whatever, and then I might start saying, oh yeah, it's a describe thing, right? Even if you're specifying things out of order, you can get the completion for it. Often when I'm looking around for something, I will use this describe function with orderless and vertical to just start typing the words that I think it might be called. Let me show you that now. For example, the describe-function here… What describe-function does is it gets a name of a function, and it will display the documentation for it. Let's say, for example… Let's look for describe package. So it will describe this information. It will show you where it's found. It will show you what its arguments are and what the documentation is. So that's orderless. It helps you find things.

vertico

(use-package vertico
  :ensure t
  :config
  (vertico-mode))
2024-01-28_16-04-08.png
Figure 3: Vertico completion

00:25:29.380: Another way to do it is just to type in the names and hope that you can find the function that way. Now, when you're starting off with a plain Emacs, it's a little bit sparse. You actually have to remember the things. If you start typing describe, you can use tab for completion. You have to hit it twice to get more of a completion list. So this is one of the things that I tend to encourage people to change right away, because completions make it much easier for you to see what you actually want to do. One of the things that I like to use for this is a package called Vertico. And if I evaluate that, if I use the package and turn on vertico mode, then you'll see that it displays the functions right there. Even if I don't remember how to spell apropos, I can start typing apr and it will display it right away. If I'm looking for something like function, you'll notice that it can't find anything, but that's because we're still missing the next thing that I want to share, which is orderless.

marginalia

(use-package marginalia
  :ensure t
  :bind (:map minibuffer-local-map
              ("M-A" . marginalia-cycle))
  :init
  (marginalia-mode))
2024-01-28_16-08-08.png
Figure 4: Marginalia: margin notes

00:28:10.920: So that's orderless. It helps you find things. The other nice thing that you can add on top of this completion is a package called marginalia. Marginalia, anyway, marginalia, sure. Now, when you're describing functions, sometimes the first line is all you need in order to figure out whether this is something you want or not. Marginalia will let you, let's say for example if you're looking for a function, it will let you see the arguments as well as a brief description of it in the right side here. It adds these margin notes to a lot of the searches, a lot of the completions that you have available. Let's say for example, if I'm looking for… I want a function that works with sequences and it makes things flatter. No, it makes things, okay, let's make, let's pick something that involves splitting things into different groups. And seq-partition here, you can see here that it takes a sequence and it returns a list of elements of sequence grouped into subsequences of length n. Having that function description right there can be really helpful when you're trying to find something. All right. So that's Marginalia.

shortdoc

M-x shortdoc:

2024-01-28_16-09-05.png
Figure 5: shortdoc sequence

00:29:56.020: Another way to find something if you aren't quite sure what you're looking for is shortdoc. With shortdoc, you can give it a group of functions, and the wonderful Emacs developers have already created a whole bunch of cheat sheets for these different functions. For example, I do a lot of work with sequences, which is basically any kind of list or vector or… I think, sets, maybe? I don't know, it's… Anyway, sequences. So there is a shortdoc for sequence, and what it does is it shows you very short documentation (hence short doc) showing you the different important functions in this group, with examples. I really like the fact that I can just flip through this and then in the different sections, try to find the function that I'm looking for. This is especially helpful if you don't know what something is called or even what keywords you might start to look for, because one of the big challenges with Emacs Lisp is just figuring out what things are called. So, shortdoc, you can just call it with M-x shortdoc, and then you can browse through it. As you can see, there are a whole lot of different things that are included there. You can probably define your own too if you want to. For example, string-related functions show me all the things that… Like one time I was trying to figure out whether it was called repeat or whatever. It's actually called make-string. You can see all of the examples there.

helpful

Install from MELPA:

(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
(use-package helpful
  :ensure t
  :bind
  (("C-h f" . helpful-callable)
   ("C-h v" . helpful-variable)
   ("C-h k" . helpful-key)
   ("C-h x" . helpful-command)))
2024-01-28_16-10-56.png

00:31:44.120: Now, this is great for finding functions. but sometimes you want to have even more information about something when you're looking at it. So if I C-h f, which is the describe-function keyboard shortcut, the, it'll default to this, the symbol at point, which is helpful. It'll show me the documentation for it. But you can actually get even more documentation than this. That's where the helpful package comes in, which is another thing that I've been finding really useful. Now, Helpful is not built in, but you can install it from Melpa, which is the Milkypostman Elpa, Emacs Lisp package repository. Oh, sorry, archive, A, not R, archive. You can find the instructions for doing that at melpa.org. So let's get this into our configuration. I paste it in, I evaluate the lines, and then it has a bunch of commands that replace the functions that we have. Well, not replace, but you know, they encourage you to bind it over the keyboard shortcuts for find-function– sorry, describe-function or describe-variable or describe-key and so forth. For example, if I press C-h f, it will now call helpful-callable. If I then use something like seq-find, maybe, then it will show me not only the signature, the arguments for the function, and the documentation for it, which is fairly normal, but it'll give me as well references. It'll let me enable edebugging right from there, and even include the source code. I find that the source… Looking at the source code for functions is very helpful. Before, I used to use describe-function or find-function. Well, describe-function will give you a link to its implementation. And find~function will try to find the… Is it actually called find-function? Yeah. So, there is a find-function that finds the definition of a function, but with helpful, I can get the source code right there. So then I can say, show me all sorts of things, and I don't have to do that extra jump. A whole bunch of other things, in case you're curious: It'll show you the symbol properties or whether something is advised or not. You get some of that as well with a regular describe-function, but this is a little bit extra. So that's the helpful package, which I do find helpful, as it says. As Alejandro points out, even source code in C, if it's available. So I think I was talking about libxml-parse-html-region. libxml-parse-html-region is actually the thing that I mentioned. You'll see here that it's defined in xml.c, but the source code is here as well. All it does is it calls the parse region from libxml2, which is arcane wizardry, and I don't know how to fiddle with the C stuff yet, which is why we ended up hacking it at the Emacs Lisp level instead. So, helpful is actually very helpful. One thing that makes it even more helpful

elisp-demos

(use-package elisp-demos
  :ensure t
  :init
  (advice-add 'describe-function-1 :after #'elisp-demos-advice-describe-function-1)
  (advice-add 'helpful-update :after #'elisp-demos-advice-helpful-update))

Example: set-transient-map

2024-01-28_16-13-08.png
Figure 7: Demos for set-transient-map

00:35:13.260: One thing that makes it even more helpful than that is another package called elisp-demos. elisp-demos adds some extra examples to this. Let's try that out here. Now that I've included that, it has added some advice around helpful-update to load the demos. If I look up something like seq-partition maybe, which is that function we mentioned earlier, you'll notice that there's a new section here called demos, and an example here of how someone uses it to… You pass a list, you pass a number, and it gives you some results. I put in this patch recently that the maintainer has accepted, hooray, and it allows you to add your own notes [with this button]. So you can add a note there. The kiddo is awake, so I'd better talk even faster. Okay, so the last thing I wanted to show is you can use this not only to include– hello kiddo, you're awake, you're awake– not only to include your own examples, but also, you can use it to take other notes. Here, for example, is set-transient-map. There are examples there. If I look at tabulated-list-mode, I think there aren't any demos for this one yet. But, very quickly, I will show you before I feed the kiddo some breakfast– (although if you want, you can start getting your own breakfast)– is you can also use that to add your own notes here. This is a blog post that had a whole bunch of information on how to set up tabulated list mode, which will open eventually in… Ah! Some browser. Okay, I will just open it here because I just remembered my default browser is Firefox, though… We will show that some other time. Okay, so this is the blog post that explains a lot about how to use tabulated-list-mode, or at least it gives a very short example. And then… Actually, let's just copy this over here. Sure, we can add… Ha, it's not added. Let's make that lisp… I don't have my usual structs defined here. OK, so now if I C-h f tabulate-list-mode you can see here the… Oh, that's not an end_export, is it? That should be an end_src. So you can see here, it has the example that we've just added and you can also include whatever notes you have all about the thing. That is probably all I can do today because I gotta go feed a kiddo. All right folks, thank you for joining me. Next stream is probably Sunday again, probably around this time, but maybe with faster talking. Thanks everyone and have lots of fun. Thanks for dropping by!

View org source for this post

2024-01-21 Yay Emacs: copy link, Spookfox + Org Babel, choosing what to hack on, SVG highlighting, ical

| yay-emacs, emacs

<2024-01-21 Sun 07:30-08:15>

Very rough notes, just gotta get them out there! =)

  • 7:24:43 AM Hello and thanks for joining me!
  • Meta information:
  • Do you have any Yay Emacs moments this week?
  • 7:31:23 AM trying vdo.ninja to get the video from the X230T to the Surface Book and using OBS from the Surface Book
  • 7:32:12 AM Org Mode custom link: copy to clipboard
  • 7:34:49 AM Running the current Org Mode Babel Javascript block from Emacs using Spookfox
  • 7:45:42 AM Emacs tweaks: Choosing what to hack on (also, I figured out dynamically highlighting SVG diagrams from Graphviz!)
  • 8:14:16 AM What are you looking forward to exploring next week?
    • Me, maybe:
      • using soundex and a list of commonly misrecognized words to correct transcripts
      • Map of Emacs communities for possible 5-minute lightning talk at LibrePlanet
      • smarter refiling: tag target, active thoughts/posts/projects, card/pile sorting
      • (Update: None of this happened, but that's cool! Figured out how to add closed captions for audio on my site and how to synchronize sketch highlights with the audio)

Also, my Evil Plan for Yay Emacs!

I'd love to hear your comments via YouTube live chat, Mastodon (I'm @sachac@emacs.ch), or e-mail (sacha@sachachua.com).

Thanks to:

Other notes:

Next livestream: Sat 2024-01-28 7:30 AM EST, https://yayemacs.com and https://youtube.com/@sachactube/live . I'll probably talk about learning more about Emacs Lisp functions using apropos-function, eldoc, marginalia, helpful, and elisp-demos. See you then!

View org source for this post

Updating Planet Venus so that planet.emacslife.com can handle mix-blend-mode in my SVGs

| geek, python

I wanted to easily turn segments from my Yay Emacs livestreams or recorded narration into closed-caption audio and dynamic highlighting of my SVG sketches and text transcripts. That way, people could easily jump around to sections they're interested in.

Not everyone has Javascript turned on, so I wanted to start with something that made sense even in RSS feeds like the one on Planet Emacslife (which strips out <style> and <script>) and was progressively enhanced with captions and highlighting if you saw it on my site.

2024-01-25_08-37-11.png
Figure 1: My SVGs were broken: black fill, no mix-blend-mode

The blog aggregator I'm using, Planet Venus, hasn't been updated in 14 years. It even uses Python 2. I considered switching to a different aggregator, so I started checking out different community planets. Most of the other planets listed in this HN thread about aggregators looked like they were using the same Planet Venus aggregator, although these were some planets that used something else:

I decided I'd stick with Planet Venus for now, since I could probably figure out how to get the attributes sorted out.

I found planet/vendor/feedparser.py by digging around. Adding mix-blend-mode to the list of attributes there was not enough to get it working. I started exploring pdb for interactive Python debugging inside Emacs, although I think dap is an option too. I wrote a short bit of code to test things out:

import sys,os
sys.path.insert(1, os.path.join(os.path.dirname(__file__), 'planet/vendor'))
from feedparser import _sanitizeHTML
assert 'strong' in _sanitizeHTML('<strong>Hello</strong>', 'utf-8', 'text/html')
assert 'mix-blend-mode' in _sanitizeHTML('<svg><path style="fill: red;mix-blend-mode:darken"></path></svg>', 'utf-8', 'text/html')

It was pretty easy to use pdb to start stepping through and into functions, although I didn't dig into it deeply because I figured it out another way. While looking through the pull requests for the Venus repository, I came across this pull request to add data- attributes which was helpful because it pointed me to planet/vendor/html5lib/sanitizer.py. Once I added mix-blend-mode to that one, things worked. Here's my Github branch.

2024-01-25_08-51-33.png
Figure 2: planet.emacslife.com now lets me use mix-blend-mode

On a somewhat related note, I also had to patching shr to handle SVG images with viewBox attributes. I guess SVGs aren't that common yet, but I'm looking forward to playing around with them more, so I might as well make things better (at least when it comes to things I can actually tweak). mix-blend-mode on SVG elements says it's not supported in Safari or a bunch of mobile browsers, but it seems to be working on my phone, so maybe that's cool now. Using mix-blend-mode means I don't have to do something complicated when it comes to animating highlights while still keeping text visible, and improving SVG support is the right thing to do. Onward!

View org source for this post

Patching elfeed and shr to handle SVG images with viewBox attributes

Posted: - Modified: | emacs

I want to use more SVG sketches in my blog posts. I would like them to look reasonable in elfeed. When I first checked them out, though, the images were a little too big to be comfortable.

To test things quickly, I figured out how to use Elfeed to display the first entry from a local file.

(with-temp-buffer (get-buffer-create "*elfeed*")
  (elfeed-show-entry
   (car
    (elfeed-entries-from-rss
     "file:///tmp/test/index.xml"
     (xml-parse-file "/tmp/test/index.xml")))))
2024-01-26_08-34-03.png
Figure 1: The image is a little too big to be comfortable

I'd just been using the default width and height from the pdftocairo import, but changing the width and height seemed like a good first step. I could fix this when I convert the file, export it from Org Mode as a my-include link, or transform it when processing it in the 11ty static site generator. Let's start by changing it in the SVG file itself.

(defun my-svg-resize (file width height)
  "Resize FILE to WIDTH and HEIGHT in pixels, keeping aspect ratio."
  (interactive "FSVG: \nnWidth: \nnHeight: ")
  (let* ((dom (xml-parse-file file))
         (orig-height (string-to-number (dom-attr dom 'height)))
         (orig-width (string-to-number (dom-attr dom 'width)))
         (aspect-ratio (/ (* 1.0 orig-width) orig-height))
         new-width new-height)
    (setq new-width width
          new-height (/ new-width aspect-ratio))
    (when (> new-height height)
      (setq new-height height
            new-width (* new-height aspect-ratio)))
    (dom-set-attribute dom 'width (format "%dpx" new-width))
    (dom-set-attribute dom 'height (format "%dpx" new-height))
    (with-temp-file file
      (xml-print dom))))

Even when I changed the width and height of the SVG image, the image didn't follow suit. Mysterious.

2024-01-26_08-34-32.png
Figure 2: SVG image cut off

After a bit of digging around using Edebug, I found out that elfeed uses shr, which uses libxml-parse-html-region, and that converts attributes to lowercase. This is generally what you want to do for HTML, since HTML tags and attributes are case-insensitive, but SVG tags are case-sensitive. It looks like other implementations work around this by special-casing attributes. libxml-parse-html-region is C code that calls a library function, so it's hard to tinker with, but I can at least fix the behaviour at the level of shr. I took the list of SVG attributes to correct case for and wrote this code to fix the attribute cases.

List of atttributes to correct
(defconst shr-correct-attribute-case
  '((attributename . attributeName)
    (attributetype . attributeType)
    (basefrequency . baseFrequency)
    (baseprofile . baseProfile)
    (calcmode . calcMode)
    (clippathunits . clipPathUnits)
    (diffuseconstant . diffuseConstant)
    (edgemode . edgeMode)
    (filterunits . filterUnits)
    (glyphref . glyphRef)
    (gradienttransform . gradientTransform)
    (gradientunits . gradientUnits)
    (kernelmatrix . kernelMatrix)
    (kernelunitlength . kernelUnitLength)
    (keypoints . keyPoints)
    (keysplines . keySplines)
    (keytimes . keyTimes)
    (lengthadjust . lengthAdjust)
    (limitingconeangle . limitingConeAngle)
    (markerheight . markerHeight)
    (markerunits . markerUnits)
    (markerwidth . markerWidth)
    (maskcontentunits . maskContentUnits)
    (maskunits . maskUnits)
    (numoctaves . numOctaves)
    (pathlength . pathLength)
    (patterncontentunits . patternContentUnits)
    (patterntransform . patternTransform)
    (patternunits . patternUnits)
    (pointsatx . pointsAtX)
    (pointsaty . pointsAtY)
    (pointsatz . pointsAtZ)
    (preservealpha . preserveAlpha)
    (preserveaspectratio . preserveAspectRatio)
    (primitiveunits . primitiveUnits)
    (refx . refX)
    (refy . refY)
    (repeatcount . repeatCount)
    (repeatdur . repeatDur)
    (requiredextensions . requiredExtensions)
    (requiredfeatures . requiredFeatures)
    (specularconstant . specularConstant)
    (specularexponent . specularExponent)
    (spreadmethod . spreadMethod)
    (startoffset . startOffset)
    (stddeviation . stdDeviation)
    (stitchtiles . stitchTiles)
    (surfacescale . surfaceScale)
    (systemlanguage . systemLanguage)
    (tablevalues . tableValues)
    (targetx . targetX)
    (targety . targetY)
    (textlength . textLength)
    (viewbox . viewBox)
    (viewtarget . viewTarget)
    (xchannelselector . xChannelSelector)
    (ychannelselector . yChannelSelector)
    (zoomandpan . zoomAndPan))
  "Attributes for correcting the case in SVG and MathML.
Based on https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inforeign .")

This recursive function does the actual replacements.

(defun shr-correct-dom-case (dom)
  "Correct the case for SVG segments."
  (dolist (attr (dom-attributes dom))
    (when-let ((rep (assoc-default (car attr) shr-correct-attribute-case)))
      (setcar attr rep)))
  (dolist (child (dom-children dom))
    (shr-correct-dom-case child))
  dom)

Then we can replace shr-tag-svg with this:

(defun shr-tag-svg (dom)
  (when (and (image-type-available-p 'svg)
             (not shr-inhibit-images)
             (dom-attr dom 'width)
             (dom-attr dom 'height))
    (funcall shr-put-image-function
             (list (shr-dom-to-xml (shr-correct-dom-case dom) 'utf-8)
                   'image/svg+xml)
             "SVG Image")))

The result is that the image now respects width, height, and viewBox:

2024-01-26_08-33-31.png
Figure 3: Fixed image

Here is a small test for shr-correct-dom-case:

(ert-deftest shr-correct-dom-case ()
  (let ((case-fold-search nil))
    (should
     (string-match
      "viewBox"
      (shr-dom-to-xml
       (shr-correct-dom-case
        (with-temp-buffer
          (insert "<svg viewBox=\"0 0 100 100\"></svg>")
          (libxml-parse-html-region (point-min) (point-max)))))))))

And another test involving displaying an image:

(with-current-buffer (get-buffer-create "*test*")
  (erase-buffer)
  (insert "<svg width=\"100px\" height=\"100px\" viewBox=\"0 0 200 200\"><circle cx=\"100\" cy=\"100\" r=\"100\"/></svg>\n")
  (shr-insert-document (libxml-parse-html-region (point-min) (point-max)))
  (display-buffer (current-buffer)))
2024-01-26_09-09-48.png
Figure 4: Correct output: full circle

shr.el is in Emacs core, so I'll need to turn this into a patch and send it to emacs-devel at some point.

View org source for this post