outline-indent.el – Indentation based Folding and Outlining in Emacs

5/5

The outline-indent.el Emacs package provides a minor mode that enables code folding and outlining based on indentation levels for various indentation-based text files, such as YAML, Python, and other indented text files.

In addition to code folding, outline-indent.el allows moving indented sub-trees up and down, promoting and demoting sections to adjust indentation levels, customizing the ellipsis, and inserting a new line with the same indentation level as the current line, among other features.

The outline-indent.el package leverages the built-in outline-minor-mode, which is maintained by the Emacs developers and has less chance of being abandoned like origami.el.

The outline-indent.el Emacs package offers a similar functionality to Vim’s set foldmethod=indent setting. Just as in Vim, it allows to fold and unfold code sections based on their indentation levels.

Installation

To install the outline-indent using straight.el:

  1. If you haven’t already done so, add the straight.el bootstrap code to your init file.
  2. Add the following code to your Emacs init file:
(use-package outline-indent
  :ensure t
  :straight (outline-indent
             :type git
             :host github
             :repo "jamescherti/outline-indent.el")
  :custom
  (outline-indent-ellipsis " ▼ "))Code language: Lisp (lisp)

Usage

Once installed, the minor mode can be activated using:

(outline-indent-minor-mode)Code language: Lisp (lisp)

The minor mode can also be automatically activated for a certain mode. For example for Python and YAML:

(add-hook 'python-mode-hook #'outline-indent-minor-mode)
(add-hook 'python-ts-mode-hook #'outline-indent-minor-mode)

(add-hook 'yaml-mode-hook #'outline-indent-minor-mode)
(add-hook 'yaml-ts-mode-hook #'outline-indent-minor-mode)Code language: Lisp (lisp)

(You can also adjust the indentation offset by modifying the variable outline-indent-default-offset)

Once outline-indent-minor-mode is activated, you can use the built-in outline-minor-mode functions to fold or unfold indented sections:

  • outline-hide-body: Hide all body lines in buffer, leaving all headings visible.
  • outline-hide-other: Hide everything except current body and parent and top-level headings.
  • outline-hide-entry: Hide the body directly following this heading.
  • outline-hide-leaves: Hide the body after this heading and at deeper levels.
  • outline-hide-subtree: Hide everything after this heading at deeper levels.
  • outline-show-children: Show all direct subheadings of this heading.
  • outline-hide-sublevels: Hide everything but the top LEVELS levels of headers, in whole buffer.
  • outline-show-all: Show all of the text in the buffer.
  • outline-show-entry: Show the body directly following this heading.
  • outline-show-subtree: Show everything after this heading at deeper levels.
  • outline-show-branches: Show all subheadings of this heading, but not their bodies.
  • outline-show-children: Show all direct subheadings of this heading.

You can also indent/unindent and move subtree up and down:

  • (outline-indent-demote) and (outline-indent-promote): Indent or unindent the entire subtree.
  • (outline-indent-move-subtree-down) and (outline-indent-move-subtree-up) to move the current subtree up or down.
  • (outline-insert-heading) to insert a new line with the same indentation level/depth as the current line just before the next heading that shares the same or less indentation level.

In Evil mode, outline-indent-minor-mode works out of the box, and you can use the Evil keyboard mappings: zo, zc, zO, zC, za, zr, and zm to manage folds.

Related links

Emacs: Enhancing up and down subtree movement in outline-mode and outline-minor-mode

4.5/5

When editing outlined files (e.g., using the built-in outline-minor-mode, or packages like outline-indent.el, outline-yaml.el, etc.), handling subtrees efficiently can significantly enhance productivity, especially when working with complex documents. If you’re familiar with outline-mode or outline-minor-mode, you might have noticed that the built-in functions for moving subtrees up and down, outline-move-subtree-up and outline-move-subtree-down:

  • Blank line exclusion: outline-move-subtree-up and outline-move-subtree-down exclude the last blank line of the subtree when the outline-blank-line variable is set to t. Setting outline-blank-line to t is worthwhile because it retains a visible blank line after the subtree and before the next heading, improving the readability of the document.
  • Cursor position reset: After moving a subtree up or down, the cursor position is often reset, which can be disruptive during editing.

