zyedidia / micro

A modern and intuitive terminal-based text editor
https://micro-editor.github.io
MIT License
25.04k stars 1.17k forks source link

Cursor doesn't return to document after a prompt ends #300

Closed techtonik closed 8 years ago

techtonik commented 8 years ago
  1. type some letters so that file becomes unsaved
  2. hit CtrlQ to see quit prompt
  3. hit CtrlQ once more, quit prompt is still there (and it probably should not be)
  4. press 'n'

Instead of quitting, `n' is typed into editor.

micro-a4ac9f2-win32.zip

zyedidia commented 8 years ago

This is the expected behavior. Pressing CtrlQ always cancels a prompt. The issue here is that on Windows the prompt is not cleared and the cursor is not put back in the right location.

techtonik commented 8 years ago

Is it only on Windows? From https://github.com/zyedidia/micro/blob/a6d695f47137c24be7da9aec217dc94ec02fec9b/cmd/micro/actions.go#L1300 I don't see where Quit action cancels the prompt. Or is it deeper..

techtonik commented 8 years ago

.. not in CanClose https://github.com/zyedidia/micro/blob/a6d695f47137c24be7da9aec217dc94ec02fec9b/cmd/micro/view.go#L167 interesting - it looks like Go allows to spread method definitions over several files, I see that Quit method on View was in actions.go - looks like View is a some kind of God-like object. =)

zyedidia commented 8 years ago

Yeah, inside CanClose it calls messenger.Prompt which is a function in messenger.go. Here is the line you are looking for: https://github.com/zyedidia/micro/blob/a6d695f47137c24be7da9aec217dc94ec02fec9b/cmd/micro/messenger.go#L190

techtonik commented 8 years ago

Prompt is not removed from screen too.

zyedidia commented 8 years ago

My bad, this is actually not windows only.

techtonik commented 8 years ago

The thing that is unclear in https://github.com/zyedidia/micro/commit/54a34001e33641b2e9de832eb6d417d7813cbb9a is why for returning on CtrlQ m.Clear + m.Reset is not needed, but for returning on n only m.hasPrompt is not enough.

zyedidia commented 8 years ago

Well it's a question of whether the prompt should clear itself when it is done, or whether it is up to the caller to reset and clear. I was inconsistent here, so I guess I'll clean it up a bit.

techtonik commented 8 years ago

In my case the logic is that I expected the messenger to clear the prompt when messenger is done interacting with user.

techtonik commented 8 years ago

How about this? Would that be an improvement to the code?

diff --git a/cmd/micro/messenger.go b/cmd/micro/messenger.go
index a272a78..00c0374 100644
--- a/cmd/micro/messenger.go
+++ b/cmd/micro/messenger.go
@@ -126,12 +126,12 @@ func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) {
 }

 // LetterPrompt gives the user a prompt and waits for a one letter response
-func (m *Messenger) LetterPrompt(prompt string, responses ...rune) (rune, bool) {
+func (m *Messenger) LetterPrompt(prompt string, responses ...rune) (choice rune, aborted bool) {
    m.hasPrompt = true
    m.Message(prompt)

    _, h := screen.Size()
-   for {
+   for m.hasPrompt {
        m.Clear()
        m.Display()
        screen.ShowCursor(Count(m.message), h-1)
@@ -144,20 +144,19 @@ func (m *Messenger) LetterPrompt(prompt string, responses ...rune) (rune, bool)
            case tcell.KeyRune:
                for _, r := range responses {
                    if e.Rune() == r {
-                       m.Clear()
-                       m.Reset()
                        m.hasPrompt = false
-                       return r, false
+                       choice, aborted = r, false
                    }
                }
            case tcell.KeyCtrlC, tcell.KeyCtrlQ, tcell.KeyEscape:
-               m.Clear()
-               m.Reset()
                m.hasPrompt = false
-               return ' ', true
+               choice, aborted = ' ', true
            }
        }
    }
+   m.Clear()
+   m.Reset()
+   return
 }

 type Completion int