From 1b4050780b1a2514b228e7ab513268f3e41eef2e Mon Sep 17 00:00:00 2001 From: xin liang Date: Wed, 19 Jun 2024 11:18:13 +0800 Subject: [PATCH 1/3] Dev: ui_configure: Complete required parameters first --- crmsh/command.py | 19 +++++++++++++++++++ crmsh/ra.py | 4 ++++ crmsh/ui_configure.py | 3 +++ 3 files changed, 26 insertions(+) diff --git a/crmsh/command.py b/crmsh/command.py index 35b91425c2..77ff717fad 100644 --- a/crmsh/command.py +++ b/crmsh/command.py @@ -8,6 +8,8 @@ import inspect import re +import ctypes +import ctypes.util from . import help as help_module from . import ui_utils from . import log @@ -566,6 +568,10 @@ def complete(self, context, args): ''' ret = [] if self.completer is not None: + if sort_completion_inst is not None and sort_completion_inst.value == 0: + # Restore the original value of rl_sort_completion_matches + # before calling the completer again + sort_completion_inst.value = orig_sort_completion_value specs = inspect.getfullargspec(self.completer) if 'context' in specs.args: ret = self.completer([self.name] + args, context) @@ -591,3 +597,16 @@ def _check_args(fn, expected): if argnames != expected: raise ValueError(fn.__name__ + ": Expected method with signature " + repr(expected)) + + +readline_path = ctypes.util.find_library('readline') +sort_completion_inst = None +if readline_path: + # Inspired by + # https://stackoverflow.com/questions/31229708/python-gnu-readline-bindings-keep-my-sort-order + # Python readline module sort the completion result by + # alphabetical order by default. To archive the custom + # sort order, need to disable the sort_completion_matches + rl = ctypes.cdll.LoadLibrary(readline_path) + sort_completion_inst = ctypes.c_ulong.in_dll(rl, 'rl_sort_completion_matches') + orig_sort_completion_value = sort_completion_inst.value diff --git a/crmsh/ra.py b/crmsh/ra.py index f5bbdf4f27..15fd850a3e 100644 --- a/crmsh/ra.py +++ b/crmsh/ra.py @@ -410,6 +410,10 @@ def params(self, completion=False): "type": typ, "default": default, } + items = list(d.items()) + # Sort the dictionary by required and then alphabetically + items.sort(key=lambda item: (item[1]["required"] != '1', item[0])) + d = dict(items) return cache.store(ident, d) def actions(self): diff --git a/crmsh/ui_configure.py b/crmsh/ui_configure.py index 7915eb23c3..8a67b6345b 100644 --- a/crmsh/ui_configure.py +++ b/crmsh/ui_configure.py @@ -231,6 +231,9 @@ def _prim_params_completer(agent, args): return [] elif '=' in completing: return [] + if command.sort_completion_inst is not None: + # Set the value to 0 to use the costum sort order + command.sort_completion_inst.value = 0 return utils.filter_keys(agent.params(completion=True), args) From e9d76d657b84c95ec2297838e9f30ebf2a185def Mon Sep 17 00:00:00 2001 From: xin liang Date: Wed, 19 Jun 2024 11:34:28 +0800 Subject: [PATCH 2/3] Dev: ui_context: Don't append space when completion ends with equal sign --- crmsh/ui_context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crmsh/ui_context.py b/crmsh/ui_context.py index 0b71e6d0b8..5d9bc68f1b 100644 --- a/crmsh/ui_context.py +++ b/crmsh/ui_context.py @@ -229,7 +229,7 @@ def matching(word): ret = None # logging.debug("line:%s, text:%s, ret:%s, state:%s", repr(line), repr(text), ret, state) if not text or (ret and line.split()[-1].endswith(ret)): - if ret == "id=": + if ret.endswith('='): return ret return ret + ' ' return ret From 1ac113d1d06c3fed1f27b3db0856cf6827592082 Mon Sep 17 00:00:00 2001 From: xin liang Date: Wed, 26 Jun 2024 10:54:18 +0800 Subject: [PATCH 3/3] Dev: ra: Refine RAInfo.params interface to exclude some completion results --- crmsh/ra.py | 10 ++-------- crmsh/ui_configure.py | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/crmsh/ra.py b/crmsh/ra.py index 15fd850a3e..17c9c9d4ac 100644 --- a/crmsh/ra.py +++ b/crmsh/ra.py @@ -377,7 +377,7 @@ def mk_ra_node(self): self.broken_ra = False return self.ra_elem - def params(self, completion=False): + def params(self): ''' Construct a dict of dicts: parameters are keys and dictionary of attributes/values are values. Cached too. @@ -385,12 +385,6 @@ def params(self, completion=False): completion: If true, filter some (advanced) parameters out. ''' - if completion: - if self.mk_ra_node() is None: - return None - return [c.get("name") - for c in self.ra_elem.xpath("//parameters/parameter") - if c.get("name") and c.get("name") not in self.excluded_from_completion] ident = "ra_params-%s" % self if cache.is_cached(ident): return cache.retrieve(ident) @@ -399,7 +393,7 @@ def params(self, completion=False): d = {} for c in self.ra_elem.xpath("//parameters/parameter"): name = c.get("name") - if not name: + if not name or name in self.excluded_from_completion: continue required = c.get("required") if not (c.get("deprecated") or c.get("obsoletes")) else "0" unique = c.get("unique") diff --git a/crmsh/ui_configure.py b/crmsh/ui_configure.py index 8a67b6345b..39e71d302c 100644 --- a/crmsh/ui_configure.py +++ b/crmsh/ui_configure.py @@ -234,7 +234,7 @@ def _prim_params_completer(agent, args): if command.sort_completion_inst is not None: # Set the value to 0 to use the costum sort order command.sort_completion_inst.value = 0 - return utils.filter_keys(agent.params(completion=True), args) + return utils.filter_keys(agent.params(), args) def _prim_meta_completer(agent, args):