Input Line Editor with history function

From Nutwiki
Jump to: navigation, search

Overview

This example introduces another function of the Nut/OS EdLine module: The history function.

In most editors and command shells nowadays, you can recall previously issued commands using the up and down keys, saving you the effort of retyping the commands over and over again. EdLine provides a similar functionality.

Thankfully, it is really easy to use.

Again, this example assumes you have a working knowledge of the previous EdLine examples, especially the basic one (Input Line Editor) and the example with custom keymap (Input Line Editor with Keymap).

Source Code

<source lang="c">

  1. include <stdio.h>
  2. include <io.h>
  1. include <dev/board.h>
  1. include <gorp/edline.h>
  1. define LINE_MAXLENGTH 100

EDLINE *el; char *buf;

int main(void) {

   u_long baud = 115200;
   NutRegisterDevice(&DEV_UART, 0, 0);
   freopen(DEV_UART_NAME, "w", stdout);
   freopen(DEV_UART_NAME, "r", stdin);
   _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
   puts("\nNut/OS EdLine Demo");
   puts("\nPlease enter some text: ");
   buf = malloc(LINE_MAXLENGTH);
   el = EdLineOpen(EDIT_MODE_ECHO | EDIT_MODE_HISTORY);
   EdLineRegisterKeymap(el, EdLineKeyMapVt100);
   for (;;) {
       EdLineRead(el, buf, LINE_MAXLENGTH);
       printf("You entered: %s\nYou can now enter something else or recall the previous entry via the history.\n\n", buf);
   }
   EdLineClose(el);
   return 0;

} </source>

Details

There are 2 major differences you should look out for. The first one is this:

<source lang="c">

   el = EdLineOpen(EDIT_MODE_ECHO | EDIT_MODE_HISTORY);

</source>

As you can see, we OR in another flag during the creation of our EdLine. This instructs Nut/OS to create an empty history and attach it to the EdLine.

You'll most likely not deal with this history structure directly but you should still be aware that it will use up some of your RAM to store user input. Make sure you can actually spare that RAM.

<source lang="c">

   for (;;) {
       EdLineRead(el, buf, LINE_MAXLENGTH);
       printf("You entered: %s\nYou can now enter something else or recall the previous entry via the history.\n\n", buf);
   }

</source>

In the previous examples we always read only one line. Demonstrating a history function with this would be pretty pointless, though, so we read lines in an endless loop to allow for as many inputs as you may want to make for testing this. Besides the structural change the code itself is still the same as in previous examples, though.

We are actually already done here. The EdLine will store the previous inputs and allow us to recall them. The only problem: It doesn't know how to handle the up/down keys. You can still cycle through inputs via ctrl+r and ctrl+v though.

Since we want up and down to work, though, we add another line in here:

<source lang="c">

   EdLineRegisterKeymap(el, EdLineKeyMapVt100);

</source>

From the keymap example we can already tell what's happening here: We are assigning a custom keymap to the EdLine. This keymap is able to handle the arrow keys, so you can now cycle through the history with the up and down keys or even move the cursor to the middle of the line and start typing there.

The EdLineKeyMapVt100 comes included with Nut/OS.

Now there is one potential problem, still... What if you already HAVE a custom keymap but still want to use this one?

Let's assume your keymap function looks like this:

<source lang="c"> int CustomKeyMap(int key, int *seq) {

   /* here goes your code */
 
   return key;

} </source>

You can integrate it with the Vt100 keymap like this:

<source lang="c"> int CustomKeyMap(int key, int *seq) {

   key = EdLineKeyMapVt100(key, seq);
   if (key != EDIT_KEY_IGNORE) {
       /* here goes your code */
   }
 
   return key;

} </source>

This looks a lot like the way the custom keymap example integrates the default keymap. That's because it is not really different in any way, it just integrates the VT100 instead of the default keymap.

Output

<source lang="text"> Nut/OS EdLine Demo

Please enter some text: My first line... You entered: My first line... You can now enter something else or recall the previous entry via the history.

And a second... You entered: And a second... You can now enter something else or recall the previous entry via the history.

Yay! You entered: Yay! You can now enter something else or recall the previous entry via the history.

My first line... again? Thanks, history functions! You entered: My first line... again? Thanks, history functions! You can now enter something else or recall the previous entry via the history.

My first line... again? Thanks, history functions! </source>