Skip to content

tuh8888/chezmoi.el

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

chezmoi.el

This package provides convenience functions for interacting with the chezmoi dotfile management system via Emacs. These are mostly equivalents to functions like find-file and save-buffer.

https://melpa.org/packages/chezmoi-badge.svg

resources/chezmoi-template-recording.gif

The recording above demonstrates editing a chezmoi template with source file on left, command log on top right, and associated target file on bottom right.

Installation

Clone this repo or use a package manager.

(use-package chezmoi)

Add keybindings to some functions. Or call using M-x <cmd>.

(global-set-key (kbd "C-c C f")  #'chezmoi-find)
(global-set-key (kbd "C-c C s")  #'chezmoi-write)

You can manually call M-x chezmoi-mode in a source file buffer to turn on/of syncronization and template rendering (see Templates). When using chezmoi-find or chezmoi-ediff, chezmoi-mode will be turned on for you in the source file’s buffer.

Usage

One of the main goals of this package is to allow users to access their files managed by chezmoi and sync changes in the source state with the target state files that are used. Opening source state files is done using chezmoi-find. This opens a buffer for the source state and adds a hook to sync it with the corresponding target state file when changes are saved. However, to prevent overwriting changes that were made to the target state file outside of the source state (such as by auto-generated content), this hook is only added when the source and target states are in sync at the time of opening.

You can overwrite the target state file manually by calling chezmoi-write from within the source state buffer. Alternatively, you can overwrite the source state file with the content from the current target state file using chezmoi-write. This can be performed for several files in a row using chezmoi-write-files.

Quickly jump to the corresponding target file or source file using chezmoi-open-other.

Functions

Some functions provided are direct equivalents to common emacs functions.

Functionchezmoi equivalentchezmoi.el
find-filechezmoi editchezmoi\vertfind
save-bufferchezmoi applychezmoi\vertwrite
diffchezmoi diffchezmoi\vertdiff
ediffchezmoi mergechezmoi\vertediff
magit-statuschezmoi git statuschezmoi\vertmagit-status

Templates

Chezmoi.el provides a minor mode for displaying the values of chezmoi template strings as overlays in source file buffers. You can toggle their display with M-x chezmoi-template-buffer-display or with a configuration variable:

(setq-default chezmoi-template-display-p t)   ;; Display template values in all source buffers.
(setq chezmoi-template-display-p t)           ;; Display template values in current buffer.
(setq-default chezmoi-template-display-p nil) ;; Don't display template values by default.

Integrations

Ediff: Comparing source and target states

Emacs has a lovely package called ediff for comparing differences between files which is perfect for when the source and target states get out of sync. Quickly resolve inconsistencies between source and target states using chezmoi-ediff. Or view the raw diff using chezmoi-diff if you prefer. Pipe this into your own diff workflow using (chezmoi-diff 1) to give raw diff input to some other diff management tool.

Company

Company integration is provided through chezmoi-company-backend. Simply add it to to company-backends. This will show completions for when editing template variables.

(require 'chezmoi-company)
(add-hook 'chezmoi-mode-hook #'(lambda () (if chezmoi-mode
                                              (add-to-list 'company-backends 'chezmoi-company-backend)
                                            (delete 'chezmoi-company-backend 'company-backends))))

Cape

Cape integration is provided through chezmoi-capf. Simply add it to to completion-at-point-functions. This will show completions for when editing template variables.

(require 'chezmoi-cape)
(add-to-list 'completion-at-point-functions #'chezmoi-capf)

Dired

In a Dired buffer, add files to chezmoi by either moving to the file or marking some and calling chezmoi-dired-add-marked-files.

Magit

Use chezmoi-magit-status to jump to the magit-status for your chezmoi.

Org

Configuration

Evil

Integrate with evil mode by toggling template display when entering insert mode.

(defun chezmoi--evil-insert-state-enter ()
  "Run after evil-insert-state-entry."
  (chezmoi-template-buffer-display nil (point))
  (remove-hook 'after-change-functions #'chezmoi-template--after-change 1))

(defun chezmoi--evil-insert-state-exit ()
  "Run after evil-insert-state-exit."
  (chezmoi-template-buffer-display nil)
  (chezmoi-template-buffer-display t)
  (add-hook 'after-change-functions #'chezmoi-template--after-change nil 1))

(defun chezmoi-evil ()
  (if chezmoi-mode
      (progn
        (add-hook 'evil-insert-state-entry-hook #'chezmoi--evil-insert-state-enter nil 1)
        (add-hook 'evil-insert-state-exit-hook #'chezmoi--evil-insert-state-exit nil 1))
    (progn
      (remove-hook 'evil-insert-state-entry-hook #'chezmoi--evil-insert-state-enter 1)
      (remove-hook 'evil-insert-state-exit-hook #'chezmoi--evil-insert-state-exit 1))))
(add-hook 'chezmoi-mode-hook #'chezmoi-evil)

Ligatures

Ligatures don’t seem to play nice with overlaid text. When using templates, it is recommended to turn off ligature-mode.

;; Turn off ligatures because they show up poorly.
(add-hook 'chezmoi-mode-hook #'(lambda () (when (require 'ligature)
                                            (ligature-mode (if chezmoi-mode 0 1)))))

Org babel tangle

I find this hook useful for my emacs config files generated through org-tangle.

(add-hook 'org-babel-post-tangle-hook #'chezmoi-write))

Spacemacs layer

Provided here is a sample layer for those who use Spacemacs. Add it by creating a Spacemacs layer called “chezmoi” and create a file in it called “packages.el” with the following code:

(defconst chezmoi-packages
  '(
    chezmoi)
  "The list of Lisp packages required by the chezmoi layer.")


(defun chezmoi/init-chezmoi ()
  (use-package chezmoi
    :init
    (spacemacs/declare-prefix "f d" "chezmoi")

    (spacemacs/set-leader-keys
      "f d s" #'chezmoi-write
      "f d g" #'chezmoi-magit-status
      "f d d" #'chezmoi-diff
      "f d e" #'chezmoi-ediff
      "f d f" #'chezmoi-find
      "f d i" #'chezmoi-write-files
      "f d o" #'chezmoi-open-other
      "f d t" #'chezmoi-template-buffer-display
      "f d c" #'chezmoi-mode)

    (when (equalp dotspacemacs-editing-style 'vim)
      (defun chezmoi--evil-insert-state-enter ()
        "Run after evil-insert-state-entry."
        (chezmoi-template-buffer-display nil (point))
        (remove-hook 'after-change-functions #'chezmoi-template--after-change 1))

      (defun chezmoi--evil-insert-state-exit ()
        "Run after evil-insert-state-exit."
        (chezmoi-template-buffer-display nil)
        (chezmoi-template-buffer-display t)
        (add-hook 'after-change-functions #'chezmoi-template--after-change nil 1))

      (defun chezmoi-evil ()
        (if chezmoi-mode
            (progn
              (add-hook 'evil-insert-state-entry-hook #'chezmoi--evil-insert-state-enter nil 1)
              (add-hook 'evil-insert-state-exit-hook #'chezmoi--evil-insert-state-exit nil 1))
          (progn
            (remove-hook 'evil-insert-state-entry-hook #'chezmoi--evil-insert-state-enter 1)
            (remove-hook 'evil-insert-state-exit-hook #'chezmoi--evil-insert-state-exit 1))))
      (add-hook 'chezmoi-mode-hook #'chezmoi-evil))


    (setq chezmoi-template-display-p t) ;; Display template values in all source buffers.

    (require 'chezmoi-company)
    (add-hook 'chezmoi-mode-hook #'(lambda () (if chezmoi-mode
                                             (add-to-list 'company-backends 'chezmoi-company-backend)
                                           (setq company-backends (delete 'chezmoi-company-backend company-backends)))))

    ;; Turn off ligatures cuz they look bad.
    (add-hook 'chezmoi-mode-hook #'(lambda () (ligature-mode (if chezmoi-mode 0 1))))

    ;; I find this hook useful for my emacs config files generated through org-tangle.
    (defun chezmoi-org-babel-tangle ()
      (when-let ((fle (chezmoi-target-file (buffer-file-name))))
        (chezmoi-write file)))
    (add-hook 'org-babel-post-tangle-hook #'chezmoi-org-babel-tangle)))

About

An emacs package for interacting with chezmoi.

Resources

License

Stars

Watchers

Forks

Packages

No packages published