* [spp] [PATCH] controller: fix bug of path completion
@ 2019-01-30 6:02 ogawa.yasufumi
0 siblings, 0 replies; only message in thread
From: ogawa.yasufumi @ 2019-01-30 6:02 UTC (permalink / raw)
To: ferruh.yigit, spp, ogawa.yasufumi
From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
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 <ogawa.yasufumi@lab.ntt.co.jp>
---
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
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2019-01-30 6:04 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-30 6:02 [spp] [PATCH] controller: fix bug of path completion ogawa.yasufumi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).