Customizing the Prompt in Mini Micro

JoeStrout - Jul 23 '23 - - Dev Community

Though Mini Micro is a modern virtual machine, it shares some design features with classic home computers of the '80s era. Most noticeable of these is that it boots into a prompt, which is a short string next to a blinking cursor.

animated GIF of prompt and blinking cursor

The purpose of the prompt is to make it clear that anything you type is going to the command shell (which in Mini Micro's case, means the MiniScript read-eval-print loop), rather than to some running program that is asking for input.

By default, the prompt in Mini Micro is a right square-bracket, as you can see in the image above. But did you know that you can change this prompt? You can make it any text you like, and beyond that, you can even write code to dynamically change the prompt. This article will show how and give several examples, from simple to fancy.

Changing the Prompt Strings

Let's start with the simplest case: maybe you don't like the square bracket because that's also used in MiniScript syntax (for indexing into things, e.g. "Howdy"[:3]). Perhaps you'd prefer the pound (hashtag) sign, which has no use in MiniScript syntax. Just type:

env.prompt = "#"
Enter fullscreen mode Exit fullscreen mode

env.prompt = "#"

Or you could use some even more obscure character, like those you find in /sys/demo/specialChars. For example, try:

env.prompt = char(57888)
Enter fullscreen mode Exit fullscreen mode

env.prompt = char(57888)<br>

Any string you assign to env.prompt will appear as the command prompt until you assign something else (or quit Mini Micro). It doesn't have to be a single character; if your name is Jen, perhaps you'd like "Hello Jen!" as your prompt. Go wild!

Remember the "more" prompt

The MiniScript REPL actually uses two prompts: the standard one we've shown so far, and a second one used when the REPL needs more input, for example because you have started an if block or for loop. This second prompt is "...]" by default.

for loop on the command line

But you can override this "more input needed" prompt as well, by assigning to env.morePrompt. For example, again referring to /sys/demo/specialChars, you could choose to use a 1-spot die for the main prompt and a 3-spot die (reminiscent of "...") for the morePrompt:

env.prompt = char(9856)
env.morePrompt = char(9858)
Enter fullscreen mode Exit fullscreen mode

Dice prompts

Updating the startup script

To keep your custom prompt working even after you restart Mini Micro, you'll want to put it into your startup script. Use cd to ensure the current directory is /usr. Then, if you already have a /usr/startup.ms file, edit "startup" will launch the editor with that file. If not, just do edit to edit a new program, and save it as "startup". In either case, type some code like the following into your startup script:

// set a custom prompt
env.prompt = char(57888)
Enter fullscreen mode Exit fullscreen mode

Be sure to save this program so it'll be there for you the next time you run Mini Micro. Also run the program once to make sure your changes are applied right away. Note that you can save and run directly from the code editor, using the buttons at the top (or their keyboard shortcuts); or you can close the editor and use the save and run commands on the command line.

Making a prompt function

Instead of assigning just a simple string, you can assign a function to env.prompt. This function can do anything you like, as long as it returns quickly. If it returns a string, that string will be displayed as the prompt in the usual way. Or, your function can do its own printing.

For example, here's an example that prints the prompt in a darker color, by interpolating between the current text color and the text background color.

env.prompt = function
    c = text.color
    text.color = color.lerp(c, text.backColor)
    print "]", ""
    text.color = c
end function
Enter fullscreen mode Exit fullscreen mode

Running this code causes the prompt to fade nicely into the background, so you can focus your attention on the MiniScript code.

A faded prompt

Or, perhaps you always want to know what time it is? You could have your prompt display the time!

env.prompt = function
    return _dateStr[-8:] + ">"
end function
Enter fullscreen mode Exit fullscreen mode

Time prompt

(Note that this directly uses the _dateStr function normally wrapped by the /sys/lib/dateTime module, but we can't count on having that module available for the prompt function, so we use _dateStr directly here.)

Or if you're like me, you have a lot of directories and subdirectories, and sometimes forget which one you're in. Try this prompt function to display the current directory in your prompt:

env.prompt = function
    return file.curdir + "]"
end function
Enter fullscreen mode Exit fullscreen mode

If you find that creates a prompt that is too long, then consider this version, which shows just the last part of the current directory:

env.prompt = function
    d = file.curdir
    if d[-1] == "/" then d = d[:-1]
    return d.split("/")[-1] + "]"
end function
Enter fullscreen mode Exit fullscreen mode

Directory prompt

Getting Fancy

Your prompt and morePrompt functions don't have to restrict themselves to printing something for the prompt itself; they can do anything, as long as they do it very quickly. (If a prompt function takes too long to execute, Mini Micro will cancel it and display no prompt at all.)

The longer startup script below creates a prompt function that draws a status bar, showing the current directory as well as the date/time, at the top of the screen in display layer 1. It also draws the standard prompt, but in a different color, and does the same for the "more" prompt. Finally, it replaces the standard clear method (normally defined in /sys/lib/startup.ms) with one that leaves display layer 1 alone, and resets the text cursor to row 24, since row 25 is now under the status bar.

env.prompt = function
    now = _dateStr
    s = file.curdir + " " * 68
    s = s[:68-now.len] + now
    display(1).mode = displayMode.text
    display(1).backColor = color.clear
    display(1).clear
    display(1).row = 25; display(1).column = 0
    display(1).color = color.black
    display(1).backColor = "#6666CC"
    display(1).print s
    c = text.color
    text.color = color.lerp(c, text.backColor)
    print "]", ""
    text.color = c
    return "?!?"
end function

env.morePrompt = function
    c = text.color
    text.color = color.lerp(c, text.backColor)
    print "...]", ""
    text.color = c
    return "?!?"
end function

clear = function
    display(0).mode = displayMode.off
    display(2).mode = displayMode.off
    display(3).mode = displayMode.text
    display(3).clear
    display(4).mode = displayMode.sprite
    display(4).clear
    display(5).mode = displayMode.pixel
    display(5).clear "#00000D", 960, 640
    display(6).mode = displayMode.off
    display(7).mode = displayMode.solidColor
    display(7).color = "#000000"
    globals.text = display(3)
    globals.gfx = display(5)
    text.row = 24
end function
Enter fullscreen mode Exit fullscreen mode

The result looks like this:

Screen shot of fancy prompt function in action

I hope this gives you some ideas! Take the time to play around with the examples above, and find prompts that best suit your own preferences. Let me know in the comments what you decide to do!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .