mirror of
https://github.com/nvbn/thefuck.git
synced 2025-03-20 17:48:41 +00:00
#N/A: Support editing command
This commit is contained in:
parent
96925fc737
commit
d0edea1baa
@ -22,6 +22,8 @@ def test_read_actions(patch_get_key):
|
|||||||
'\n',
|
'\n',
|
||||||
# Enter:
|
# Enter:
|
||||||
'\r',
|
'\r',
|
||||||
|
# Edit:
|
||||||
|
const.KEY_BACKSPACE, 'd',
|
||||||
# Ignored:
|
# Ignored:
|
||||||
'x', 'y',
|
'x', 'y',
|
||||||
# Up:
|
# Up:
|
||||||
@ -30,8 +32,9 @@ def test_read_actions(patch_get_key):
|
|||||||
const.KEY_DOWN, 'j',
|
const.KEY_DOWN, 'j',
|
||||||
# Ctrl+C:
|
# Ctrl+C:
|
||||||
const.KEY_CTRL_C, 'q'])
|
const.KEY_CTRL_C, 'q'])
|
||||||
assert (list(islice(ui.read_actions(), 8))
|
assert (list(islice(ui.read_actions(True), 10))
|
||||||
== [const.ACTION_SELECT, const.ACTION_SELECT,
|
== [const.ACTION_SELECT, const.ACTION_SELECT,
|
||||||
|
const.ACTION_EDIT, const.ACTION_EDIT,
|
||||||
const.ACTION_PREVIOUS, const.ACTION_PREVIOUS,
|
const.ACTION_PREVIOUS, const.ACTION_PREVIOUS,
|
||||||
const.ACTION_NEXT, const.ACTION_NEXT,
|
const.ACTION_NEXT, const.ACTION_NEXT,
|
||||||
const.ACTION_ABORT, const.ACTION_ABORT])
|
const.ACTION_ABORT, const.ACTION_ABORT])
|
||||||
|
@ -14,15 +14,18 @@ KEY_DOWN = _GenConst('↓')
|
|||||||
KEY_CTRL_C = _GenConst('Ctrl+C')
|
KEY_CTRL_C = _GenConst('Ctrl+C')
|
||||||
KEY_CTRL_N = _GenConst('Ctrl+N')
|
KEY_CTRL_N = _GenConst('Ctrl+N')
|
||||||
KEY_CTRL_P = _GenConst('Ctrl+P')
|
KEY_CTRL_P = _GenConst('Ctrl+P')
|
||||||
|
KEY_BACKSPACE = _GenConst('Backspace')
|
||||||
|
|
||||||
KEY_MAPPING = {'\x0e': KEY_CTRL_N,
|
KEY_MAPPING = {'\x0e': KEY_CTRL_N,
|
||||||
'\x03': KEY_CTRL_C,
|
'\x03': KEY_CTRL_C,
|
||||||
'\x10': KEY_CTRL_P}
|
'\x10': KEY_CTRL_P,
|
||||||
|
'\x7f': KEY_BACKSPACE}
|
||||||
|
|
||||||
ACTION_SELECT = _GenConst('select')
|
ACTION_SELECT = _GenConst('select')
|
||||||
ACTION_ABORT = _GenConst('abort')
|
ACTION_ABORT = _GenConst('abort')
|
||||||
ACTION_PREVIOUS = _GenConst('previous')
|
ACTION_PREVIOUS = _GenConst('previous')
|
||||||
ACTION_NEXT = _GenConst('next')
|
ACTION_NEXT = _GenConst('next')
|
||||||
|
ACTION_EDIT = _GenConst('edit')
|
||||||
|
|
||||||
ALL_ENABLED = _GenConst('All rules enabled')
|
ALL_ENABLED = _GenConst('All rules enabled')
|
||||||
DEFAULT_RULES = [ALL_ENABLED]
|
DEFAULT_RULES = [ALL_ENABLED]
|
||||||
|
@ -56,10 +56,19 @@ def show_corrected_command(corrected_command):
|
|||||||
reset=color(colorama.Style.RESET_ALL)))
|
reset=color(colorama.Style.RESET_ALL)))
|
||||||
|
|
||||||
|
|
||||||
def confirm_text(corrected_command):
|
def edit_part(show_edit):
|
||||||
|
if show_edit:
|
||||||
|
return '/{yellow}e{bold}d{normal}it'.format(
|
||||||
|
yellow=color(colorama.Fore.YELLOW),
|
||||||
|
bold=color(colorama.Style.BRIGHT),
|
||||||
|
normal=color(colorama.Style.NORMAL))
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
def confirm_text(corrected_command, show_edit):
|
||||||
sys.stderr.write(
|
sys.stderr.write(
|
||||||
(u'{prefix}{clear}{bold}{script}{reset}{side_effect} '
|
(u'{prefix}{clear}{bold}{script}{reset}{side_effect} '
|
||||||
u'[{green}enter{reset}/{blue}↑{reset}/{blue}↓{reset}'
|
u'[{green}enter{reset}{edit}{reset}/{blue}↑{reset}/{blue}↓{reset}'
|
||||||
u'/{red}ctrl+c{reset}]').format(
|
u'/{red}ctrl+c{reset}]').format(
|
||||||
prefix=const.USER_COMMAND_MARK,
|
prefix=const.USER_COMMAND_MARK,
|
||||||
script=corrected_command.script,
|
script=corrected_command.script,
|
||||||
@ -69,7 +78,8 @@ def confirm_text(corrected_command):
|
|||||||
green=color(colorama.Fore.GREEN),
|
green=color(colorama.Fore.GREEN),
|
||||||
red=color(colorama.Fore.RED),
|
red=color(colorama.Fore.RED),
|
||||||
reset=color(colorama.Style.RESET_ALL),
|
reset=color(colorama.Style.RESET_ALL),
|
||||||
blue=color(colorama.Fore.BLUE)))
|
blue=color(colorama.Fore.BLUE),
|
||||||
|
edit=edit_part(show_edit)))
|
||||||
|
|
||||||
|
|
||||||
def debug(msg):
|
def debug(msg):
|
||||||
|
@ -127,3 +127,10 @@ class Fish(Generic):
|
|||||||
history.write(entry.encode('utf-8'))
|
history.write(entry.encode('utf-8'))
|
||||||
else:
|
else:
|
||||||
history.write(entry)
|
history.write(entry)
|
||||||
|
|
||||||
|
def can_edit(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def edit_command(self, command):
|
||||||
|
"""Return the shell editable command"""
|
||||||
|
return 'commandline -r "' + command + '"'
|
||||||
|
@ -121,6 +121,14 @@ class Generic(object):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def can_edit(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# FIXME: this is just an attempt to make it work in bash or zsh
|
||||||
|
def edit_command(self, command):
|
||||||
|
"""Return the shell editable command"""
|
||||||
|
return 'export READLINE_LINE="' + command + '"'
|
||||||
|
|
||||||
def get_builtin_commands(self):
|
def get_builtin_commands(self):
|
||||||
"""Returns shells builtin commands."""
|
"""Returns shells builtin commands."""
|
||||||
return ['alias', 'bg', 'bind', 'break', 'builtin', 'case', 'cd',
|
return ['alias', 'bg', 'bind', 'break', 'builtin', 'case', 'cd',
|
||||||
|
@ -209,6 +209,7 @@ class CorrectedCommand(object):
|
|||||||
self.script = script
|
self.script = script
|
||||||
self.side_effect = side_effect
|
self.side_effect = side_effect
|
||||||
self.priority = priority
|
self.priority = priority
|
||||||
|
self.should_edit = False
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
"""Ignores `priority` field."""
|
"""Ignores `priority` field."""
|
||||||
@ -232,6 +233,9 @@ class CorrectedCommand(object):
|
|||||||
of running fuck in case fixed command fails again.
|
of running fuck in case fixed command fails again.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if self.should_edit:
|
||||||
|
self.script = shell.edit_command(self.script)
|
||||||
|
|
||||||
if settings.repeat:
|
if settings.repeat:
|
||||||
repeat_fuck = '{} --repeat {}--force-command {}'.format(
|
repeat_fuck = '{} --repeat {}--force-command {}'.format(
|
||||||
get_alias(),
|
get_alias(),
|
||||||
@ -241,6 +245,10 @@ class CorrectedCommand(object):
|
|||||||
else:
|
else:
|
||||||
return self.script
|
return self.script
|
||||||
|
|
||||||
|
def edit(self):
|
||||||
|
self.should_edit = True
|
||||||
|
return self
|
||||||
|
|
||||||
def run(self, old_cmd):
|
def run(self, old_cmd):
|
||||||
"""Runs command from rule for passed command.
|
"""Runs command from rule for passed command.
|
||||||
|
|
||||||
|
@ -3,21 +3,24 @@
|
|||||||
import sys
|
import sys
|
||||||
from .conf import settings
|
from .conf import settings
|
||||||
from .exceptions import NoRuleMatched
|
from .exceptions import NoRuleMatched
|
||||||
|
from .shells import shell
|
||||||
from .system import get_key
|
from .system import get_key
|
||||||
from .utils import get_alias
|
from .utils import get_alias
|
||||||
from . import logs, const
|
from . import logs, const
|
||||||
|
|
||||||
|
|
||||||
def read_actions():
|
def read_actions(can_edit):
|
||||||
"""Yields actions for pressed keys."""
|
"""Yields actions for pressed keys."""
|
||||||
while True:
|
while True:
|
||||||
key = get_key()
|
key = get_key()
|
||||||
|
|
||||||
# Handle arrows, j/k (qwerty), and n/e (colemak)
|
# Handle arrows, edit, j/k (qwerty), and n/e (colemak)
|
||||||
if key in (const.KEY_UP, const.KEY_CTRL_N, 'k', 'e'):
|
if key in (const.KEY_UP, const.KEY_CTRL_N, 'k', 'e'):
|
||||||
yield const.ACTION_PREVIOUS
|
yield const.ACTION_PREVIOUS
|
||||||
elif key in (const.KEY_DOWN, const.KEY_CTRL_P, 'j', 'n'):
|
elif key in (const.KEY_DOWN, const.KEY_CTRL_P, 'j', 'n'):
|
||||||
yield const.ACTION_NEXT
|
yield const.ACTION_NEXT
|
||||||
|
elif can_edit and key in (const.KEY_BACKSPACE, 'd'):
|
||||||
|
yield const.ACTION_EDIT
|
||||||
elif key in (const.KEY_CTRL_C, 'q'):
|
elif key in (const.KEY_CTRL_C, 'q'):
|
||||||
yield const.ACTION_ABORT
|
yield const.ACTION_ABORT
|
||||||
elif key in ('\n', '\r'):
|
elif key in ('\n', '\r'):
|
||||||
@ -78,18 +81,21 @@ def select_command(corrected_commands):
|
|||||||
logs.show_corrected_command(selector.value)
|
logs.show_corrected_command(selector.value)
|
||||||
return selector.value
|
return selector.value
|
||||||
|
|
||||||
logs.confirm_text(selector.value)
|
logs.confirm_text(selector.value, shell.can_edit())
|
||||||
|
|
||||||
for action in read_actions():
|
for action in read_actions(shell.can_edit()):
|
||||||
if action == const.ACTION_SELECT:
|
if action == const.ACTION_SELECT:
|
||||||
sys.stderr.write('\n')
|
sys.stderr.write('\n')
|
||||||
return selector.value
|
return selector.value
|
||||||
|
elif action == const.ACTION_EDIT:
|
||||||
|
sys.stderr.write('\n')
|
||||||
|
return selector.value.edit()
|
||||||
elif action == const.ACTION_ABORT:
|
elif action == const.ACTION_ABORT:
|
||||||
logs.failed('\nAborted')
|
logs.failed('\nAborted')
|
||||||
return
|
return
|
||||||
elif action == const.ACTION_PREVIOUS:
|
elif action == const.ACTION_PREVIOUS:
|
||||||
selector.previous()
|
selector.previous()
|
||||||
logs.confirm_text(selector.value)
|
logs.confirm_text(selector.value, shell.can_edit())
|
||||||
elif action == const.ACTION_NEXT:
|
elif action == const.ACTION_NEXT:
|
||||||
selector.next()
|
selector.next()
|
||||||
logs.confirm_text(selector.value)
|
logs.confirm_text(selector.value, shell.can_edit())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user