Skip to content

Expose initial evil state as defcustom#161

Merged
dakra merged 1 commit intodakra:mainfrom
Cianidos:evil-ghostel-initial-state-defcustom
Apr 21, 2026
Merged

Expose initial evil state as defcustom#161
dakra merged 1 commit intodakra:mainfrom
Cianidos:evil-ghostel-initial-state-defcustom

Conversation

@Cianidos
Copy link
Copy Markdown
Contributor

Problem

evil-ghostel-mode hard-codes (evil-set-initial-state 'ghostel-mode 'insert) inside its activation body (evil-ghostel.el:337). Wired to ghostel-mode-hook per the README:

(use-package evil-ghostel
  :hook (ghostel-mode . evil-ghostel-mode))

the call fires on every ghostel buffer creation, running before evil-initialize reads the initial state via after-change-major-mode-hook. User overrides (Customize, setq, direct evil-set-initial-state) survive until the next new ghostel buffer opens, then get clobbered.

Change

  • Add evil-ghostel-default-state defcustom. :set re-runs evil-set-initial-state so Customize / setopt take effect immediately. Direct calls to evil-set-initial-state also keep working — the registry is last-writer-wins.
  • Apply the current value once at load — covers (setq ... ) before require, where defcustom preserves the value without calling :set.
  • Drop the hard-coded call from the activation body.

Default stays 'insert; no behaviour change for existing users.

Tests

Three new ERT cases in test/evil-ghostel-test.el:

  • default-state-load-applied — value is registered at load.
  • default-state-custom-set-updates-registry — Customize propagates.
  • mode-activation-preserves-initial-state — regression guard: activation no longer clobbers the registry.

@Cianidos
Copy link
Copy Markdown
Contributor Author

Context on why this matters to me, in case it's useful for the design discussion:

I prefer defaulting new ghostel buffers to 'emacs because ESC then passes through to the terminal untouched — which is essential for TUI apps (htop, btop, fzf pickers, vim over ssh, etc.).

evil-ghostel seems designed around a normal ↔ insert flow: insert to interact with the TUI, normal to navigate the buffer. In practice I find normal ↔ emacs (toggled via C-z) smoother for the same flow — emacs-state behaves like a vanilla terminal, normal-state gives me the evil goodies (scrollback, search, yank).

Possible I'm using the package against its intended grain; happy to hear if there's a more canonical way. Either way, the defcustom lets both workflows coexist without config-side advice tricks.

`evil-ghostel-mode' hard-coded `(evil-set-initial-state 'ghostel-mode
'insert)' inside its activation body.  Since the minor mode is wired
to `ghostel-mode-hook', that call fires on every ghostel buffer
creation — and runs before `evil-initialize' reads the initial state
via `after-change-major-mode-hook'.  Any user override (customize,
setq, or direct `evil-set-initial-state' call) was silently clobbered
on the next ghostel buffer.

Replace the hard-coded call with `evil-ghostel-initial-state', a
defcustom whose `:set' re-runs `evil-set-initial-state'.  Apply the
current value once at package load to cover the `setq-before-require'
path where `defcustom' preserves the value without invoking `:set'.
The evil registry is last-writer-wins, so users who prefer the raw
API can still call `evil-set-initial-state' directly from `:config'
without knowing about the option.

Default remains `insert' to preserve existing behaviour.

Add tests covering: load-time registration, customize-set updates,
and activation not clobbering the initial-state setting (regression
guard).
@dakra dakra force-pushed the evil-ghostel-initial-state-defcustom branch from d64e400 to 5fcbb19 Compare April 21, 2026 07:04
@dakra
Copy link
Copy Markdown
Owner

dakra commented Apr 21, 2026

Thanks again ❤️

evil-ghostel seems designed around a normal ↔ insert flow: insert to interact with the TUI, normal to navigate the buffer. In practice I find normal ↔ emacs (toggled via C-z) smoother for the same flow — emacs-state behaves like a vanilla terminal, normal-state gives me the evil goodies (scrollback, search, yank).

Possible I'm using the package against its intended grain; happy to hear if there's a more canonical way. Either way, the defcustom lets both workflows coexist without config-side advice tricks.

Personally I'm not a evil user. I just added this package because a few users requested it and it's very popular.
So if something is not evil-idiomatic etc, you can just say or create a PR to fix it.

@dakra dakra merged commit 5fcbb19 into dakra:main Apr 21, 2026
19 of 20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants