About James Cherti

James Cherti is an experienced Infrastructure and Software engineer. He has written high-quality Python, Bash, C/C++, PHP, JavaScript source codes, administered Linux servers, and delivered several presentations in universities. He is also an active Open Source contributor.

Emacs: YAML file code Folding and Outlining

Recommendation: I recommend you to try a similar package from the same author: outline-indent.el, which provides a minor mode for Emacs that enables code folding and outlining based on indentation levels for various indent-based text files such as YAML, Python, and others. In addition to code folding, it allows moving indented subtrees up/down, customizing the ellipsis, and inserting a heading that creates a new line with the same indentation level/depth as the current line, among other features.

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

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.

Ansible: Installing and configuring Gitolite using Ansible for secure Git repository management

Gitolite provides a way to manage Git repositories, control access to those repositories, and maintain a central configuration using simple configuration files and SSH keys.

Automating Gitolite Installation with Ansible

The Ansible tasks outlined in this article are designed to simplify the installation and configuration of Gitolite on your server. These tasks can automatically handle the entire setup process, including prerequisites like installing necessary packages and configuring system users and groups.

This automation significantly reduces the risk of human error and ensures a consistent setup across different environments.

The Ansible tasks:

---
# Automating Gitolite Installation with Ansible
# License: MIT
# Author: James Cherti
# URL: https://www.jamescherti.com/ansible-install-gitolite-linux/

- name: Install Gitolite
  block:
    - name: Check if the Operating System is supported
      fail:
        msg: "Operating System family is not supported: {{ ansible_os_family }}"
      when: ansible_os_family not in ["Debian", "RedHat"]

    - name: Install Gitolite on Debian-based Systems
      apt:
        name: gitolite3
      when: ansible_os_family == "Debian"

    - name: Install Gitolite on RedHat-based Systems
      yum: name=gitolite3
      when: ansible_os_family == "RedHat"

    - name: Create Gitolite system group
      group:
        name: "{{ gitolite_group }}"
        system: true

    - name: Create Gitolite system user
      user:
        name: "{{ gitolite_user }}"
        group: "{{ gitolite_group }}"
        home: "{{ gitolite_home }}"
        shell: "{{ gitolite_shell }}"
        create_home: true
        system: true

    - name: Ensure Gitolite home directory exists with proper permissions
      file:
        state: directory
        path: "{{ gitolite_home }}"
        owner: "{{ gitolite_user }}"
        group: "{{ gitolite_group }}"
        mode: 0700

- name: Configure Gitolite SSH key
  block:
    - name: Generate Gitolite SSH key pair if it does not exist
      become: true
      become_user: "{{ gitolite_user }}"
      command: ssh-keygen -t rsa -b 4096 -f {{ gitolite_ssh_key_path | quote }} -N ""
      args:
        creates: "{{ gitolite_ssh_key_path }}"

    - name: Set permissions for the Gitolite .ssh directory
      file:
        path: "{{ gitolite_ssh_directory }}"
        owner: "{{ gitolite_user }}"
        group: "{{ gitolite_user }}"
        mode: 0700

    - name: Set permissions for the SSH public key
      file:
        path: "{{ gitolite_ssh_key_path }}.pub"
        owner: "{{ gitolite_user }}"
        group: "{{ gitolite_user }}"
        mode: 0644

    - name: Set permissions for the SSH private key
      file:
        path: "{{ gitolite_ssh_key_path }}"
        owner: "{{ gitolite_user }}"
        group: "{{ gitolite_user }}"
        mode: 0600

- name: Setup Gitolite
  block:
    - name: Initialize Gitolite with the admin public key
      become: true
      become_user: "{{ gitolite_user }}"
      command:
        argv:
          - "gitolite"
          - "setup"
          - "-pk"
          - "{{ gitolite_ssh_public_key_path }}"
      args:
        creates: /var/lib/gitolite/repositories/gitolite-admin.gitCode language: YAML (yaml)

The required Ansible variables:

---
# Automating Gitolite Installation with Ansible
# License: MIT
# Author: James Cherti
# URL: https://www.jamescherti.com/ansible-install-gitolite-linux/

gitolite_user: gitolite
gitolite_group: gitolite
gitolite_shell: /bin/bash
gitolite_home: "/var/lib/{{ gitolite_user }}"
gitolite_ssh_directory: "{{ gitolite_home }}/.ssh"
gitolite_ssh_key_path: "{{ gitolite_ssh_directory }}/id_rsa"
gitolite_ssh_public_key_path: "{{ gitolite_ssh_directory }}/id_rsa.pub"Code language: YAML (yaml)

Related links

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

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

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:

Ansible: Reintegrating /etc/rc.local in Linux systems that use Systemd as their init system

