Skip to content

Commit

Permalink
Add command_line_prompt
Browse files Browse the repository at this point in the history
  • Loading branch information
alejandrogallo committed Feb 25, 2019
1 parent 2cfa54a commit f54e255
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 1 deletion.
97 changes: 97 additions & 0 deletions papis/tui/widgets/command_line_prompt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from prompt_toolkit.filters import has_focus, Condition
from prompt_toolkit.layout.processors import BeforeInput
from prompt_toolkit.buffer import Buffer
from prompt_toolkit.completion import WordCompleter, Completer, Completion
from prompt_toolkit.layout.containers import (
HSplit, Window, WindowAlign, ConditionalContainer
)
from prompt_toolkit.layout.controls import (
BufferControl,
FormattedTextControl
)
from prompt_toolkit.application.current import get_app
import shlex


class Command:
"""
:param name: Name of the command
:type name: parameter_type
:param run: A callable object where the first argument is the cmd itself.
:type run: callable
"""
def __init__(self, name, run, aliases=[]):
assert(isinstance(name, str)), 'name should be a string'
assert(callable(run)), 'run should be callable'
assert(isinstance(aliases, list))
self.name = name
self.run = run
self.aliases = aliases

@property
def app(self):
return get_app()

@property
def names(self):
return [self.name] + self.aliases

def __call__(self, *args, **kwargs):
return self.run(self, *args, **kwargs)


class CommandLinePrompt(ConditionalContainer):
"""
A vim-like command line prompt widget.
It's supposed to be instantiated only once.
"""
instance = None
def __init__(self, commands=[]):
CommandLinePrompt.instance = self
assert(isinstance(commands, list))
for c in commands:
assert(isinstance(c, Command))
self.commands = commands
wc = WordCompleter(sum([c.names for c in commands], []))
self.buf = Buffer(
completer=wc, complete_while_typing=True
)
self.buf.text = ''
self.window = Window(
content=BufferControl(
buffer=self.buf,
input_processors=[BeforeInput(':')]
),
height=1
)
super(CommandLinePrompt, self).__init__(
content=self.window,
filter=has_focus(CommandLinePrompt.instance)
)

def trigger(self):
input_cmd = shlex.split(self.buf.text)
if not input_cmd:
return
name = input_cmd[0]
cmds = list(filter(lambda c: name in c.names, self.commands))

if len(cmds) > 1:
raise Exception('More than one command matches the input')
elif len(cmds) == 0:
raise Exception('No command found ({0})'.format(name))

input_cmd.pop(0)
return cmds[0](*input_cmd)

def clear(self):
self.text = ''

@property
def text(self):
return self.buf.text

@text.setter
def text(self, text):
self.buf.text = text

2 changes: 1 addition & 1 deletion tests/tui/test_command_line_prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ def test_commandlineprompt():
prompt.text = 'est'
e = prompt.trigger()
except Exception as e:
assert(str(e) == 'No command found')
assert(str(e) == 'No command found (est)')
else:
assert(False)

0 comments on commit f54e255

Please sign in to comment.