Here’s how you can address these issues by using custom functions to enhance subtree movement:

(require 'outline)

(defun my-advice-outline-hide-subtree (orig-fun &rest args)
  "Advice for `outline-hide-subtree'.
This ensures that the outline is folded correctly by
outline-move-subtree-up/down, preventing it from being unable to open the fold."
  (let ((outline-blank-line
         (if (bound-and-true-p my-outline-hide-subtree-blank-line-enabled)
             my-outline-hide-subtree-blank-line
           outline-blank-line)))
    (apply orig-fun args)))

(defun my-advice-outline-move-subtree-up-down (orig-fun &rest args)
  "Move the current subtree up/down past ARGS headlines of the same level.
This function ensures the last blank line is included, even when
`outline-blank-line' is set to t. It also restores the cursor position,
addressing the issue where the cursor might be reset after the operation."
  (interactive "p")
  (let ((column (current-column))
        (outline-blank-line nil)
        (my-outline-hide-subtree-blank-line-enabled t)
        (my-outline-hide-subtree-blank-line outline-blank-line))
    (apply orig-fun (or args 1))
    (move-to-column column)))

(advice-add 'outline-hide-subtree
            :around #'my-advice-outline-hide-subtree)
(advice-add 'outline-move-subtree-up
            :around #'my-advice-outline-move-subtree-up-down)
(advice-add 'outline-move-subtree-down
            :around #'my-advice-outline-move-subtree-up-down)Code language: Lisp (lisp)

I also recommend using Ctrl-Up and Ctrl-Down key bindings for moving subtrees up and down.

(define-key outline-mode-map (kbd "C-<up>") 'outline-move-subtree-up)
(define-key outline-mode-map (kbd "C-<down>") 'outline-move-subtree-down)

(defun my-setup-outline-minor-mode-keybindings ()
    "Set up keybindings for moving subtrees in `outline-minor-mode'."
  (define-key outline-minor-mode-map (kbd "C-<up>") 'outline-move-subtree-up)
  (define-key outline-minor-mode-map (kbd "C-<down>") 'outline-move-subtree-down))
(add-hook 'outline-minor-mode-hook 'my-setup-outline-minor-mode-keybindings) Code language: Lisp (lisp)

With this setup, you will ensure that every time you use outline-move-subtree-up or outline-move-subtree-down, the last blank line of the subtree is included and the cursor position is restored.

Introducing elispcomp: Compiling Elisp code directly from the command line

5/5

The elispcomp command line tool allows compiling Emacs Lisp (Elisp) code directly from the terminal or from a shell script. It facilitates the generation of optimized .elc (byte-compiled) and .eln (native-compiled) files, which can significantly improve the performance of Emacs.

The tool executes a headless instance of Emacs that recursively scans the specified directories, byte compiling and native compiling all the .el files that haven’t been compiled yet. It supports various configuration options, allowing you to adapt the compilation process to suit your needs.

When configured appropriately, Emacs can compile to both .elc and .eln files. However, for those who wish to automate the background compilation of .el files using a script, the elispcomp command-line tool can be beneficial in ensuring that their Emacs setup remains up-to-date without manual intervention and without starting an Emacs instance. I personally use elispcomp compile multiple Elisp files across various machines and Emacs versions.

Installation

To get started with elispcomp, you can install it using pip, Python’s package installer. Here’s how:

pip install --user elispcomp

This command installs elispcomp and places the executable in your ~/.local/bin/ directory, making it easily accessible from your command line.

Usage

The elispcomp command line tool is straightforward to use.

First example: To compile all .el files located in the ~/.emacs.d/lisp:

elispcomp ~/.emacs.d/lispCode language: plaintext (plaintext)

Second example: To compile all .el files located in the ~/.emacs.d/lisp directory, and store the native-compiled files in the ~/.emacs.d/eln-cache directory:

elispcomp --eln-cache ~/.emacs.d/.eln-cache ~/.emacs.d/lispCode language: plaintext (plaintext)

Command line options

usage: elispcomp [--option] [N]

Recursively byte and native compile .el files.

positional arguments:
  N                     The directories to be scanned recursively by Emacs to 
                        locate the '.el' files for compilation.

options:
  -h, --help            show this help message and exit
  -c ELN_CACHE, --eln-cache ELN_CACHE
                        The eln-cache directory where Emacs stores the
                        compiled native compiled code. Defaults to the
                        default Emacs eln-cache directory.
  -e EMACS_BIN, --emacs-bin EMACS_BIN
                        Path to the Emacs binary. Defaults: emacs
  -j JOBS, --jobs JOBS  Specify the number of parallel jobs for compilation.
                        Default: Half the number of available CPUs
  -b, --disable-byte-comp
                        Disable byte-compile. Default: enabled
  -n, --disable-native-comp
                        Disable native compilation. Default: enabled
  -i LOAD_PATH, --load-path LOAD_PATH
                        Recursively adds the subdirectories of the specified
                        directory to the Emacs `load-path`. This option can
                        be used multiple times to include several directories.
Code language: plaintext (plaintext)

The elispcomp command-line tool offers an alternative approach to managing Emacs Lisp code. Try it out and experience a new way to compile your Elisp codebase from the command line or from a script.

Links

Emacs Evil Mode: Disabling the automatic removal of spaces after leaving Insert mode

5/5

By default, Emacs evil-mode removes newly inserted spaces when exiting insert mode. However, some users may find this disruptive to their workflow. This is particularly true for those who edit file formats where trailing spaces are significant or who simply prefer to manage whitespace manually.

To prevent the automatic removal of trailing spaces when leaving insert mode, add the following Elisp code to the Emacs init file:

(with-eval-after-load 'evil
  (defun my-evil-disable-remove-spaces ()
    "Disable automatic removal of trailing spaces in `evil-mode'."
    (setq-local evil-maybe-remove-spaces nil))

  (add-hook 'evil-insert-state-entry-hook #'my-evil-disable-remove-spaces))Code language: Lisp (lisp)

The function above sets the evil-maybe-remove-spaces variable to nil when entering insert mode, preventing the evil-maybe-remove-spaces function from deleting whitespace after leaving insert mode.

The evil-insert-state function, which Evil uses to switch to insert mode, behaves as follows:

  • When entering insert mode: It sets the evil-maybe-remove-spaces variable to t.
  • When exiting insert mode, it calls the evil-maybe-remove-spaces function, which removes trailing spaces if the evil-maybe-remove-spaces variable is set to t. Because the my-evil-disable-remove-spaces function above sets the evil-maybe-remove-spaces variable to nil when entering insert mode, it prevents the evil-maybe-remove-spaces function from deleting whitespace after leaving insert mode.

If you want to compare the behavior before and after the function above, use whitespace-mode. This mode visually highlights different types of whitespace characters, such as spaces, tabs, and newlines, making it easier to see the differences.

Customizing evil-mode with the simple piece of Elisp code above can prevent the automatic removal of trailing spaces when exiting insert mode. This adjustment allows for better control over whitespace in files.

Emacs: Customizing the Ellipsis (…) in Outline Mode and Outline Minor Mode

5/5

The built-in Emacs outline-mode and outline-minor-mode allow structuring documents with collapsible sections. By default, these modes use an ellipsis (“…”) to indicate folded text. However, the default ellipsis and its face can make it hard to distinguish between folded text and regular text. This is why it can be beneficial to customize the ellipsis.

The code snippets provided in this article allow for customizing the ellipsis either globally or locally within a buffer.

Set the global outline ellipsis

The following function can be used to change the ellipsis in both outline-mode and outline-minor-mode to ▼:

(defun my-outline-set-global-ellipsis (ellipsis)
  "Apply the ellipsis ELLIPSIS to outline mode globally."
  (let* ((face-offset (* (face-id 'shadow) (ash 1 22)))
         (value (vconcat (mapcar (lambda (c) (+ face-offset c)) ellipsis))))
    (set-display-table-slot standard-display-table 'selective-display value)))

(my-outline-set-global-ellipsis " ▼ ")
Code language: Lisp (lisp)

The Elisp code above will change the outline-mode and outline-minor-mode ellipsis to:

(The screenshot above shows a YAML file folded using outline-indent.el or outline-yaml.el, which leverages outline-minor-mode to outline and enable code folding in YAML files.)

Set the buffer local outline ellipsis

To apply the ellipsis locally to a buffer, the following Elisp code snippet modifies the display settings within that buffer. This ensures that any changes made affect only the current buffer, leaving the global Emacs environment unaffected. This approach is particularly useful for customizing displays in specific files or testing new configurations without affecting other buffers or sessions.

Here is the Emacs Lisp code snippet to achieve this:

(defun my-outline-set-buffer-local-ellipsis (ellipsis)
  "Apply the ellipsis ELLIPSIS to outline mode locally to a buffer."
  (let* ((display-table (or buffer-display-table (make-display-table)))
         (face-offset (* (face-id 'shadow) (ash 1 22)))
         (value (vconcat (mapcar (lambda (c) (+ face-offset c)) ellipsis))))
    (set-display-table-slot display-table 'selective-display value)
    (setq buffer-display-table display-table)))Code language: Lisp (lisp)

And here is an example of applying the buffer-local ellipsis to text-mode:

(add-hook 'text-mode-hook
          #'(lambda() (my-outline-set-buffer-local-ellipsis " ▼ ")))Code language: PHP (php)

Conclusion

Customizing the ellipsis in outline-mode and outline-minor-mode is a simple yet effective way to personalize your Emacs and create a more visually appealing way to handle folds.

Emacs: YAML file code Folding and Outlining

5/5

Working with long and complex YAML files can be a daunting task. In such cases, code folding becomes an invaluable tool, allowing the collapse and expansion of sections of the file and enhancing readability and navigation. This makes it easier to focus on specific parts of the code without being overwhelmed by the entire document.

To address this need, I would like to introduce you to outline-yaml.el, a minor mode for Emacs that brings code folding and outlining capabilities to YAML files, making editing YAML files more efficient and enjoyable. Leveraging Emacs’ built-in outline-minor-mode, outline-yaml.el provides a structured and navigable view of YAML content, simplifying the editing of even the most difficult YAML files.

Installation of outline-yaml.el

  1. Install and configure yaml-mode or yaml-ts-mode.
  2. If you haven’t already done so, add the straight.el bootstrap code to your init file.
  3. After that, add the following code to your Emacs init file:
(use-package outline-yaml
  :ensure t
  :straight (outline-yaml
             :type git
             :host github
             :repo "jamescherti/outline-yaml.el")
  :hook
  ((yaml-mode . outline-yaml-minor-mode)
   (yaml-ts-mode . outline-yaml-minor-mode)))Code language: Lisp (lisp)

How to change the Ellipsis (…) to (▼)?

The code snippet in this article can be used to to change the Ellipsis to ▼.

Links

Emacs: Enabling native compilation and dynamically adjusting the number of Elisp files compiled in parallel

5/5

Emacs has experienced a significant performance boost with the introduction of native compilation, available from version 27 and above. This feature converts Emacs Lisp code into machine-level code, enabling faster execution and enhanced responsiveness.

Speeding up compilation by using the maximum number of available CPU cores significantly reduces compilation time. However, it’s also necessary to leave a few CPU cores free to ensure the operating system runs smoothly, including the graphical user interface, shells, and other processes. The source code snippet outlined in this article is designed to effectively manage resources by allocating CPU cores for native compilation while reserving some for system operations.

Configuring native compilation and adjusting the number of parallel compilations

To configure native compilation and dynamically adjust the number of parallel compilations, add the following code snippet to early-init.el or init.el:

;; Description: Enable native compilation and dynamically adjust
;; the number of Elisp files compiled in parallel.
;;
;; Compatible with: Emacs >= 28.1 (because `num-processors' is required)
;;
;; URL: https://www.jamescherti.com/emacs-native-compilation-config-jobs/
;; License: MIT
;; Author: James Cherti

(defvar my-native-comp-reserved-cpus 2
  "Number of CPUs to reserve and not use for `native-compile'.")

(defun my-calculate-native-comp-async-jobs ()
  "Set `native-comp-async-jobs-number' based on the available CPUs."
  ;; The `num-processors' function is only available in Emacs >= 28.1
  (max 1 (- (num-processors) my-native-comp-reserved-cpus)))

(if (and (featurep 'native-compile)
         (fboundp 'native-comp-available-p)
         (native-comp-available-p))
    ;; Activate `native-compile'
    (setq native-comp-async-jobs-number (my-calculate-native-comp-async-jobs)
          native-comp-deferred-compilation t
          package-native-compile t)
  ;; Deactivate the `native-compile' feature if it is not available
  (setq features (delq 'native-compile features)))Code language: Lisp (lisp)

What does the source code snippet above do?

  • Reserves CPUs: Sets aside 2 CPUs to not be used by the native compilation feature in Emacs.
  • Calculates Available CPUs for Compilation: Determines how many CPUs can be used for compiling Emacs Lisp files by subtracting the reserved CPUs from the total count.
  • Sets Native Compilation Parameters: Configures Emacs to use the calculated number of CPUs for parallel compilation tasks.
  • Ensures Feature Availability: Activates native compilation settings only if the feature is supported and available, otherwise deactivates it.
  • Optimizes Performance: Aims to enhance Emacs performance by efficiently using system resources without overloading the system.

How to check if native compilation is available?

To check whether native compilation is supported, you can run the following Emacs Lisp code:

(message (if (and (fboundp 'native-comp-available-p)
                  (native-comp-available-p))
             "Native compilation is available"
           "Native compilation is *not* available"))
Code language: Lisp (lisp)

Conclusion

Managing system resources efficiently is key to maintaining optimal performance in Emacs, especially when using the native compilation feature. The source code snippet outlined in this article provides a dynamic method for adjusting the number of native compilation jobs according to the number of available CPUs. This enhances the responsiveness and efficiency of Emacs without overloading the system.

Emacs Theme: Tomorrow Night Deepblue, a beautiful theme with a deep blue background

5/5

The Emacs theme jamescherti/tomorrow-night-deepblue-theme.el is a beautiful deep blue variant of the Tomorrow Night colorscheme, which is renowned for its elegant color palette. It is pleasing to the eyes and is easy to read.

The Tomorrow Night Deepblue Emacs theme features a deep blue background color that creates a calming atmosphere. The contrasting colors make it easy to distinguish between different elements of your code. The theme is also a great choice for programmer who miss the blue themes that were trendy a few years ago.

The theme was inspired by classic DOS text editors such as QuickBASIC, RHIDE, and Turbo Pascal, which featured blue backgrounds by default. There’s something special about the early days of programming and the tools we used that brings back fond memories.

Installation

MELPA

To install the tomorrow-night-deepblue-theme.el from MELPA, you need to add the following code to the Emacs init file:

(use-package tomorrow-night-deepblue-theme
  :ensure t
  :config
  ;; Disable all themes and load the Tomorrow Night Deep Blue theme
  (mapc #'disable-theme custom-enabled-themes)
  (load-theme 'tomorrow-night-deepblue t))
Code language: Lisp (lisp)

What are the differences between Tomorrow Night Blue and Deepblue?

The main differences lie in the large number of additional faces and the background color, which enable support for many more modern Emacs packages. Currently, Tomorrow Night Deepblue supports over 1170 faces (compared to 333 in the original version), with a background color reminiscent of traditional editors. The author plans to make further changes to support even more faces. Contributions are welcome!

This is the background color of the Tomorrow Night Deepblue, the theme featured in this article:

This background color or the Tomorrow Night Blue, the previous version upon which this theme is based:

Conclusion

In summary, the Tomorrow Night Deepblue Emacs theme offers a calming deep blue background that helps you focus. Its clear colors make it easy to see different parts of your code. It’s a great choice for programmers who miss the popular blue themes from a few years ago.

Related links

Making the Emacs built-in tab-bar Look Like Vim’s Tab Bar

4.5/5

The vim-tab-bar.el Emacs package modifies the appearance of the Emacs tab-bar to resemble Vim’s tabbed browsing interface. It also ensures that the tab-bar’s appearance remains consistent with the overall color scheme of the current theme.

The Emacs built-in tab-bar feature, which enables users to manage multiple buffers through a visual interface at the top of the Emacs window, is available in Emacs version 27 or higher.

Installation

MELPA

The vim-tab-bar.el package can be installed from MELPA by adding the following lines to your Emacs init file:

(use-package vim-tab-bar
  :ensure t
  :config
  (vim-tab-bar-mode 1))Code language: CSS (css)

Screenshots

Here are a few more screenshots showing how the jamescherti/vim-tab-bar.el package adapts Emacs tab-bar colors to any loaded theme:

The above theme is the Tomorrow Night Deepblue Emacs theme

How do Vim tabs look like?

For those who have never used Vim and are curious about the appearance of Vim tabs, here is a screenshot:

Emacs Evil Mode: How to restore both the line and column number of a mark, not just the line number

Rate this post

In Emacs with Evil mode, similar to Vim, a mark represents a position in the buffer that you can set and later return to, facilitating quick navigation between different locations within a file.

Set and restore a mark

You can set a mark by pressing the m button followed by a letter. For example, pressing ma sets a mark at the current cursor position and associates it with the letter a. To restore a mark, press either the backtick (`) or the single quote (') followed by the associated letter. For instance, pressing 'a restores the cursor to the line of the mark, while pressing `a moves the cursor to the exact line and column of the mark.

How to use a single quote instead of a backtick to restore both the line and column numbers of a mark

If you prefer using the single quote (') to restore both the line and column number of a mark, I’ve made a small change to accommodate this preference. The following Elisp code ensures that the single quote (') restores both the line and column, while the backtick (`) restores only the line:

(define-key evil-motion-state-map "`" 'evil-goto-mark-line)
(define-key evil-motion-state-map "'" 'evil-goto-mark)Code language: Lisp (lisp)

Emacs: Striking through Org Mode DONE tasks

Rate this post

It’s always satisfying to cross something off a to-do list, almost like declaring to yourself, ‘I did it!’ That’s the feeling I wanted to bring into Emacs Org Mode.

The following Emacs Lisp (Elisp) code instructs Emacs to apply a strike-through to any task marked as DONE:

;; Enable the fontification of headlines for tasks that have been marked as
;; completed.
(setq org-fontify-done-headline t)

(custom-set-faces
 ;; Face used for todo keywords that indicate DONE items.
 '(org-done ((t (:strike-through t))))

 ;; Face used to indicate that a headline is DONE. This face is only used if
 ;; ‘org-fontify-done-headline’ is set. If applies to the part of the headline
 ;; after the DONE keyword.
 '(org-headline-done ((t (:strike-through t)))))
Code language: Lisp (lisp)

By adding strike-through for completed items, Emacs Org Mode becomes clearer and more satisfying to use.

Emacs: Functions to evaluate Elisp Code, then display the result or copy it to the clipboard

Rate this post

The Elisp code below introduces three functions designed to evaluate Emacs Lisp code, either under the cursor or within a selected text region. These functions can return the evaluation result, copy it to the clipboard, or display it in the minibuffer. The functions allow obtaining immediate feedback from the code evaluation.

;; License: MIT
;; Author: James Cherti
;; URL: https://www.jamescherti.com/emacs-evaluate-elisp-display-result-copy-clipboard/
;;
;; Description: The following source code snippet introduces three functions
;; designed to evaluate Emacs Lisp code, either under the cursor or within a
;; selected text region. These functions can return the evaluation result, copy
;; it to the clipboard, or display it in the minibuffer. The functions are
;; especially useful for obtaining immediate feedback from the code evaluation.

(defun my-eval-and-get-result ()
  "Evaluate Elisp code under cursor or in the active region, then return the
result. If there is a syntax error or any other error during evaluation, an
error message is displayed."
  (interactive)
  (let* ((elisp-code (if (use-region-p)
                         (buffer-substring-no-properties (region-beginning)
                                                         (region-end))
                       (buffer-substring-no-properties (line-beginning-position)
                                                       (line-end-position)))))
    (condition-case err
        (let ((result (format "%S" (eval (read elisp-code)))))
          result)
      (error (message "Error: %s" (error-message-string err)))
      nil)))

(defun my-eval-and-copy-result-to-clipboard (&optional display-result)
  "Evaluate Elisp code under cursor or in the active region, copy the result to
the clipboard. With a prefix argument, also display the result using message."
  (interactive)
  (let ((result (my-eval-and-get-result)))
    (when result
      (kill-new result)
      (when display-result
        (message "%s" result)))))

(defun my-eval-and-copy-clipboard-and-print-result ()
  "Evaluate Elisp code under cursor or in the active region, copy the result to
  the clipboard, and display the result."
  (interactive)
  (my-eval-and-copy-result-to-clipboard t))

(defun my-eval-and-print ()
  "Evaluate Elisp code under cursor or in the active region, display the
result."
  (interactive)
  (let ((result (my-eval-and-get-result)))
    (when result
      (message "%s" result))))
Code language: Lisp (lisp)

Configure Emacs org-mode to automatically add the TODO keyword to new Org Mode headings

5/5

The built-in method used by Emacs Org mode to insert new headings does not automatically prepend the inserted heading with TODO, except when C-S-<return> is pressed. I prefer using C-<return> for all headings, whether they are to-do tasks or not, to maintain my workflow efficiency. This motivated me to write the function outlined in this article.

The function below can be triggered by pressing C-<return> to insert a new Org heading. If activated while on a TODO task, it will prefix the inserted heading with TODO, effectively creating a new to-do item. Additionally, for users of evil-mode, the function transitions into insert mode.

;; Function: (my-org-insert-heading-respect-content-and-prepend-todo)
;; Author: James Cherti
;; License: MIT
;; Key binding: Ctrl-Enter
;; URL: https://www.jamescherti.com/emacs-add-todo-keyword-to-new-org-mode-headings/
;;
;; Description: The function inserts a new heading at the current cursor
;; position, and prepends it with "TODO " if activated while on a "TODO" task,
;; thus creating a new to-do item. In addition to that, for those utilizing
;; evil-mode the function transitions the user into insert mode right after the
;; "TODO " insertion.

(defun my-org-insert-heading-respect-content-and-prepend-todo ()
    "Insert a new org-mode heading respecting content and prepend it with 'TODO'.
  Additionally, ensure entry into insert state when evil-mode is active."
    (interactive)
    (let ((entry-is-todo (org-entry-is-todo-p)))
      (when (bound-and-true-p evil-mode)
        (evil-insert-state))
      (org-insert-heading-respect-content)
      (when entry-is-todo
        (just-one-space)
        (insert "TODO")
        (just-one-space))))

;; Replace the key bindings for inserting headings in Org mode
(define-key org-mode-map (kbd "C-<return>")
            'my-org-insert-heading-respect-content-and-prepend-todo)
Code language: Lisp (lisp)

Emacs: Open a Vertico/Consult or Ivy/Counsel candidate in a new tab

Rate this post

In this article, you will find code snippets designed to simplify the task of opening Vertico/Consult/Embark or Ivy/Counsel candidates in a new Emacs tab using tab-bar.

The generic function that opens candidates in a new tab

This function below, tab-new-func-buffer-from-other-window, is designed to open the buffer generated by a specified function (func) in the other window and subsequently create a new tab. It also ensures that the state of the original window and tab is preserved.

;; License: MIT
;; Author: James Cherti
;; URL: https://www.jamescherti.com/emacs-open-vertico-consult-ivy-counsel-candidate-new-tab/

(defun tab-new-func-buffer-from-other-window (func)
  "Open the buffer created by the FUNC function in the other window in a new tab."
  (let* ((original-tab-index (1+ (tab-bar--current-tab-index)))
         (original-window (selected-window)))
    ;; Save the state of the other window
    (other-window 1)
    (let* ((other-window (selected-window))
           (other-window-buf (current-buffer))
           (other-window-point (point))
           (other-window-view (window-start)))
      ;; Move back to the original window
      (other-window -1)

      ;; Call the specified function (e.g., embark-dwim, ivy-call...)
      (funcall func)

      ;; Switch back to the other window
      (other-window 1)
      (unless (eq (selected-window) original-window)
        (let* ((preview-buf (current-buffer)))
          ;; Create a new tab and switch to the preview buffer
          (tab-bar-new-tab)
          (switch-to-buffer preview-buf)

          ;; Go back to the original tab
          (tab-bar-select-tab original-tab-index)

          ;; Restore the state of the other window
          (select-window other-window)
          (switch-to-buffer other-window-buf)
          (goto-char other-window-point)
          (set-window-start nil other-window-view)

          ;; Switch to the original window
          (select-window original-window))))))Code language: Lisp (lisp)

Option 1: Open Vertico, Consult, and Embark candidate in a new tab (embark-dwim)

For users of Vertico/Consult/Embark, the following function utilizes the generic function to open the default Embark action buffer in a new tab:

(defun tab-new-embark-dwim ()
  "Open embark-dwim in a new tab."
  (interactive)
  (tab-new-func-buffer-from-other-window #'embark-dwim))Code language: Lisp (lisp)

You can add the following key mapping to Vertico:

(keymap-set vertico-map "C-t" #'tab-new-embark-dwim)Code language: Lisp (lisp)

For Emacs Evil users, you can also add the following mappings:

(evil-define-key '(insert normal) vertico-map (kbd "C-t") 'tab-new-embark-dwim)
Code language: Lisp (lisp)

Option 2: Open Ivy, Counsel candidates in a new tab (ivy-call)

For users of Counsel/Ivy, the following function utilizes the generic function above to open the buffer created by ivy-call in a new tab:

(defun tab-new-ivy-call ()
  "Open ivy-call in a new tab."
  (interactive)
  (tab-new-func-buffer-from-other-window #'ivy-call))Code language: Lisp (lisp)

You can add the following key mapping to ivy-minibuffer-map:

(keymap-set ivy-minibuffer-map "C-t" #'tab-new-ivy-call)Code language: Lisp (lisp)

For Emacs Evil users, you can also add the following mappings:

(evil-define-key '(insert normal) ivy-minibuffer-map (kbd "C-t") 'tab-new-ivy-call)Code language: Lisp (lisp)

Preventing Emacs from entering the debugger when a specific error occurs

Rate this post

Emacs provides a built-in feature called debug-on-error, which can be activated with (setq debug-on-error t). The feature determines whether Emacs should enter the debugger when an error occurs. By default, Emacs enters the debugger for all errors, which can be helpful for diagnosing issues. However, there are cases where one may want to ignore specific errors that are not critical to their workflow.

Ignoring specific errors when (setq debug-on-error t) is activated

Open the Emacs configuration file, typically located at ~/.emacs or ~/.emacs.d/init.el. Then use the debug-ignored-errors variable to make Emacs ignore a specific error:

(add-to-list 'debug-ignored-errors 'specific-error-symbol)Code language: plaintext (plaintext)

Replace 'specific-error-symbol with the actual error that the specific function might raise.

Example

Suppose you encounter the search-failed error in Emacs (Evil package) when searching for a non-existent pattern:

Debugger entered--Lisp error: (search-failed "my-pattern")
  signal(search-failed ("my-pattern"))
  evil-ex-start-search(forward nil)
  evil-ex-search-forward(nil)
  funcall-interactively(evil-ex-search-forward nil)
  command-execute(evil-ex-search-forward)Code language: plaintext (plaintext)

To make Emacs ignore the search-failed error above, the following can be used:

(add-to-list 'debug-ignored-errors 'search-failed)Code language: plaintext (plaintext)