You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by je...@apache.org on 2019/04/10 10:45:27 UTC

[mynewt-core] branch master updated: sys/shell: Tab completion works more like bash

This is an automated email from the ASF dual-hosted git repository.

jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git


The following commit(s) were added to refs/heads/master by this push:
     new 73853ab  sys/shell: Tab completion works more like bash
73853ab is described below

commit 73853ab9aab553782ee416685bd1c7b7913007a6
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Tue Apr 9 13:26:47 2019 +0200

    sys/shell: Tab completion works more like bash
    
    If there are multiple matches but there is some common
    part that could be appended without printing all possibilities
    just append common part first.
    This allows to quickly use tab for completion of similar commands
    without polluting shell.
---
 sys/shell/src/shell.c | 85 ++++++++++++++++++++++++++++-----------------------
 1 file changed, 46 insertions(+), 39 deletions(-)

diff --git a/sys/shell/src/shell.c b/sys/shell/src/shell.c
index 1ee4470..335564e 100644
--- a/sys/shell/src/shell.c
+++ b/sys/shell/src/shell.c
@@ -592,67 +592,74 @@ complete_command(char *line, char *command_prefix,
                  int command_len, int module_idx,
                  console_append_char_cb append_char)
 {
-    const char *first_match = NULL;
-    int i, j, common_chars = -1, space = 0;
-    const struct shell_module *module;
+    int first_match = -1;
+    int match_count = 0;
+    int i, j, common_chars = -1;
+    const struct shell_cmd *commands;
 
-    module = &shell_modules[module_idx];
+    commands = shell_modules[module_idx].commands;
 
-    for (i = 0; module->commands[i].sc_cmd; i++) {
-        if (strncmp(command_prefix,
-            module->commands[i].sc_cmd, command_len)) {
+    for (i = 0; commands[i].sc_cmd; i++) {
+        if (0 != strncmp(command_prefix, commands[i].sc_cmd, command_len)) {
             continue;
         }
+        match_count++;
 
-        if (!first_match) {
-            first_match = module->commands[i].sc_cmd;
+        if (match_count == 1) {
+            first_match = i;
+            common_chars = strlen(commands[i].sc_cmd);
             continue;
         }
 
-        /* more commands match, print first match */
-        if (first_match && (common_chars < 0)) {
-            console_printf("\n");
-            console_printf("%s\n", first_match);
-            common_chars = strlen(first_match);
+        /*
+         * Common chars were already reduced to what was printed,
+         * no need to check more.
+         */
+        if (common_chars <= command_len) {
+            continue;
         }
-
-        /* cut common part of matching names */
-        for (j = 0; j < common_chars; j++) {
-            if (first_match[j] != module->commands[i].sc_cmd[j]) {
+        /* Check how many additional chars are same as first command's */
+        for (j = command_len; j < common_chars; j++) {
+            if (commands[first_match].sc_cmd[j] != commands[i].sc_cmd[j]) {
                 break;
             }
         }
-
         common_chars = j;
-
-        console_printf("%s\n", module->commands[i].sc_cmd);
     }
 
-    /* no match, do nothing */
-    if (!first_match) {
+    if (match_count == 0) {
         return;
     }
 
-    if (common_chars >= 0) {
-        /* multiple match, restore prompt */
-        print_prompt();
-        console_printf("%s", line);
-    } else {
-        common_chars = strlen(first_match);
-        space = 1;
-    }
-
-    /* complete common part */
-    for (i = command_len; i < common_chars; i++) {
-        if (!append_char(line, first_match[i])) {
-            return;
+    /* Additional characters could be appended */
+    if (common_chars > command_len) {
+        /* complete common part */
+        for (i = command_len; i < common_chars; i++) {
+            if (!append_char(line, (uint8_t)commands[first_match].sc_cmd[i])) {
+                return;
+            }
         }
+        if (match_count == 1) {
+            /* Whole word matched, append space */
+            append_char(line, ' ');
+        }
+        return;
     }
 
-    /* for convenience add space after command */
-    if (space) {
-        append_char(line, ' ');
+    /*
+     * More words match but there is nothing that could be appended
+     * list all possible matches.
+     */
+    console_printf("\n");
+    console_printf("%s\n", commands[first_match].sc_cmd);
+    for (i = first_match + 1; commands[i].sc_cmd; i++) {
+        if (0 == strncmp(command_prefix, commands[i].sc_cmd, command_len)) {
+            console_printf("%s\n", commands[i].sc_cmd);
+        }
     }
+    /* restore prompt */
+    print_prompt();
+    console_printf("%s", line);
 }
 
 static void