;; -*- lexical-binding: t; -*- (defvar kj/history-command "fc -R $HISTFILE && fc -l 1" "History command used to get shell history.") (defvar kj/history-regexp (rx bol (* " ") ;; Index (* digit) (* " ") ;; Command (group (1+ (not "\n"))))) (use-package emacs :elpaca nil :after consult :config (defun kj/get-shell-history () (with-temp-buffer (unless (process-file "zsh" nil (current-buffer) nil "-c" kj/history-command) (error "Getting history failed: %s" (buffer-string))) (goto-char (point-min)) (let ((result)) (save-match-data (while (re-search-forward kj/history-regexp nil t) (let ((command ;; Fix up multi-line commands. (string-replace "\\\\n" "\\\n" (match-string-no-properties 1)))) (push command result)))) result))) (defun kj/consult-history () (interactive) (if (not (or (and (minibufferp) (eq minibuffer-history-variable 'shell-command-history)) (derived-mode-p 'term-mode 'shell-mode) )) (call-interactively 'consult-history) (pcase-let* ((bol (cond ((derived-mode-p 'eshell-mode) 'eshell-bol) ((derived-mode-p 'term-mode) 'term-bol) ((derived-mode-p 'comint-mode) 'comint-bol))) (`(,beg . ,end) (cond ((minibufferp) (cons (minibuffer-prompt-end) (point-max))) (bol (save-excursion (funcall bol) (cons (point) (pos-eol)))) (t (cons (point) (point))))) (str (consult--read (kj/get-shell-history) :prompt "Shell history: " :history t :sort nil :initial (buffer-substring-no-properties beg end) :state (consult--insertion-preview beg end)))) (delete-region beg end) (insert (substring-no-properties str)))))) (provide 'kj-history)