For years, /etc/rc.local has been a staple in Linux administration, providing a straightforward means to execute scripts or commands automatically upon system startup. However, with the transition to newer init systems like systemd, the /etc/rc.local script is no longer executed at boot time.

Ansible tasks that restore the /etc/rc.local script

The following Ansible tasks will create and configure /etc/rc.local and also ensure its execution by Systemd at boot time.

---
# Description: Reintegrate /etc/rc.local in Linux systems that use Systemd 
#              as their init system.
# Author: James Cherti
# License: MIT
# URL: https://www.jamescherti.com/ansible-config-etc-rc-local-linux-systemd/

- name: Check if /etc/rc.local exists
  stat:
    path: "/etc/rc.local"
  register: etc_rc_local_file

- name: Create the file /etc/rc.local should it not already exist
  copy:
    dest: /etc/rc.local
    owner: root
    group: root
    mode: 0750
    content: |
      #!/usr/bin/env bash
  when: not etc_rc_local_file.stat.exists

- name: Create the systemd service rc-local.service
  register: rc_local
  copy:
    dest: /etc/systemd/system/rc-local.service
    owner: root
    group: root
    mode: 0644
    content: |
      [Unit]
      Description=/etc/rc.local compatibility

      [Service]
      Type=oneshot
      ExecStart=/etc/rc.local
      TimeoutSec=0
      RemainAfterExit=yes
      SysVStartPriority=99

      [Install]
      WantedBy=multi-user.target

- name: Reload systemd daemon
  systemd:
    daemon_reload: yes
  when: rc_local.changed|bool

- name: Enable rc-local.service
  systemd:
    name: rc-local
    enabled: true
Code language: YAML (yaml)

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

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

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.

Emulating Cherry MX Blue Mechanical Keyboard Sounds on Linux

For people nostalgic for the era of tactile and audible feedback from typing on a mechanical keyboard, Cherrybuckle allow simulating the sounds of a mechanical keyboard with Cherry MX Blue key switches.

Cherrybuckle operates as a background process within a computer system, capturing and emitting a sound for each key pressed and released. It is a fork of the Bucklespring project that adds Cherry MX sounds to the default Bucklespring keyboard sounds.

Installing dependencies

The dependencies can be installed on a Debian or Ubuntu system using the following commands:

sudo apt-get install build-essential git
sudo apt-get install libalure-dev libx11-dev libxtst-dev pkg-configCode language: plaintext (plaintext)

Compiling and running Cherrybuckle on Debian/Ubuntu

Retrieve the project source code for the Git repository:

git clone https://github.com/jamescherti/cherrybuckleCode language: plaintext (plaintext)

Change the current working directory to “cherrybuckle”:

cd cherrybuckleCode language: plaintext (plaintext)

Compile the source code into an executable program:

makeCode language: plaintext (plaintext)

Finally, execute Cherrybuckle:

./cherrybuckleCode language: plaintext (plaintext)

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

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

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)

Creating and Restoring a Gzip Compressed Disk Image with dd on UNIX/Linux

Creating and restoring disk images are essential tasks for developers, system administrators, and users who want to safeguard their data or replicate systems efficiently. One useful tool for this purpose is dd, which allows for low-level copying of data. In this article, we will explore how to clone and restore a partition from a compressed disk image in a UNIX/Linux operating system.

IMPORTANT: There is a risk of data loss if a mistake is made. The dd command can be dangerous if not used carefully. Specifying the wrong input or output device can result in data loss. Users should exercise caution and double-check their commands before executing them.

Cloning a Partition into a Compressed Disk Image

To clone a partition into a compressed disk image, you can use the dd and gzip commands:

dd if=/dev/SOURCE conv=sync bs=64K | gzip --stdout > /path/to/file.gzCode language: plaintext (plaintext)

This command copies the content of the block device /dev/SOURCE to the compressed file /path/to/file.gz, 64 kilobytes at a time.

Restoring a Partition from a Compressed Disk Image

To restore a partition from a file containing a compressed disk image, use the following command:

gunzip --stdout /path/to/file.gz | dd of=/dev/DESTINATION conv=sync bs=64K
Code language: plaintext (plaintext)

This command decompresses the content of the compressed file located at /path/to/file.gz and copies it to the block device /dev/DESTINATION, 64 kilobytes at a time.

More information about the dd command options

Here are additional details about the dd command options:

  • The status=progress option makes dd display transfer statistics progressively.
  • The conv=noerror option instructs dd to persist despite encountering errors. However, ignoring errors might result in data corruption in the copied image. The image could be incomplete or corrupted, especially if errors occur in critical parts of the data. This option can be added to the conv option as follows: conv=sync,noerror
  • The conv=sync option makes dd wait for both the data and the metadata to be physically written to the storage media before proceeding to the next operation. In situations where data integrity is less critical, using conv=sync can help restore as much data as possible, even from a source with occasional errors.
  • Finally, the bs=64K option instructs dd to read or write up to the specified bytes at a time (in this case, 64 kilobytes). The default value is 512 bytes, which is relatively small. It is advisable to consider using 64K or even the larger 128K. However, it’s important to note that while a larger block size speeds up the transfer, a smaller block size enhances transfer reliability.

