From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from bcmv-tmail01.ecl.ntt.co.jp (bcmv-tmail01.ecl.ntt.co.jp [124.146.185.148]) by dpdk.org (Postfix) with ESMTP id 95F7E1B1DD for ; Wed, 30 Jan 2019 07:04:40 +0100 (CET) Received: from bcmv-ns01.ecl.ntt.co.jp (bcmv-ns01.ecl.ntt.co.jp [129.60.83.123]) by bcmv-tmail01.ecl.ntt.co.jp (8.14.4/8.14.4) with ESMTP id x0U64bbM010259; Wed, 30 Jan 2019 15:04:37 +0900 Received: from bcmv-ns01.ecl.ntt.co.jp (localhost [127.0.0.1]) by bcmv-ns01.ecl.ntt.co.jp (Postfix) with ESMTP id 81638138; Wed, 30 Jan 2019 15:04:37 +0900 (JST) Received: from localhost.localdomain (lobster.nslab.ecl.ntt.co.jp [129.60.13.95]) by bcmv-ns01.ecl.ntt.co.jp (Postfix) with ESMTP id 66044C7; Wed, 30 Jan 2019 15:04:37 +0900 (JST) From: ogawa.yasufumi@lab.ntt.co.jp To: ferruh.yigit@intel.com, spp@dpdk.org, ogawa.yasufumi@lab.ntt.co.jp Date: Wed, 30 Jan 2019 15:02:28 +0900 Message-Id: <1548828148-6392-1-git-send-email-ogawa.yasufumi@lab.ntt.co.jp> X-Mailer: git-send-email 2.7.4 X-TM-AS-MML: disable Subject: [spp] [PATCH] controller: fix bug of path completion X-BeenThere: spp@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Soft Patch Panel List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 30 Jan 2019 06:04:41 -0000 From: Yasufumi Ogawa SPP CLI uses `shell_lib.compl_common()` to completion path for commands referring a file or a directory, but does not work correctly if the path includes '-'. It is because Cmd unexpectedly treats '-' as a delimiter as same as '/'. This patch is to fix this issue by correcting path including '-' while serching candidates. Signed-off-by: Yasufumi Ogawa --- src/controller/shell_lib/common.py | 120 +++++++++++++++++++++++++++++++------ 1 file changed, 102 insertions(+), 18 deletions(-) diff --git a/src/controller/shell_lib/common.py b/src/controller/shell_lib/common.py index 87263d0..447584b 100644 --- a/src/controller/shell_lib/common.py +++ b/src/controller/shell_lib/common.py @@ -5,6 +5,9 @@ import os from .. import spp_common +CHAR_EXCEPT = '-' + + def decorate_dir(curdir, filelist): """Add '/' the end of dirname for path completion @@ -21,39 +24,91 @@ def decorate_dir(curdir, filelist): def compl_common(text, line, ftype=None): - """File path completion for 'complete_*' method + """File path completion for 'complete_*' method. - This method is called from 'complete_*' to complete 'do_*'. - 'text' and 'line' are arguments of 'complete_*'. + This is a helper method for `complete_*` methods implemented in a + sub class of Cmd. `text` and `line` are arguments of `complete_*`. - `complete_*` is a member method of builtin Cmd class and - called if tab key is pressed in a command defiend by 'do_*'. - 'text' and 'line' are contents of command line. - For example, if you type tab at 'command arg1 ar', - last token 'ar' is assigned to 'text' and whole line - 'command arg1 ar' is assigned to 'line'. + `complete_*` is a member method of Cmd class and called if TAB key + is pressed in a command defiend by `do_*`. `text` and `line` are + contents of command line. For example, if you type TAB after + 'command arg1 ar', the last token 'ar' is assigned to 'text' and + whole line 'command arg1 ar' is assigned to 'line'. + + `ftype` is used to filter the result of completion. If you give 'py' + or 'python', the result only includes python scripts. + * 'py' or 'python': python scripts. + * 'log': log files of extension is 'log'. + * 'directory': get only directories, excludes files. + * 'file' get only files, excludes directories. NOTE: - If tab is typed after '/', empty text '' is assigned to - 'text'. For example 'aaa b/', text is not 'b/' but ''. + Cmd treats '/' and '-' as special characters. If you type TAB after + them, empty text '' is assigned to `text`. For example after + 'aaa b/', `text` is not 'b/' but ''. It means that completion might + not work correctly if given path includes these characters while + getting candidates with `os.getcwd()` or `os.listdir()`. + + This method is implemented to complete the path correctly even if + special characters are included. """ + # spp_common.logger.debug('completion, text = "%s"' % text) + + tokens = line.split(' ') + target = tokens[-1] # get argument given by user + if text == '': # tab is typed after command name or '/' - tokens = line.split(' ') - target_dir = tokens[-1] # get dirname for competion + + # spp_common.logger.debug("tokens: %s" % tokens) + # spp_common.logger.debug("target: '%s'" % target) + + # check chars Cmd treats as delimiter + if target.endswith(CHAR_EXCEPT): + target_dir = '/'.join(target.split('/')[0:-1]) + target = target.split('/')[-1] + else: + target_dir = target + + # spp_common.logger.debug("text is '', tokens: '%s'" % tokens) + # spp_common.logger.debug("text is '', target_dir: '%s'" % target_dir) + if target_dir == '': # no dirname means current dir - res = decorate_dir( + decorated_list = decorate_dir( '.', os.listdir(os.getcwd())) else: # after '/' - res = decorate_dir( + decorated_list = decorate_dir( target_dir, os.listdir(target_dir)) + + # spp_common.logger.debug('decorated_list: %s' % decorated_list) + + res = [] + if target.endswith(CHAR_EXCEPT): + for d in decorated_list: + if d.startswith(target): + + nof_delims_t = target.count(CHAR_EXCEPT) + nof_delims_d = d.count(CHAR_EXCEPT) + idx = nof_delims_d - nof_delims_t + 1 + d = d.split(CHAR_EXCEPT)[(-idx):] + d = CHAR_EXCEPT.join(d) + + res.append(d) + else: + res = decorated_list + else: # tab is typed in the middle of a word - tokens = line.split(' ') - target = tokens[-1] # target dir for completion + + # spp_common.logger.debug("text is not '', tokens: '%s'" % tokens) + # spp_common.logger.debug("text is not '', target: '%s'" % target) if '/' in target: # word is a path such as 'path/to/file' seg = target.split('/')[-1] # word to be completed target_dir = '/'.join(target.split('/')[0:-1]) + + # spp_common.logger.debug('word be completed: "%s"' % seg) + # spp_common.logger.debug('target_dir: "%s"' % target_dir) + else: seg = text target_dir = os.getcwd() @@ -62,7 +117,31 @@ def compl_common(text, line, ftype=None): for t in os.listdir(target_dir): if t.find(seg) == 0: # get words matched with 'seg' matched.append(t) - res = decorate_dir(target_dir, matched) + decorated_list = decorate_dir(target_dir, matched) + + # spp_common.logger.debug('decorated_list: %s' % decorated_list) + + res = [] + target_last = target.split('/')[-1] + if CHAR_EXCEPT in target_last: + for d in decorated_list: + if d.startswith(seg): + + # spp_common.logger.debug('pd: %s' % d) + + nof_delims_t = target_last.count(CHAR_EXCEPT) + nof_delims_d = d.count(CHAR_EXCEPT) + idx = nof_delims_d - nof_delims_t + 1 + d = d.split(CHAR_EXCEPT)[(-idx):] + d = CHAR_EXCEPT.join(d) + + # spp_common.logger.debug('ad: %s' % d) + + res.append(d) + else: + res = decorated_list + + # spp_common.logger.debug('res: %s' % res) if ftype is not None: # filtering by ftype completions = [] @@ -74,6 +153,10 @@ def compl_common(text, line, ftype=None): for fn in res: if fn[-3:] == '.py': completions.append(fn) + elif ftype == 'log': + for fn in res: + if fn[-3:] == '.log': + completions.append(fn) elif ftype == 'file': for fn in res: if fn[-1] != '/': @@ -82,6 +165,7 @@ def compl_common(text, line, ftype=None): completions = res else: completions = res + return completions -- 2.7.4