Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

comint-input-ring usage #336

Closed
azzamsa opened this issue May 28, 2020 · 8 comments
Closed

comint-input-ring usage #336

azzamsa opened this issue May 28, 2020 · 8 comments

Comments

@azzamsa
Copy link

azzamsa commented May 28, 2020

Can we use comint in vterm buffer?

I tried helm-comint-input-ring in vterm buffer it doesn't work. But it works in other e/shell/ansi-term buffer.

Thank you for vterm.

@brotzeit
Copy link
Contributor

brotzeit commented Jun 1, 2020

vterm currently doesn't fill helm-comint-input-ring.

I'm using a custom helm source on a file and modified vterm-send-return so it appends the input to this file.

(setq term-prompt-regexp "^[^#$%>\\n]*[#$%>] *")
(defvar vterm-history "path/to/vterm_history")

(defun vterm-send-return ()
  "Send `C-m' to the libvterm."
  (interactive)
  (when vterm--term
    (let* ((beg (vterm--get-prompt-point))
          (end (vterm--get-end-of-line))
          (string (buffer-substring-no-properties beg end))
          (file vterm-history))
      (write-region (concat string "\n") nil file t 0))
    (if (vterm--get-icrnl vterm--term)
        (process-send-string vterm--process "\C-j")
      (process-send-string vterm--process "\C-m"))))

(defun helm-vterm-history ()
  (interactive)
  (let ((contents (with-temp-buffer
                    (insert-file-contents vterm-history)
                    (reverse (split-string (buffer-string) "\n")))))
    (helm :sources `((name . "vterm history")
                     (candidates . contents)
                     (action . (lambda (candidate)
                                 (vterm-send-string candidate))))
          :candidate-number-limit 10000)))

I noticed this still needs some improvements :P

@azzamsa
Copy link
Author

azzamsa commented Jun 2, 2020

Great!. It works like a charm.

Thank you for vterm.

@azzamsa azzamsa closed this as completed Jun 2, 2020
@azzamsa
Copy link
Author

azzamsa commented Jun 2, 2020

@brotzeit I've added the check to ignore empty string so that it doesn't get written into the history file.

image

@azzamsa
Copy link
Author

azzamsa commented Jun 3, 2020

I've some problem with the code:

  1. duplicate entries
  2. appending empty string.

So here is my updated version:

I'll updated the code here if I find a bug

(defun get-current-cmd ()
    (let* ((beg (vterm--get-prompt-point))
           (end (vterm--get-end-of-line)))
      (buffer-substring-no-properties beg end)))

  (defun vterm-send-return ()
    "Send `C-m' to the libvterm."
    (interactive)
    (when vterm--term
      (let* ((current-cmd (get-current-cmd)))
        (if (not (string= current-cmd ""))
            (add-to-list 'vterm-history current-cmd)))

      ;; default part from vterm.el
      ;; (setq cursor-type 'bar)
      (if (vterm--get-icrnl vterm--term)
          (process-send-string vterm--process "\C-j")
        (process-send-string vterm--process "\C-m"))))

  (defun helm-vterm-history ()
    (interactive)
    (let ((histories vterm-history)
          (current-cmd (get-current-cmd)))
      (helm :sources `((name . "vterm history")
                       (candidates . histories)
                       (action . (lambda (candidate)
                                   (vterm-send-string candidate))))
            :input current-cmd
            :candidate-number-limit 10000))))

@brotzeit
Copy link
Contributor

brotzeit commented Jun 3, 2020

Instead of checking if the string is empty, I don't append strings that are too long. For example when you use return on the output of systemctl status, you get the whole output appended to your history every time you press enter.

Maybe somebody finds a better way to handle this. It's really convenient to have a global history.

@azzamsa
Copy link
Author

azzamsa commented Jun 3, 2020

Instead of checking if the string is empty, I don't append strings that are too long. For example when you use return on the output of systemctl status, you get the whole output appended to your history every time you press enter.

I can't reproduce this behavior with the code above

@brotzeit
Copy link
Contributor

brotzeit commented Jun 3, 2020

Oh then I have to try it 👍

@theottm
Copy link

theottm commented Dec 13, 2022

I also looked for something like that. I'm using the completing-read ecosystem though. I implemented something this morning.

I am mostly interested in the history of zsh, so I ended up reading the zsh history directly. Duplicates are already handled by zsh so this is nice. Here is the code maybe it helps someone in the future:

;; this function is from http://xahlee.info/emacs/emacs/elisp_read_file_content.html
(defun read-lines-from-files (filePath)
  "Return a list of lines of a file at filePath."
  (with-temp-buffer
    (insert-file-contents filePath)
    (split-string (buffer-string) "\n" t)))

(defun vterm-history (histfile)
  (vterm-send-string (completing-read "Commands: " (read-lines-from-files histfile)) t))

(defun vterm-history-zsh ()
  (interactive)
  (vterm-history "~/.config/zsh/.histfile"))

(define-key vterm-mode-map (kbd "C-c C-q") 'vterm-history-zsh)

As you see this can be easily adapted to read from any history file, even from a combination of history files if needed.

It probably also relates to minad/consult#121

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

No branches or pull requests

3 participants