This is an automated email from Gerrit. Tarek BOCHKATI (tarek.bouchk...@gmail.com) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/6311
-- gerrit commit 57414fb25b54d4a0454866137101f51c86b0d9dd Author: Tarek BOCHKATI <tarek.bouchk...@gmail.com> Date: Wed Jun 9 22:47:46 2021 +0100 telnet: add path auto-completion [RFC/WIP] limitations: give path hints only if the string starts with '/', './' (maybe '~/', PS: tcl glob do not support it) no windows support incomplete double quote support clean-up c code Change-Id: Iadd859d7c3ea7b090a9f7cb668b7a3eb30927444 Signed-off-by: Tarek BOCHKATI <tarek.bouchk...@gmail.com> diff --git a/src/server/startup.tcl b/src/server/startup.tcl index 447b57c..c9fc2d4 100644 --- a/src/server/startup.tcl +++ b/src/server/startup.tcl @@ -24,10 +24,11 @@ proc POST {args} { prevent_cps } proc Host: {args} { prevent_cps } # list of commands we don't want to appear in autocomplete +lappend _telnet_autocomplete_skip _telnet_cmd_autocomplete_helper +lappend _telnet_autocomplete_skip _telnet_path_autocomplete_helper lappend _telnet_autocomplete_skip _telnet_autocomplete_helper -# helper for telnet autocomplete -proc _telnet_autocomplete_helper pattern { +proc _telnet_cmd_autocomplete_helper pattern { set cmds [info commands $pattern] # skip matches in variable '_telnet_autocomplete_skip' @@ -39,3 +40,47 @@ proc _telnet_autocomplete_helper pattern { return [lsort $cmds] } + +proc _telnet_path_autocomplete_helper pattern { + # TODO: IMPORTANT: quoted paths are not supported correctly + + # get the last argument + # FIXME linux accepts double quotes in file names + + if {[regexp -indices {["'][^"']+$} $pattern indices]} { + set offset [expr [lindex $indices 0] + 1] + } elseif {[regexp -indices {\S+$} $pattern indices]} { + set offset [lindex $indices 0] + } else { + return {} + } + + set path_prefix [string range $pattern 0 [expr $offset - 1]] + set path_pattern [string range $pattern $offset end] + + # TODO check windows support + + set paths [glob -nocomplain $path_pattern] + + # if it is a directorry append '/' + foreach path $paths { + if {[file isdirectory $path]} { + append path / + } + + lappend completions $path_prefix$path + } + + return [lsort $completions] +} + +# helper for telnet autocomplete +proc _telnet_autocomplete_helper pattern { + set cmds [_telnet_cmd_autocomplete_helper $pattern] + + if {[llength $cmds] > 0} { + return $cmds + } + + return [_telnet_path_autocomplete_helper $pattern] +} diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 2ad3791..faf656c 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -497,12 +497,14 @@ static void telnet_auto_complete(struct connection *connection) char *name = (char *)Jim_GetString(elem, NULL); /* validate the command */ + /* TODO: rename variable with cmd prefix/suffix, because it contains paths as well */ bool ignore_cmd = false; Jim_Cmd *jim_cmd = Jim_GetCommand(command_context->interp, elem, JIM_NONE); if (!jim_cmd) { /* Why we are here? Let's ignore it! */ - ignore_cmd = true; + /* TODO: maybe the TCL knows better + * ignore_cmd = true; */ } else if (jimcmd_is_oocd_command(jim_cmd)) { struct command *cmd = jimcmd_privdata(jim_cmd); @@ -545,16 +547,19 @@ static void telnet_auto_complete(struct connection *connection) /* end of command filtering */ /* proceed with auto-completion */ - if (list_empty(&matches)) + if (list_empty(&matches)) { telnet_bell(connection); - else if (common_len == usr_cmd_len && list_is_singular(&matches) && t_con->line_cursor == t_con->line_size) + } else if (common_len == usr_cmd_len && list_is_singular(&matches) && t_con->line_cursor == t_con->line_size) { telnet_insert(connection, " ", 1); - else if (common_len > usr_cmd_len) { + } else if (common_len > usr_cmd_len) { int completion_size = common_len - usr_cmd_len; if (telnet_insert(connection, first_match + usr_cmd_len, completion_size)) { /* in bash this extra space is only added when the cursor in at the end of line */ - if (list_is_singular(&matches) && t_con->line_cursor == t_con->line_size) - telnet_insert(connection, " ", 1); + if (list_is_singular(&matches) && t_con->line_cursor == t_con->line_size) { + /* do not insert a whitespace if it's a directory */ + if (first_match[common_len - 1] != '/') + telnet_insert(connection, " ", 1); + } } } else if (!list_is_singular(&matches)) { telnet_write(connection, "\n\r", 2); --