How can I prompt a user for input and use this as a variable in my package?


#1

Hi,

Earlier today I started a new issue at my language-archlinux package, requesting for help with creating a new command for this package that requires user input. I’m not sure how to prompt users for input and use that input in my command. Before you state the obvious way of resolving this issue myself, that is, looking at the source code of packages that prompt users for input and then act based on it, I have. Specifically I have looked at the source code of the man package and git-plus packages, which both prompt users for input. But I do not understand CoffeeScript (or for that matter JavaScript) well enough to know what I need to copy to get my package to do this. Please, break this down for me and I will be eternally grateful!

Thanks for your time,
Brenton


#2

From your issue, just copying from the man package wouldn’t be enough. You need multiple inputs. Also, it sounds like your collaborator is on top of it, but the man package has a very simple implementation of user input, so I think it’s still useful here for educational purposes.

There are a whole bunch of ways to prompt for input. It really depends on how you want to do it and what sort of input you require. If you just want a simple string like the man package, you can do exactly what it does.

The action starts in man.coffee. When the (hilariously named) man:man command is called, it does this:

    man: () ->
        @manInputView = new ManInputView()

So we can go over to man-input-view.coffee and look at that. When the new view is created, the attach method is called.

        attach: ->
            @panel ?= atom.workspace.addModalPanel(item: this)
            @panel.show()
            @selectEditor.focus()

This makes a modal panel with nothing in it except for the text field, and focuses the text field. We know what selectEditor refers to because of

        @content: ->
            @div class: 'command-palette', =>
                @subview 'selectEditor', new TextEditorView(mini: true)

When you hit enter, the confirm method gets called (enter is bound by default to core:confirm, which the initialize method associates with @confirm). This gets the text in the editor and tries to open a man page at the URI.

        confirm: ->
            page = @selectEditor.getText()
            uri = "man://editor/#{page}"
            atom.workspace.open(uri)
            @detach()

Then detach just does cleanup.


How do you ask the user for input?
#3

Your answer was so good that I was able to implement this myself without any further help.


#4

Woot, score. :smiley:


#5

Thanks for the answer, it helped me a lot, but it seems that the input is async.
The form opens but it is the Enter key that triggers the rest of the action.
What I would need is a sync prompt like:

var answer = Input.prompt();

The execution would be interrupted waiting for the user.

Thanks.


#6

Wouldn’t a sync prompt stop all Atom functionality until it was done, not just the execution of your package?


#7

Indeed, but It would be OK.
I’d like to run programs written in a language for which I have a JS interpreter.
In some programs, there are instructions like window.prompt() that I’d like to be able to use in Atom.


#9

As far as I know, there’s nothing in Atom’s API that’s designed for this, so you might either have to access the browser functions. Have you tried implementing window.prompt()?

This Node package sounds like a possibility.


#10

Thanks for this pointer. I tried so many such packages in the past to build a REPL in the CLI that I can’t remember if I tried this one.
I’m currently using readline-sync but not in Atom.
prompt-sync seems to also rely on TTY and so cannot work in Atom.

What were you saying about Electron?

EDIT: Searching for the error I first bumped on (prompt is and will not be supported), I found this interesting thread:
https://discuss.atom.io/t/why-isnt-window-prompt-supported/24299/

EDIT2: This one is interesting too:
https://github.com/electron/electron/issues/472


#11

In that case, you will probably have to just make your package wait until it receives input before proceeding, without it being properly synchronous.

Nothing. I misread the dialog docs.