How to implement a simple text menu in console?

Posted on
  • Hi,

    I am using a RAK8212 and want to implement a simple interactive text menu.
    I am connected via BLE.

    The text menu could look like this:

    Please enter you choice:
    
    1 Do this
    2 Do that
    
    You choice>
    

    Bluetooth.read(1) returns immediately.
    Bluetooth.on('data', function() {...}) also doesn't work, as the application has no such a thing as a event loop that runs all the time.

    Any ideas how to create a interactive text menu in the console?

  • Not a perfect solution, but until you have something more elaborate: make the menu point A, B and C... and ask to enter A, B or C appended with (), for example: B(). This is like ad-hoc invoking the function B() on the Espruino board. Before showing the menu, define the A(), B() and C() ... functions (body) and delete them after menu input... (Instead of define and delete, assign A, B and C to and existing empty function, before the menu you assign them the desired existing functions, and afterwards you re-assign them again to the empty function.) That's the least intrusive option.

    The other option is to loop something into the console loop: before it reaches the JavaScript interpreter, you catch it, test it, and do what you need, and if it is not the menu thing, you pass it untouched... (Loopback?) may be you can put something into the echo-routined (post vs pre, and then clean out the expression input buffer of the JavaScript interpreter)... About the details: I'm not knowledgeable enough, would need to do some research.

    You can make the both flag/state controlled, so you do not have to setup and tear down for every menu.

  • At least when console is on Serial1 you can move it somewhere else (LoopbackA.setConsole();) and then read Serial1 directly. And after reading answer you can set console back via Serial1.setConsole()
    see e.g. http://forum.espruino.com/conversations/278818/

    Not sure if it is posible with bluetooth console too, possibly yes?

  • I like the idea with having A(), B(), C() function names.

  • As @fanoush says you can move the console elsewhere. Maybe try something like:

    function ask(text, callback) {
      Bluetooth.println(text);
      Bluetooth.on('data',function(d) {
        Bluetooth.removeAllListeners("data");
        callback(d);
      });
    }
    
    function go() {
      // Move console out the way
      LoopbackA.setConsole();
      ask("A, B or C?", function(d) {
        Bluetooth.println("You picked "+JSON.stringify(d));
        ask("1, 2 or 3?", function(d) {
          Bluetooth.println("You picked "+JSON.stringify(d));
          /* Move the console back so you
          can interact with the REPL again. If you don't
          you'll have to disconnect and reconnect via
          Bluetooth to get it back */
          Bluetooth.setConsole();
        });
      });
    }
    

    Note that while the console is out the way, print/etc won't work either and you can't interact with the REPL.

    As @allObjects says, having A() etc is super easy to do though.

    Another option based on that is to use 'getters' that got introduced in new Espruino 2v00ish, which will work in a similar way, but without you needing the brackets:

    >Object.defineProperty(global,"a",{get:()=>print("you picked 'a'")})
    ={...}
    >a
    you picked 'a'
    
  • @Gordon, getters are THE PERFECT solution... NICE ...how could I not think about... (never used getters, not even in my browser world, where most of my JS exposure happened...)

  • getters are THE PERFECT solution

    Well, in this specific case I would call it very nice hack, not perfect solution ;-)

    However something like console.pause()/resume() would help in this case so that it doesn't need to be reassigned twice with that ->xxx message. Also maybe console.current referencing which Serial device is current console would help in case of temporary reassignment (or is there a way to get it?).

  • You can get the current device with eval(process.env.CONSOLE) - but honestly just a flag to ditch the console reassignment messages would probably be fine?

  • but honestly just a flag to ditch the console reassignment messages would probably be fine?

    Yes. perhaps with some harmless Null device that would just drop the bytes if LoopbackA is not harmless (i.e. buffering the data for LoopbackB, eating memory).

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

How to implement a simple text menu in console?

Posted by Avatar for wklenk @wklenk

Actions