Skip to content

Commit

Permalink
WIP on bind -x
Browse files Browse the repository at this point in the history
  • Loading branch information
KingMob committed Dec 29, 2024
1 parent fca2f8a commit f277301
Show file tree
Hide file tree
Showing 5 changed files with 312 additions and 18 deletions.
23 changes: 19 additions & 4 deletions builtin/readline_osh.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
from frontend.py_readline import Readline
from core import sh_init
from display import ui
from state import Mem

_ = log

import sys # REMOVE ME

class ctx_Keymap(object):

Expand All @@ -46,11 +48,14 @@ def __exit__(self, type, value, traceback):
class Bind(vm._Builtin):
"""Interactive interface to readline bindings"""

def __init__(self, readline, errfmt):
# type: (Optional[Readline], ui.ErrorFormatter) -> None
def __init__(self, readline, errfmt, mem):
# type: (Optional[Readline], ui.ErrorFormatter, Mem) -> None
self.readline = readline
self.errfmt = errfmt
self.mem = mem
self.exclusive_flags = ["q", "u", "r", "x", "f"]

readline.set_bind_shell_command_hook(lambda *args: self.bind_shell_command_hook(*args))

def Run(self, cmd_val):
# type: (cmd_value.Argv) -> int
Expand Down Expand Up @@ -79,15 +84,15 @@ def Run(self, cmd_val):
# print("\tFound flag: {0} with tag: {1}".format(flag, attrs.attrs[flag].tag()))
if found:
self.errfmt.Print_(
"error: can only use one of the following flags at a time: -"
"error: Can only use one of the following flags at a time: -"
+ ", -".join(self.exclusive_flags),
blame_loc=cmd_val.arg_locs[0])
return 1
else:
found = True
if found and not arg_r.AtEnd():
self.errfmt.Print_(
"error: cannot mix bind commands with the following flags: -" +
"error: Too many arguments. Check your quoting. Also, you cannot mix normal bindings with the following flags: -" +
", -".join(self.exclusive_flags),
blame_loc=cmd_val.arg_locs[0])
return 1
Expand Down Expand Up @@ -142,6 +147,7 @@ def Run(self, cmd_val):
readline.unbind_keyseq(arg.r)

if arg.x is not None:
# print("arg.x: %s" % arg.x)
readline.bind_shell_command(arg.x)

if arg.X:
Expand Down Expand Up @@ -170,6 +176,15 @@ def Run(self, cmd_val):
return 1

return 0

def bind_shell_command_hook(self, cmd, line_buffer, point):
# type: (str, str, int) -> (str, str)
print("Executing cmd: %s" % cmd)
print("Setting READLINE_LINE to: %s" % line_buffer)
print("Setting READLINE_POINT to: %s" % point)
sys.stdout.flush()

return (line_buffer, str(point))


class History(vm._Builtin):
Expand Down
2 changes: 1 addition & 1 deletion core/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,7 @@ def Main(
b[builtin_i.forkwait] = process_osh.ForkWait(shell_ex)

# Interactive builtins depend on readline
b[builtin_i.bind] = readline_osh.Bind(readline, errfmt)
b[builtin_i.bind] = readline_osh.Bind(readline, errfmt, mem)
b[builtin_i.history] = readline_osh.History(readline, sh_files, errfmt,
mylib.Stdout())

Expand Down
22 changes: 17 additions & 5 deletions frontend/py_readline.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
if TYPE_CHECKING:
from core.completion import ReadlineCallback
from core.comp_ui import _IDisplay
from core.state import Mem


class Readline(object):
Expand Down Expand Up @@ -138,23 +139,34 @@ def unbind_keyseq(self, keyseq):
# type: (str) -> None
line_input.unbind_keyseq(keyseq)

def bind_shell_command(self, cmdseq):
def bind_shell_command(self, bindseq):
# type: (str) -> None
cmdseq_split = cmdseq.strip().split(":", 1)
import sys
print("default encoding: %s" % sys.getdefaultencoding())
cmdseq_split = bindseq.strip().split(":", 1)
if len(cmdseq_split) != 2:
raise ValueError("%s: missing colon separator" % cmdseq)
raise ValueError("%s: missing colon separator" % bindseq)

# Below checks prevent need to do so in C, but also ensure rl_generic_bind
# will not try to incorrectly xfree `cmd`/`data`, which doesn't belong to it
keyseq = cmdseq_split[0].rstrip()
if len(keyseq) <= 2:
raise ValueError("%s: empty binding key sequence" % keyseq)
raise ValueError("%s: empty/invalid key sequence" % keyseq)
if keyseq[0] != '"' or keyseq[-1] != '"':
raise ValueError("%s: missing double-quotes around the binding" % keyseq)
raise ValueError("%s: missing double-quotes around the key sequence" % keyseq)
keyseq = keyseq[1:-1]

cmd = cmdseq_split[1]
print("type of cmd string: %s" % type(cmd)) # REMOVE ME
line_input.bind_shell_command(keyseq, cmd)

def set_bind_shell_command_hook(self, hook):
# type: (Callable[[str, str, int], (str, str)]) -> None

if hook is None:
raise ValueError("missing bind shell command hook function")

line_input.set_bind_shell_command_hook(hook)


def MaybeGetReadline():
Expand Down
Loading

0 comments on commit f277301

Please sign in to comment.