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

File name completion overwrites already entered path in shell-mode #1755

Open
vidagabor opened this issue Sep 13, 2018 · 5 comments · May be fixed by #3051
Open

File name completion overwrites already entered path in shell-mode #1755

vidagabor opened this issue Sep 13, 2018 · 5 comments · May be fixed by #3051
Labels
bug compat Issues relating to backward/forward compatibility

Comments

@vidagabor
Copy link

Hi!

I have a long standing issue: in shell-mode, let's say there's /aa/bbb/cccc directory, and I want to complete this. If I enter "cd /aa/bbb" and I hit TAB, I get "cd /aabbb/" immediately. If I enter "cd /aa/bbb/" (there's a trailing /), and I hit TAB, the dropdown list appears which allows me to select from the candidates, which is "..", "cccc" and "." in this example. So after TAB, the already entered command switches to "cd /aa/b". If I go down and select "cccc" from the list, I get "cd /aa/bcccc". It varies how many characters of the already entered path is overwritten, but I couldn't figure out what it depends on.

If I toggle debug-on-quit, and hit ^G while the dropdown list is active, I get this back trace:

Debugger entered--Lisp error: (quit)
  read-from-minibuffer("(/aa/bbb/): " nil (keymap keymap (3 keymap (19 . ivy-rotate-sort) (1 . ivy-toggle-ignore) (15 . ivy-occur)) (67108903 . ivy-avy) (33554464 . ivy-restrict-to-matches) (15 . hydra-ivy/body) (22 . ivy-scroll-up-command) (prior . ivy-scroll-down-command) (next . ivy-scroll-up-command) (7 . minibuffer-keyboard-quit) (right . ivy-forward-char) (32 . self-insert-command) (18 . ivy-reverse-i-search) (19 . ivy-next-line-or-history) (remap keymap (describe-mode . ivy-help) (kill-ring-save . ivy-kill-ring-save) (kill-whole-line . ivy-kill-whole-line) (kill-line . ivy-kill-line) (scroll-down-command . ivy-scroll-down-command) (scroll-up-command . ivy-scroll-up-command) (end-of-buffer . ivy-end-of-buffer) (beginning-of-buffer . ivy-beginning-of-buffer) (kill-word . ivy-kill-word) (forward-char . ivy-forward-char) (delete-char . ivy-delete-char) (backward-kill-word . ivy-backward-kill-word) (backward-delete-char-untabify . ivy-backward-delete-char) (delete-backward-char . ivy-backward-delete-char) (previous-line . ivy-previous-line) (next-line . ivy-next-line)) (9 . ivy-partial-or-done) (10 . ivy-alt-done) (27 keymap (1 . ivy-read-action) (15 . ivy-dispatching-call) (111 . ivy-dispatching-done) (105 . ivy-insert-current) (106 . ivy-yank-word) (114 . ivy-toggle-regexp-quote) (16 . ivy-previous-line-and-call) (14 . ivy-next-line-and-call) (118 . ivy-scroll-down-command) (112 . ivy-previous-history-element) (110 . ivy-next-history-element) (10 . ivy-immediate-done) (13 . ivy-call)) (mouse-3 . ivy-mouse-dispatching-done) (mouse-1 . ivy-mouse-done) (down-mouse-1 . ignore) (13 . ivy-done)) nil ivy-history)
  ivy-read("(/aa/bbb/): " (#("../" 0 1 (font-lock-face completions-first-difference)) #("cccc/" 0 1 (font-lock-face completions-first-difference)) #("./" 0 1 (font-lock-face completions-first-difference))) :predicate nil :initial-input nil :sort t :action ivy-completion-in-region-action :unwind #f(compiled-function () #<bytecode 0x262bb59>) :caller ivy-completion-in-region)
  ivy-completion-in-region(#<marker at 668596 in shell @ /to:dc153fnd:/> 668604 #f(compiled-function (string pred action) #<bytecode 0x27767a5>) nil)
  completion-in-region(#<marker at 668596 in shell @ /to:dc153fnd:/> 668604 #f(compiled-function (string pred action) #<bytecode 0x27767a5>) nil)
  completion-at-point()
  funcall-interactively(completion-at-point)
  call-interactively(completion-at-point nil nil)
  command-execute(completion-at-point)

The buffer's name is "shell @ /to:dc153fnd:/" and the shell's prompt is "root@fnd01:/# ".

I'm using GNU Emacs 26.1 (build 1, x86_64-pc-linux-gnu, X toolkit, Xaw scroll bars) of 2018-06-13, and I'm using ivy 20180820.1526 installed via package.el.

I'd really appreciate any pointers how to debug this issue further, since I'm pretty sure I'm not the only one who uses Ivy like this, but seems that only I have this issue (for a long time, like at least half a year).

@neosimsim
Copy link

Having the same issue for a while.

@plantarum
Copy link

I just ran into this today, after using ivy for many years without issue.

To reproduce from emacs -Q, evaluate the following code:

(require 'package)
(setq package-load-list
      '((ivy t)))

(package-initialize)
(ivy-mode)
(shell)

This opens a shell. In my case, I have a directory ~/nextcloud/org. If I enter cd ~/next<TAB>, it completes to ~/nextcloud/. Pressing tab again offers me a vertical list of directories in ~/nextcloud/. When I select one, it is inserted a few spaces backwards. For example, if I select ~/nextcloud/org, after completion I have cd nextorg/.

GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.20, cairo version 1.16.0) of 2024-07-02
Ivy installed from Melpa 2024-07-31: ivy-20240524.1139, Version: 0.14.2,

@plantarum
Copy link

The problem seems to occur in ivy-completion-in-region, which gets called from comint-dynamic-complete-filename, which calls completion-in-region:

swiper/ivy.el

Lines 2682 to 2691 in 2a25a6f

(let* ((len (ivy-completion-common-length (car comps)))
(initial (cond ((= len 0)
"")
((let ((str-len (length str)))
(when (> len str-len)
(setq len str-len)
str)))
(t
(substring str (- len))))))
(delete-region (- end len) end)

At this point, it looks like the length of the first match in the completion list ((car comps)) is deleted from the path to be completed. I don't understand the logic here, and presumably it's correct in other contexts. But in this situation it's clearly causing problems.

As a temporary fix, this resets the default completion-in-region-function value for shell-mode:

(defun tws-shell-mode-hook ()
  ;; to override ivy-mode, which provides a problematic
  ;; completion-in-region variation:
  (setq-local completion-in-region-function #'completion--in-region))

(add-hook 'shell-mode-hook 'tws-shell-mode-hook)

@basil-conto
Copy link
Collaborator

basil-conto commented Aug 13, 2024

I just ran into this today, after using ivy for many years without issue.

Perhaps it was introduced by the following commit in Emacs 30?

At least that's when I noticed the issue in C-x p c (project-compile, which in turn delegates completion to comint-completion-at-point).

Highlight the suffix in Completions buffer in 'basic' style too
6b7ff60a5e7 2024-06-13 00:46:12 +0300

@basil-conto
Copy link
Collaborator

At first glance it looks like #3051 might be trying to address this issue; I'll try to dig deeper soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug compat Issues relating to backward/forward compatibility
Projects
None yet
4 participants