Files
thefuck/thefuck/entrypoints/fix_command.py
T
Alexander 572d301bfe Run resolvers before rules with recording
Before consulting rules, fix_command now walks the resolver chain in
the fixed order learned-db -> history -> /nix/store/zc6fy62c341aibk36p4ywff7rf9wn4wx-ripgrep-15.2.0/bin:/run/wrappers/bin:/home/fujin/.nix-profile/bin:/nix/profile/bin:/home/fujin/.local/state/nix/profile/bin:/etc/profiles/per-user/fujin/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:/home/fujin/.local/share/JetBrains/Toolbox/scripts:/nix/store/rm982p6i9ry7rwq5jn638kdpv0a2331f-binutils-wrapper-2.46/bin:/nix/store/xabfaf6i4ry9r7jdg8rn7z56j34fjfgm-hyprland-qtutils-0.1.5/bin:/nix/store/mjgd7lbvp8rli365likrg9m4a5mmi5w4-pciutils-3.15.0/bin:/nix/store/paknc34adnxagnadmx2pg4c90hss8amv-pkgconf-wrapper-2.5.1/bin guess -> binary help:
history similarity runs before the disk-wide program-name guess per
the user requirement, and the binary's own --help is the last
automatic option before asking. Whichever resolver yields a script
is logged with its source, recorded via record(), and run through
the existing priority-0 CorrectedCommand block, so every automatic
fix is remembered; declines and aborts still record nothing and the
ask path is unchanged.
2026-09-13 20:59:16 +02:00

80 lines
2.9 KiB
Python

from pprint import pformat
import os
import sys
from difflib import SequenceMatcher
from .. import logs, types, const
from ..conf import settings
from ..corrector import get_corrected_commands
from ..exceptions import EmptyCommand
from ..learned import get_correction, guess_from_path, record
from ..resolvers.help_resolver import get_help_correction
from ..resolvers.history_resolver import get_history_correction
from ..ui import select_command
from ..utils import get_alias, get_all_executables
def _get_raw_command(known_args):
if known_args.force_command:
return [known_args.force_command]
elif not os.environ.get("TF_HISTORY"):
return known_args.command
else:
history = os.environ["TF_HISTORY"].split("\n")[::-1]
alias = get_alias()
executables = get_all_executables()
for command in history:
diff = SequenceMatcher(a=alias, b=command).ratio()
if diff < const.DIFF_WITH_ALIAS or command in executables:
return [command]
return []
def fix_command(known_args):
"""Fixes previous command. Used when `thefuck` called without arguments."""
settings.init(known_args)
with logs.debug_time("Total"):
logs.debug("Run with settings: {}".format(pformat(settings)))
raw_command = _get_raw_command(known_args)
try:
command = types.Command.from_raw_script(raw_command)
except EmptyCommand:
logs.debug("Empty command, nothing to do")
return
learned_script = get_correction(command.script)
if not learned_script:
learned_script = get_history_correction(command)
if learned_script:
logs.debug("Corrected from history: {}".format(
learned_script))
record(command.script, learned_script)
if not learned_script:
learned_script = guess_from_path(command.script)
if learned_script:
logs.debug("Guessed correction from $PATH: {}".format(
learned_script))
record(command.script, learned_script)
if not learned_script:
learned_script = get_help_correction(command.script)
if learned_script:
logs.debug("Corrected from binary help: {}".format(
learned_script))
record(command.script, learned_script)
if learned_script:
learned_cmd = types.CorrectedCommand(
script=learned_script, side_effect=None, priority=0
)
logs.show_corrected_command(learned_cmd)
learned_cmd.run(command)
return
corrected_commands = get_corrected_commands(command)
selected_command = select_command(corrected_commands)
if selected_command:
record(command.script, selected_command.script)
selected_command.run(command)
else:
sys.exit(1)