Ensuring Data Integrity

Although the dd command automatically verifies that the input and output block sizes match during each block copy operation, it is prudent to further confirm the integrity of the copied data after completing the dd operation.

To achieve this, follow these steps:

Generate the md5sum of the source block device:

dd if=/dev/SOURCE | md5sumCode language: plaintext (plaintext)

Next, generate the md5sum of the gzip-compressed file:

gunzip --stdout /path/to/file.gz | md5sumCode language: plaintext (plaintext)

Ensure that the two md5sum fingerprints are equal. This additional verification step adds an extra layer of assurance regarding the accuracy and integrity of the copied data.

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

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

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)

Installing Debian from another Linux Distribution such as Gentoo or Arch Linux

There are various scenarios in which one might need to install a Debian-based system (e.g., Debian, Ubuntu, etc.) from another distribution (e.g., Arch Linux, Gentoo, etc.). One common reason is when a user wants to set up a Debian-based system alongside an existing distribution. This could be for the purpose of testing software compatibility, development, or simply to have a dual-boot.

A Debian-based distribution can be installed from any other distribution (e.g. Arch Linux, Gentoo…) using debootstrap. The debootstrap command-line tool allows installing a Debian or Ubuntu base system within a subdirectory of an existing, installed system. Unlike traditional installation methods using a CD or a USB Key, debootstrap only requires access to a Debian repository.

Step 1: Create a new LVM partition, format it, and mount it

# Create the root LVM partition
lvcreate  -L 20G -n debian_root VOL_NAME

# Format the partition
mkfs.ext4 /dev/VOL_NAME/debian_root

# Mount the partition
mkdir /mnt/debian_root
mount /dev/VOL_NAME/debian_root /mnt/debian_rootCode language: plaintext (plaintext)

Step 2: Install the debootstrap command-line tool

On Arch Linux, debootstrap can be installed using:

sudo pacman -Sy debian-archive-keyring debootstrapCode language: plaintext (plaintext)

On Gentoo, it can be installed using:

sudo emerge -a dev-util/debootstrapCode language: plaintext (plaintext)

Step 3: Install the Debian base system

Use the debootstrap command to install Debian into the target directory:

debootstrap  --arch=amd64 stable /mnt/debian_root http://deb.debian.org/debianCode language: plaintext (plaintext)

You can replace stable with another Debian release like testing or unstable if desired. You can also add the flag --force-check-gpg to force checking Release file signatures.

In the above example, it will install the Debian-based system from the repository http://deb.debian.org/debian into the local directory /mnt/debian_root.

Step 4: Chroot into the Debian system

Since you are installing a Debian-based system inside another distribution (Arch Linux, Gentoo, etc.), you’ll need to ensure that the directory where the Debian system is mounted is ready. You can achieve this by mounting certain directories and chrooting into the Debian system:

sudo mount --bind /dev /mnt/debian_root/dev
sudo mount --bind /proc /mnt/debian_root/proc
sudo mount --bind /sys /mnt/debian_root/sys
sudo mount --bind /boot /mnt/debian_root/boot
sudo cp /etc/resolv.conf /mnt/debian_root/etc/resolv.conf
sudo cp /etc/fstab /mnt/debian_root/etc/fstab
sudo chroot /mnt/debian_root /bin/bash -lCode language: plaintext (plaintext)

The chroot command will open a new shell in the Debian environment.

Step 5: Configure the Debian-based system

Now that you’re inside the Debian-based system, you can configure it as desired. You can install packages, modify configurations, set up users, etc.

Here is an example:

apt-get update

# Install the Linux Kernel
apt-get install linux-image-amd64 firmware-linux-free firmware-misc-nonfree 

# Install cryptsetup if you are using a LUKS encrypted partition
apt-get install cryptsetup cryptsetup-initramfs

# Install misc packages
apt-get install console-setup vim lvm2 sudo

# Reconfigure locales
dpkg-reconfigure locales

# Configure the host name and the time zone
echo yourhostname > /etc/hostname
ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime
Code language: plaintext (plaintext)

Do not forget to:

  • Modify /mnt/debian_root/etc/fstab (The mount point “/” has to point to the Debian system)
  • Modify /mnt/debian_root/etc/crypttab (If you are using a LUKS encrypted partition)
  • Configure the bootloader (Grub, Syslinux, etc.).

Congratulations! You have successfully installed a Debian-based system using debootstrap from another distribution such as Arch Linux, Gentoo, etc.