diff --git a/.drone.yml b/.drone.yml deleted file mode 100644 index d231983..0000000 --- a/.drone.yml +++ /dev/null @@ -1,51 +0,0 @@ -kind: pipeline -name: default - -steps: -- name: build - image: silex/emacs:27-alpine - commands: - - apk add hugo git - - git submodule update --init --recursive - - mkdir blog - - emacs --script .export.el - - hugo -d blog - -- name: deploy - image: appleboy/drone-scp - settings: - host: - from_secret: ssh_host - target: - from_secret: ssh_target - source: blog/* - strip_components: 1 - username: - from_secret: ssh_username - password: - from_secret: ssh_password - port: - from_secret: ssh_port - when: - branch: - - master - event: - exclude: - - pull_request - -- name: purge cache - image: jetrails/drone-cloudflare-caching - settings: - api_token: - from_secret: cloudflare_cache_api - zone_identifier: - from_secret: phundrak_com_zone_id - action: purge_files - list: - - https://blog.phundrak.com - when: - branch: - - master - event: - exclude: - - pull_request diff --git a/content-org/blog.org b/content-org/blog.org index 8f56a1a..be0c724 100644 --- a/content-org/blog.org +++ b/content-org/blog.org @@ -808,6 +808,430 @@ Happy programming! * Emacs :@emacs: +** Emacs 31 is coming, and here’s what’s new! :dev:emacs:release: +:PROPERTIES: +:EXPORT_FILE_NAME: emacs-31-is-coming-heres-whats-new +:EXPORT_DATE: 2026-01-02 +:EXPORT_OPTIONS: toc:2 +:export_hugo_menu: :menu "main" +:END: +[[https://blog.phundrak.com/emacs-29-what-can-we-expect/][A few years ago]], I published a blog post regarding what was new in +Emacs 29 as it came close to being released. I missed the mark for +Emacs 30, but now, Emacs 31 is getting ready for release. + +So, what can we expect for Emacs 31? Everything’s written in its =NEWS= +file, but here are some elements I think are important. Be warned, +although I’m not as hyped as I was for Emacs 29 that brought a few big +features, this article is quite a bit longer. + +*** Breaking Change + +**** Configuration +=site-start.el= will now load before your =early-init.el=, instead of +after it. + +**** Python +=python-mode= will now default to calling =python= instead of =python3=, +though it will fall back to =python3= if =python= is not found. Most modern +systems no longer ship Python 2, and =python= most likely points to +Python 3. If =python= still points to Python 2 on your system, you *MUST* +change the value of =python-interpreter= and =python-shell-interpreter=. + +As Python 2 has been EOL for five years now, its support is now +optional and disabled by default. + +*** Editing +With the new option =kill-region-dwim= set to non-nil, calling +=kill-region= will now kill the last word instead of raising an error if +no region is selected. + +Electric Pair mode got better: you can now set strings using multiple +characters in =electric-pair-pairs=, such as ='("r#\"" . "\"#")= to +surround a region with =r#"= and ="#=. And if you want an extra space +between your delimiters and the selected region, you can instead use +='("r#\"" "\"#" t)=. Also, providing a numerical prefix argument to +electric pair allows you to insert multiple delimiters at once. Now, I +just need mode-aware electric pairs to replace [[https://github.com/emacs-evil/evil-surround][evil-surround]]. + +Do you use =query-replace=? Well, you can now use =M-s t= to swap =FROM= and +=TO= during a =query-replace= or =query-replace-regexp=. And the original +=M-s= is now =M-s M-s= or =M-s s=. + +And do you like always having the line you’re editing to be at the +centre of your window? Activate =center-line-mode=. + +Accidentally hit =M-q= (=fill-paragraph=) and you want to undo it? Or you +simply want to “unfill” your paragraph? Simply invoke =unfill-paragraph= +(which I will probably bind to =M-Q=). + +*** TTY Improvements +One of my biggest gripes with Emacs in the terminal is how limited it +feels to its GUI version. Child frames, for instance, are one of TTY +Emacs’ limitations. Or, rather, /was/. + +Starting from Emacs 31, TTY Emacs will support child frames, thanks to +=tty-child-frames=. Hurray for Posframe and Corfu users among many +others! + +The option =xterm-mouse-mode= is also now enabled by default in +terminals that support it, i.e. allowing Emacs to access the OS’ +clipboard and mouse events. This means you can now bind mouse events +to Emacs functions, but at the cost of now having to rely entirely on +Emacs to copy and paste text instead of relying on your terminal +emulator. + +Also, you can now rename your TTY frames to =F=, though it will +throw an error if that name is already taken. + +*** Proper Support for User Lisp Directories +Emacs will natively support your =user-lisp/= directory in your Emacs +config directory (either your =$HOME/.emacs.d/= or your +=$HOME/.config/emacs/= directories) by recursively byte-compiling all of +its =.el= files and adding them to your =load-path=. It will also look for +autoloaded elements like it would for other packages, so no need to +explicitely require your =.el= files anymore! + +This feature can be disabled with =(setq user-lisp-auto-scrape nil)=, or +you can change the directory =user-lisp-directory= points to if your +personal Elisp files are stored somewhere else. + +Very nice, thanks Emacs devs! + +*** Visual Customization and Improvements +**** Display +The new char-table =special-mirror-table= allows you to define +replacement characters for characters Emacs may have trouble +displaying. I think that, for most native English speakers, this +feature might be pretty useless, but it can be very interesting if you +deal with glyphs that are not ASCII, especially if they are part of +your writing system (Arabic, Mandarin, Cyrillic, etc…). + +I, for one, am excited for this, as I use Emacs for most of my +worldbuilding projects, which include conlanging (creating languages), +and it requires me sometimes using characters Emacs has troubles +representing. I also have some glyphs in my Linux that render properly +with certain fonts that Emacs cannot render well with the font it +uses, therefore not making the config all that readable (I’m looking +at you, [[https://labs.phundrak.com/phundrak/nix-config/src/commit/5514d347c754ea17dd2a3ecb40fed6a62182c7ea/users/modules/desktop/waybar.nix#L59-L71][my Waybar configuration]], which I should remove since I already +don’t use Waybar any more). + +On the topic of display customization, a few font-locks were deprecated: +- =font-lock-builtin-face= +- =font-lock-comment-delimiter-face= +- =font-lock-comment-face= +- =font-lock-constant-face= +- =font-lock-doc-face= +- =font-lock-doc-markup-face= +- =font-lock-function-name-face= +- =font-lock-keyword-face= +- =font-lock-negation-char-face= +- =font-lock-preprocessor-face= +- =font-lock-string-face= +- =font-lock-type-face= +- =font-lock-variable-name-face= +- =font-lock-warning-face= + +They all have equivalents, you should customize them instead of these +deprecated font-locks. + +**** Windows +We get some new commands for manipulating our window layouts! +- =C-x w t= and =C-x w r /= to rotate the window layout +- =C-x w o /= to rotate the windows within the current + layout +- =C-x w f ///= to flip the layout + +And now, you can also indicate to Emacs to kill buffers when their +window is closed, thanks to the =kill-buffer-quit-windows= option. But I +think I’ll personally stick to =kill-buffer-and-window=, this new option +seems a bit overkill for me. Still, quite nice to have! + +Some commands and functions will create new windows on their own. +Emacs’ current behaviour is to split below if possible, and split +right otherwise. But now, =split-window-preferred-direction= introduces +three values: +- ='longest= :: somewhat similar to the current behaviour, and the new + default value: split below if your window is taller than it is wide + (Emacs’ preferred direction whenever possible), split right + otherwise. But what if both options are possible? Well, now, you can + set =split-width-threshold= (now 150 instead of 160) and + =split-height-threshold= to determine the correct behaviour to follow. +- ='vertical= :: always split below +- ='horizontal= :: always split right + +The new command =other-window-backward= is also finally here! Ever +wanted to go back to your initial window after =C-x o= (=other-window=)? +Just use =C-x O= to go back! + +**** Frames +Ever wondered how much time you’ve spent in a frame, like how you can +already determine it with =window-use-time= (which I just discovered +now)? With Emacs 31, you can now use the function (not command) +=frame-use-time=. + +=delete-frame= now sends you to your most recently used frame, not the +first one in the list of frames. A small change, but a welcome change. + +The new command =split-frame= now allows you to create a new frame and +send windows of your current frame to this new frame. The command +=merge-frames=, on the other hand, brings back a frame’s windows into +another before killing it. Very nice if you want to bring back a TTY +frame into another GUI frame, and /vice versa/. + +Also, frames cloned with =clone-frame= (which I just discovered exists) +are now aware which frame they were cloned from, and if they were +undeleted with =undelete-frame= (how many commands will I learn exist +while writing this article?). And all frames have now a unique ID, +much easier to refer to a specific frame in your Elisp code, such as +with the new commands =select-frame-by-id= or =undelete-frame-by-id=. + +**** Mode Line +The mode line can now collapse its minor modes when setting +=mode-line-collapse-minor-modes= to non-nil, useful when it becomes to +feel bloated. By default, it’s =nil=, so it won’t change its default +behaviour. It also became much easier to customize, using +=mode-line-modes-delimiters= to change or remove the existing +delimiters. Writing new mode line themes is about to get a lot easier! + +But what if you don’t want to see the mode line? Well, hide it with +=mode-line-invisible-mode=, and enjoy your distraction-free Emacs! + +**** Tabs +When tabs were introduced in Emacs, I didn’t really see the point +initially, until I realized they’re somewhat similar to sub-frames +without actually creating new frames. Very nice if, like me, you +prefer to have a single frame despite working on several projects with +the same Emacs instance. But an issue I often encounter (might be a +skill issue on my part) is that they sometimes become quite bloated, +crossing over multiple projects, at which point I decide to create +another tab and restore one specific project to that tab, recreating +my window layout with the buffers I want. That’s a tad tedious. + +Well now, you can invoke the command =split-tab= to clone your current +tab to a new one and keep your windows! And of course, it comes with +=merge-tabs=, in case you’re finally done with this specific issue your +tab was for, and you want to go back to the project’s general tab. And +in case you have a lot of tabs opened, =tab-bar-truncate= when set to +non-nil will now truncate your tabs list, instead of squishing them +together and avoid any ugly text wrapping. + +The use-case =tab-line-mode= is, however, a bit more mysterious for me, +but I guess it makes sense when you come from editors like VS Code and +are used to see all your open files as tabs (not Emacs tabs, but more +what I expected tabs to be when they were first announced). And now, +you can use =tab-line-define-keys= and set it to =nil= to avoid +=tab-line-mode= redefine =C-x /= switch between the visual +tabs and go back to Emacs’ vanilla behaviour. You can also move your +tab’s position among your tabs in =tab-line-mode= with the new commands +=tab-line-move-tab-forward= and =tab-line-move-tab-backward=, which are +bount to =C-x M-/=. And you can also set +=tab-line-exclude-buffers= to exclude known buffers from the tabs, such +as =*scratch*= or =i-dont-want-my-boss-to-see-this-when-he-walks-by.txt=. +In fact, you can even have even more powerful filtering using +=tab-line-tabs-window-buffers-filter-function=. And using the option +=tab-line-close-modified-button-show=, you can see the close button +visually warning you the buffer has been modified but not saved. Nice. + +Something I just learned is that you can close tabs with your mouse’s +middle click. But what if you made a mistake, clicked on the wrong +tab, and realized your mistake before releasing the button? Until +Emacs 30, that’s too late. Since Emacs 31, the tab will be deleted +once you release the button, so you can still move the mouse and +release the button either on the correct tab, or outside the tabs area +if you don’t want to close anything. + +*** Completion Improvements +The =*Completions*= buffer can now be much faster, updating as you +write, given the =eager-update= completion property is non-nil. And if +you don’t like the default value of the property, you can override it +with =completion-category-overrides=. And you can force the +autocompletion to update eagerly with =(setq completion-eager-update t)= +(or any value that is non-nil, but why not just use =t=?), but that can +slow Emacs down; I turned it off on my ThinkPad X220 and its +Intel Core i5-2540M (yes, I still use it), but on for my main desktop +computer with its AMD Ryzen 7 9800X3D. I should upgrade my X220’s CPU +sometime. But fortunately, the =*Completions*= buffer still got a +performance upgrade, especially when many candidates exist, though +with one caveat (see below in this chapter). + +You can also now separate what the up/down keys do from the left/write +keys when in the minibuffer! If you set the +=minibuffer-visible-completions= option to ='up-down=, you can now have +the up/down keys select different suggestions in the =*Completions*= +buffer, while the left/write keys moves your cursor in the minibuffer. +Similarly, the =M-= and =M-= keys now allow you to select +candidates in the =*Completions*= buffer, whether your completion is in +the minibuffer on in-buffer. And in all cases, =RET= now chooses the +completion you selected. + +If you want to customize how the completion candidates are displayed, +you can now use =completions-format=: set it to ='vertical=, selecting the +next candidates means selecting the one below the one currently +selected, wrapping to the net column when you reached the bottom. But +setting it to ='horizontal= will keep the old behaviour intact, +selecting the next option right of your current selection when using +=M-=. But be careful, setting =completions-format= to ='vertical= will +undo the improvements the =*Completions*= buffer received. Not an option +for my ThinkPad. + +By the way, your selection is now consistent even if the =*Completions*= +buffer updates! It’s frustrating when you started selecting something, +but for some reason, something triggered a completions update, and now +you have to move again to what you were about to select. + +*** Minibuffer Improvements +How many times have I tried to do something, only for Emacs to not do +what I wanted because the minibuffer was active but not actively +selected? Well now, =minibuffer-nonselected-mode= will warn you when you +should probably pay attention to the minibuffer, as it’s waiting for +your input. Especially useful when you /think/ it’s selected, but it’s +actually not. + +*** Mouse Improvements +When selecting text with your mouse and invoking =context-menu-mode=, +you can now select =Send to...= to send your text selection, or even the +current file, to external applications! + +*** Built-in Package Updates +**** Org Mode Updated to 9.8 +You may already have Org Mode 9.8 if you don’t use Emacs’ builtin +package, but this new version comes with some nice new features, such +as a new babel backend for C#, customizable images alignment, fixed +and better LaTeX table export, and so on. + +**** Project +No need for calling =M-x project-any-command M-x find-file= any more! +You can now call =project-root-find-file= instead. And no need for =M-x +project-any-command M-x customize-dirlocals=, you can use +=project-customize-dirlocals= instead. + +The new command =project-find-matching-buffer= can also be useful when +switching, for instance, git worktrees of the same repository, or +simply repositories with a similar structure. You can customize its +behaviour with =project-find-matching-buffer-function=. + +You can also only save a project’s files with =M-x +project-save-some-buffers= or =C-x p C-x s=, similarly to projectile’s +=projectile-save-project-buffers=. + +**** Tree-sitter +The new option =treesit-enabled-modes= will enable all known tree-sitter +modes by default when set to =t=, or only the tree-sitter based modes in +the list given to it, such as =(setopt treesit-enabled-modes +'(c-ts-mode nix-ts-mode uiua-ts-mode)=. It may change +=major-mode-remap-alist= based on =treesit-major-mode-remap-alist= if +needed. + +The user option =treesit-auto-install-grammar= is one step to replace +[[https://github.com/renzmann/treesit-auto][treesit-auto]], with =treesit-extra-load-path= being a list of directories +where grammars are installed. If you install a grammar with +=treesit-auto-install-grammar=, it will be installed in the first +directory. =treesit-language-source-alist= now supports keywords such as +=:commit=, in case the default commit selected doesn’t match what you +want (a bug you want to avoid, or which you may consider a feature). + +By the way, discoverability of things to natively do with tree-sitter +has become better! Use =treesit-cycle-sexp-thing= to explore the +navigation commands you can call. + +You can also use =treesit-language-remap-alist= to make Emacs language A +is language B, which would allow you to use B’s parser for A. +Especially useful if you know B is a superset of A, like Typescript is +a superset of JavaScript. + +Tree-sitter also now properly supports lists and comments and allows +you to act on them! + +It also now allows for better support of multiple programming +languages, such as =treesit-simple-indent-modify-rules= which unifies +across languages indentation rules, +=treesit-aggregated-simple-imenu-settings= for Imenu setup for multiple +languages, and =treesit-aggregated-outline-predicate= which indirectly +allows for =outline-minor-mode= for multiple languages. That’ll be quite +enjoyable when I’ll work on Vue files, with HTML, Typescript, and LESS +code all in the same file. Speaking of indentation, keep an eye on +=treesit-simple-indent-add-rules= and +=treesit-simple-indent-override-rules=. + +***** Language Specifics +Doxygen is now supported by =c-ts-mode= and =java-ts-mode= if enabling +=c-ts-mode-enable-doxygen= and =java-ts-mode-enable-doxygen= respectively. + +=go-ts-mode= now has unit test +support with a few new commands like =go-ts-mode-test-function-at-point= +which does exactly what you think it does, + +=php-ts-mode= had a lot of work done: it now requires =mhtml-ts-mode= +instead of =js-ts-mode=, =css-ts-mode= and =html-ts-mode= directly, and it +now benefits greatly from the multilingual improvements I talked about +earlier. + +=rust-ts-mode= now fontifies number suffixes as types (like =10_u32=) when +=rust-ts-mode-fontify-number-suffix-as-type= is non-nil. + +*** Eshell +Eshell also got some improvements: =eshell-clear= is now a better +behaved =eshell/clear= alternative, while =eshell-execute-file= went from +function to command. + +You can also set the stderr of =eshell-command= and =eshell-execute-file=. + +The syntax of Eshell also got an upgrade: the =for= command can now loop +over integer ranges, such as =1..10= (first number included, last +excluded), and you can also use =else= in =if {condition} {true-command} +else {false-command}= (=else= remains optional). You can also now chain +=else if=, as the =false-command= can be its own if/else statement. + +The history search got an improvement, with the ability to search with +regular expressions with the two new =eshell-isearch-backward-regexp= +and =eshell-isearch-forward-regexp=, or =M-r= for the backward search +while =M-s= is now freed. + +You can also set inter-session history off by setting +=eshell-history-isearch= to nil (the default value), which will limit +isearch to the Eshell’s buffer content only. If set to =t=, it will +search in the input history only, and if set to ='dwim=, it will search +in the input history only if the point is after the last prompt. + +*** A Few Additional Goodies + +=emacs-lisp-mode= now supports semantic highlight when +=elisp-fontify-semantically= is non-nil. + +A few years back, =setopt= came into Emacs as a better alternative to +=setq= for most variables declared with =defcustom=. Well, now, +=describe-variable= will tell you if a variable should be set with +=setopt=, or if other methods is alright. + +Something my ThinkPad will be thankful of, and a lot of laptops also +will be, is the new option =native-comp-async-on-battery-power=: if set +to nil, Emacs will not attempt to use the asynchronous native +compilations if your laptop is running only on its battery. The +libraries that need compilation will be a tad slower, but you won’t +have to look for a power socket as soon as with Emacs 30. Especially +nice for those in the Northern Hemisphere who want to enjoy the +upcoming summer! Or if you’re one of the weirdos like me who enjoy the +cold more than the heat. + +Something I’ll really appreciate is setting +=show-paren-not-in-comments-or-strings= to stop Emacs from highlighting +parenthesis and brackets in comments or strings. + +Sending empty strings to =emacsclient= is now possible! Until Emacs 30, +passing an empty string was the same as not passing one it at all. +Now, Emacs will understand it! + +Emacs now supports Unicode 17.0, in case you wanted to write something +with the Sidetic, Tolong Siki, Beria Erfe, or Tai Yo scripts. I was +prepared to make an emoji joke, but surprisingly, Unicode 17 did not +add any. Speaking of scripts, Emacs now support new input methods, +such =greek-polytonic= for polytonic and archaic Greek, but also quite a +few input methods for Northern Iroquoian languages, Burmese-based +languages, and Syriac languages. My inner amateur linguist approves +immensely! + +Emacs now dislikes insecure protocols: its Network Security Manager +will warn you about TLS 1.1 and DHE and RSA key exchange. ** f.el v0.21.0 released! :dev:emacs:release: :PROPERTIES: :EXPORT_FILE_NAME: f-el-v0-21-0-released