Default Value for ASK()

I was wondering if there was a way to default a value for ask, or the REQUIRED fields… so they can just click enter, or change it.

If I make it required, the default doesn’t work, if I make it not required, it won’t prompt them.
I don’t know if this is done as CommandBox level, or at the Jline level.

Any ideas?

I mapped it down to
jline.console.ConsoleReader.readLine( message ) ;

I guess this means there isn’t an easy way to do it.
:frowning:

Looking at the API… It looks like we could add Completors for the Ask command though… maybe?
:slight_smile:

Gavin Pickin
gpickin@gmail.com
http://www.gpickin.com

This sounds like a really good idea though we’d need to think it through. I think the biggest issue will be whether or not a question being "ask"ed would ever have a legitimate answer of an empty string. If not, I don’t think it would be too hard.

Adding a default to ask could be as simple as adding a second 'defaultValue" parameter to the ask() method in shell.cfc. Just check what comes back from the following line

var input = variables.reader.readLine( arguments.message );

and if it’s an empty string, just use the default value. The “ask” method in baseCommand would also need its signature updated.

Using the default for command parameters would be handled here:

https://github.com/Ortus-Solutions/commandbox/blob/master/src/cfml/system/services/CommandService.cfc#L530

There’s a couple things to consider though:

  1. CFML allows runtime expressions to be for method arguments:

function foo( bar=myvariable, baz=[] ) {}

In those instances it’s impossible to get that value from the function’s metadata.

  1. We’d need to make sure noone ever set a command parameter to ‘required’ if they wanted the command to be executable without user input using the default. I think that would be easy enough.
  • optional, no default – don’t ask if not provided, undefined
  • optional, with default – don’t ask if not provided, default value used
  • required, no default – ask if not provided, force user to enter something at gunpoint
  • required, with default – ask if not provided, allow “empty” input to use the default value
    And that last bold part would be where your suggestion fits in. With the assumption that a blank value is never a desired value and the default value in the component is not a runtime expression.

> Looking at the API… It looks like we could add Completors for the Ask command though… maybe?

No, the reason tab complete doesn’t work for "ask’ boils down to the Java jline libraries. They have a sort of narrow vision for how their libs are used in my opinion and they sort of view readLine() and readCharacter() (which we use in shell.waitForkey()) to be “internal method[s]” that we shouldn’t rely on. (https://github.com/jline/jline2/issues/152)
Since the tab complete captures the tab characters and outputs the completion options at the Java level we have no control over that. I am, however, in favor of bugging the Jline people to enhance their java library, but their lackluster response to my previous tickets don’t give me a great deal of hope. I think it’s truly a “community” project in people spare time so we’d be more likely to get it changed if we actually did the work and submitted pulls (which STILL isn’t a guarantee, of course).

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

I was thinking more pre-populate the field, I guess no one does that these days… the action you described is more the norm.

I was thinking it would prompt like

Select Webroot: /wwwroot/myroot

Which you could backspace and correct… but we could do the default much easier, on the other end of the ask statement, without any issues.
I just wanted to not ask them to type it all from scratch, if they previously set it.
If they wanted to ADD onto it or REMOVE from, it would be easier if it was already pre-entered.
But alas, doesn’t look that way.

All good.

Its fun playing with all this… pretty cool what we can do.
I’m hoping my little project ends up useable for more than just me.

Gavin Pickin

gpickin@gmail.com
http://www.gpickin.com

Pre-populating the line would be great but we’d have to check and see if the jline lib allows for that.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Ooh, guess what-- I was wrong about readLine(). I thought there was another method we use for the actual interactive prompt, but consoleReader.readLine() is actually what we use.

https://github.com/Ortus-Solutions/commandbox/blob/master/src/cfml/system/Shell.cfc#L361

This is good because it means we can get tab completion to work for ask()!

The first trick is that we’ll need to trick the completor. Right now the completor (a CFC that’s passed via Java Proxy to the jline libs) gets the currently entered text, parsed it, and comes up with the options. In this instance, we’ll probably need to remove the completor from the reader, and add in a temporary one that we can seed with some information so it knows what it’s supposed to be completing. When we’re done, we’ll need to switch back to the normal completor.

The next trick will be populating the prompt with a default value. I don’t know which method we want, but I’m pretty sure one of these methods in the consolereader class will do that for us. Possibly this one:
http://jline.sourceforge.net/javadoc/jline/ConsoleReader.html#printString(java.lang.String)

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

I seem have a proof of concept working, though I had to hack it a bit. It turns out the readLine() methods in jline don’t allow you to seen the prompt with any text, and while putString() will output to the buffer, you can’t call putString() before readLine() because it will get output before the prompt and you can’t call it after because readLine blocks until it receives your input.

I was able to trick it by threading the readline() call, waiting 100ms, then outputting the default value and flushing the buffer, then joining back to the thread to await your input. Slap this code in a command to see it work (hopefully)

reader = shell.getReader();

var threadname = createUUID();
variables.char = ‘’;
thread name="#threadname#" action=“run” {
variables.char = reader.readLine( 'What is your quest? > ’ );
}

sleep(100);
reader.putString( ‘To seek the Holy Grail.’ );
reader.flush();

thread action=“join” name="#threadname#";

print.boldRedLine( variables.char ).toConsole();
shell.setPrompt();

That code has some issues-- for instance, it throws crap in the variables scope just to get around cfthread’s scoping behaviors, but I think it shows we can bend ask() to our will :slight_smile: I may also put in a ticket for the jline project to support this though I won’t get my hopes up.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Oh, and on this topic-- something that has bugged me for a while is stuff you type as an “ask” prompt is stored in your history, which means hitting the up arrow after the command finishes and you’re back to the “regular” CommandBox prompt suggests your previous answers as commands. We need to remove the reader’s history object before “asking” and put it back when done. We do some shenanigans like this already in the REPL command as script and tag REPLs have their own histories.

Anyway, just a note for you to remind me us to do that if/when we get around to coding all this. Speaking of Gavin, can you enter a ticket? I also put in an issue in the JLine project to support this in the core. It will be interesting to see what they say:
https://github.com/jline/jline2/issues/177

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Cool… I thought it said we could use a completor but that’s as deep as I could go with learning more about all this jline stuff.

It’s not the end of the world, but kind of nice to know we could do it.
Do you / we want to do it? Good question

When more people start playing with commands we’ll have more feedback to go on

Yeah, I think we should do it. The jline stuff isn’t too complicated. All it really is, is a Java library meant to abstract all the stupid differences between terminals and operating systems so you can display a prompt on a console and collect the text. The API is pretty straightforward and I’ve even perused through the Java code to see what it does. Think of it as a multi-browser jQuery plugin for consoles :slight_smile:

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com