diff --git a/qutebrowser/mainwindow/prompt.py b/qutebrowser/mainwindow/prompt.py index e052fcbd5..547b84b8a 100644 --- a/qutebrowser/mainwindow/prompt.py +++ b/qutebrowser/mainwindow/prompt.py @@ -538,7 +538,7 @@ class FilenamePrompt(_BasePrompt): self._lineedit = LineEdit(self) if question.default: self._lineedit.setText(question.default) - self._lineedit.textChanged.connect(self._set_fileview_root) + self._lineedit.textEdited.connect(self._set_fileview_root) self._vbox.addWidget(self._lineedit) self.setFocusProxy(self._lineedit) @@ -546,18 +546,25 @@ class FilenamePrompt(_BasePrompt): self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) @pyqtSlot(str) - def _set_fileview_root(self, path): + def _set_fileview_root(self, path, *, tabbed=False): """Set the root path for the file display.""" separators = os.sep if os.altsep is not None: separators += os.altsep - if path == '/' or (path and path[-1] not in separators): + if not path: return - path.rstrip(separators) + + dirname = os.path.dirname(path) try: - if not os.path.isdir(path): + if path[-1] in separators and os.path.isdir(path): + # Input like /foo/bar/ -> show /foo/bar/ contents + path = path.rstrip(separators) + elif os.path.isdir(dirname) and not tabbed: + # Input like /foo/ba -> show /foo contents + path = dirname + else: return except OSError: return @@ -580,6 +587,7 @@ class FilenamePrompt(_BasePrompt): log.prompt.debug('Inserting path {}'.format(path)) self._lineedit.setText(path) self._lineedit.setFocus() + self._set_fileview_root(path, tabbed=True) if clicked: # Avoid having a ..-subtree highlighted self._file_view.setCurrentIndex(QModelIndex()) diff --git a/tests/unit/mainwindow/test_prompt.py b/tests/unit/mainwindow/test_prompt.py index 9018e3b88..98cd8b550 100644 --- a/tests/unit/mainwindow/test_prompt.py +++ b/tests/unit/mainwindow/test_prompt.py @@ -20,6 +20,7 @@ import os import pytest +from PyQt5.QtCore import Qt from qutebrowser.mainwindow import prompt as promptmod from qutebrowser.utils import usertypes @@ -34,6 +35,7 @@ class TestFileCompletion: @pytest.fixture def get_prompt(self, qtbot): + """Get a function to display a prompt with a path.""" def _get_prompt_func(path): question = usertypes.Question() question.title = "test" @@ -56,6 +58,7 @@ class TestFileCompletion: ]) def test_simple_completion(self, tmpdir, get_prompt, steps, where, subfolder): + """Simply trying to tab through items.""" for directory in 'abc': (tmpdir / directory).ensure(dir=True) @@ -65,3 +68,20 @@ class TestFileCompletion: prompt.item_focus(where) assert prompt._lineedit.text() == str(tmpdir / subfolder) + + def test_backspacing_path(self, qtbot, tmpdir, get_prompt): + """When we start deleting a path we want to see the subdir.""" + for directory in ['bar', 'foo']: + (tmpdir / directory).ensure(dir=True) + + prompt = get_prompt(str(tmpdir / 'foo') + os.sep) + + # Deleting /f[oo/] + with qtbot.wait_signal(prompt._file_model.directoryLoaded): + for _ in range(3): + qtbot.keyPress(prompt._lineedit, Qt.Key_Backspace) + + # We should now show / again, so tabbing twice gives us .. -> bar + prompt.item_focus('next') + prompt.item_focus('next') + assert prompt._lineedit.text() == str(tmpdir / 'bar')