Skip to content

Commit 40453bf

Browse files
authored
Merge pull request #16 from pymodbus-dev/14-fix-missing-files
14 fix missing files
2 parents 372796a + e30c43f commit 40453bf

File tree

4 files changed

+461
-2
lines changed

4 files changed

+461
-2
lines changed

pymodbus_repl/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""REPL (Read-Eval-Print Loop) tool for working with Modbus devices using the Pymodbus library."""
2-
__VERSION__ = "2.0.2"
2+
__VERSION__ = "2.0.3"
33

pymodbus_repl/lib/completer.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
"""Command Completion for pymodbus REPL. """
2+
from prompt_toolkit.application.current import get_app
3+
4+
# pylint: disable=missing-type-doc
5+
from prompt_toolkit.completion import Completer, Completion
6+
from prompt_toolkit.filters import Condition
7+
8+
from pymodbus_repl.lib.helper import get_commands, Command
9+
10+
11+
@Condition
12+
def has_selected_completion():
13+
"""Check for selected completion."""
14+
complete_state = get_app().current_buffer.complete_state
15+
return complete_state is not None and complete_state.current_completion is not None
16+
17+
18+
class CmdCompleter(Completer):
19+
"""Completer for Pymodbus REPL."""
20+
21+
def __init__(self, client=None, commands=None, ignore_case=True):
22+
"""Initialize.
23+
24+
:param client: Modbus Client
25+
:param commands: Commands to be added for Completion (list)
26+
:param ignore_case: Ignore Case while looking up for commands
27+
"""
28+
self._commands = commands or get_commands(client)
29+
self._commands["help"] = ""
30+
self._command_names = self._commands.keys()
31+
self.ignore_case = ignore_case
32+
33+
@property
34+
def commands(self):
35+
"""Return commands."""
36+
return self._commands
37+
38+
@property
39+
def command_names(self):
40+
"""Return command names."""
41+
return self._commands.keys()
42+
43+
def completing_command(self, words, word_before_cursor):
44+
"""Determine if we are dealing with supported command.
45+
46+
:param words: Input text broken in to word tokens.
47+
:param word_before_cursor: The current word before the cursor, \
48+
which might be one or more blank spaces.
49+
:return:
50+
"""
51+
return len(words) == 1 and len(word_before_cursor)
52+
53+
def completing_arg(self, words, word_before_cursor):
54+
"""Determine if we are currently completing an argument.
55+
56+
:param words: The input text broken into word tokens.
57+
:param word_before_cursor: The current word before the cursor, \
58+
which might be one or more blank spaces.
59+
:return: Specifies whether we are currently completing an arg.
60+
"""
61+
return len(words) > 1 and len(word_before_cursor)
62+
63+
def arg_completions(self, words, _word_before_cursor):
64+
"""Generate arguments completions based on the input."""
65+
cmd = words[0].strip()
66+
cmd = self._commands.get(cmd, None)
67+
return cmd if cmd else None
68+
69+
def _get_completions(self, word, word_before_cursor):
70+
"""Get completions."""
71+
if self.ignore_case:
72+
word_before_cursor = word_before_cursor.lower()
73+
return self.word_matches(word, word_before_cursor)
74+
75+
def word_matches(self, word, word_before_cursor):
76+
"""Match the word and word before cursor.
77+
78+
:param word: The input text broken into word tokens.
79+
:param word_before_cursor: The current word before the cursor, \
80+
which might be one or more blank spaces.
81+
:return: True if matched.
82+
83+
"""
84+
if self.ignore_case:
85+
word = word.lower()
86+
return word.startswith(word_before_cursor)
87+
88+
def get_completions(self, document, complete_event):
89+
"""Get completions for the current scope.
90+
91+
:param document: An instance of `prompt_toolkit.Document`.
92+
:param complete_event: (Unused).
93+
:return: Yields an instance of `prompt_toolkit.completion.Completion`.
94+
"""
95+
word_before_cursor = document.get_word_before_cursor(WORD=True)
96+
text = document.text_before_cursor.lstrip()
97+
words = document.text.strip().split()
98+
meta = None
99+
commands = []
100+
if not words:
101+
# yield commands
102+
pass
103+
if self.completing_command(words, word_before_cursor):
104+
commands = self._command_names
105+
c_meta = {
106+
k: v.help_text if isinstance(v, Command) else v
107+
for k, v in self._commands.items()
108+
}
109+
meta = lambda x: ( # pylint: disable=unnecessary-lambda-assignment
110+
x,
111+
c_meta.get(x, ""),
112+
)
113+
else:
114+
if not list(
115+
filter(lambda cmd: any(x == cmd for x in words), self._command_names)
116+
):
117+
# yield commands
118+
pass
119+
120+
if " " in text:
121+
command = self.arg_completions(words, word_before_cursor)
122+
if not command:
123+
return
124+
commands = list(command.get_completion())
125+
commands = list(
126+
filter(lambda cmd: not (any(cmd in x for x in words)), commands)
127+
)
128+
meta = command.get_meta
129+
for command in commands:
130+
if self._get_completions(command, word_before_cursor):
131+
_, display_meta = meta(command) if meta else ("", "")
132+
yield Completion(
133+
command, -len(word_before_cursor), display_meta=display_meta
134+
)

0 commit comments

Comments
 (0)