Magnificent app which corrects your previous console command
Essential data types representing commands, rules, corrections, and settings. These classes form the foundation of the correction system and provide structured data handling throughout the thefuck application.
Fundamental data structures representing commands and their execution results.
Command = namedtuple('Command', ('script', 'stdout', 'stderr'))
"""
Represents a command and its execution results.
Fields:
- script (str): The command string that was executed
- stdout (str): Standard output from command execution
- stderr (str): Standard error output from command execution
"""
class CorrectedCommand:
"""
Represents a corrected command with metadata.
Attributes:
- script (str): The corrected command string
- side_effect (callable): Optional function to execute when command runs
- priority (int): Priority for ordering multiple corrections
"""
def __init__(self, script, side_effect, priority):
"""
Initialize a corrected command.
Parameters:
- script (str): Corrected command string
- side_effect (callable or None): Function to call when executing
- priority (int): Priority value for ordering
"""
def __eq__(self, other):
"""
Compare commands (ignores priority field).
Parameters:
- other (CorrectedCommand): Other command to compare
Returns:
bool: True if script and side_effect match
"""
def __hash__(self):
"""
Hash function for use in sets and dictionaries.
Returns:
int: Hash value based on script and side_effect
"""Data structures for representing correction rules and their metadata.
Rule = namedtuple('Rule', ('name', 'match', 'get_new_command', 'enabled_by_default', 'side_effect', 'priority', 'requires_output'))
"""
Represents a correction rule with all its metadata.
Fields:
- name (str): Rule name/identifier
- match (callable): Function to test if rule applies to command
- get_new_command (callable): Function to generate corrected command
- enabled_by_default (bool): Whether rule is enabled by default
- side_effect (callable): Optional function to execute with correction
- priority (int): Rule priority for ordering
- requires_output (bool): Whether rule needs command output to function
"""
class RulesNamesList(list):
"""
Wrapper on top of list for storing rule names with special behavior.
Provides custom __contains__ behavior that checks rule names
rather than Rule objects directly.
"""
def __contains__(self, item):
"""
Check if rule is in the list by name.
Parameters:
- item (Rule): Rule object to check
Returns:
bool: True if rule name is in the list
"""Configuration management and settings representation.
class Settings(dict):
"""
Settings dictionary with attribute access support.
Extends dict to allow both dictionary-style and attribute-style access
to configuration values.
"""
def __getattr__(self, item):
"""
Get setting value as attribute.
Parameters:
- item (str): Setting name
Returns:
Any: Setting value or None if not found
"""
def update(self, **kwargs):
"""
Returns new settings with values from kwargs for unset settings.
Parameters:
- **kwargs: Setting key-value pairs
Returns:
Settings: New Settings object with updated values
"""Specialized collections for managing corrected commands.
class SortedCorrectedCommandsSequence:
"""
List-like collection/wrapper around generator that:
- Immediately gives access to the first commands through []
- Realizes generator and sorts commands on first access to other commands
- Provides lazy evaluation of command corrections
"""
def __init__(self, commands, settings):
"""
Initialize the sequence.
Parameters:
- commands (generator): Generator yielding CorrectedCommand objects
- settings (Settings): Application settings for debugging
"""
def __getitem__(self, item):
"""
Get command by index.
Parameters:
- item (int): Index of command to retrieve
Returns:
CorrectedCommand: Command at the specified index
"""
def __len__(self):
"""
Get number of commands (realizes generator if needed).
Returns:
int: Number of available commands
"""
def __bool__(self):
"""
Check if sequence has any commands.
Returns:
bool: True if sequence contains commands
"""
def __iter__(self):
"""
Iterate over commands (realizes generator if needed).
Returns:
iterator: Iterator over CorrectedCommand objects
"""from thefuck.types import Command, CorrectedCommand
# Create a command from execution results
command = Command(
script="git pussh origin main",
stdout="",
stderr="git: 'pussh' is not a git command. See 'git --help'."
)
# Create a corrected command
correction = CorrectedCommand(
script="git push origin main",
side_effect=None,
priority=1000
)
print(f"Original: {command.script}")
print(f"Correction: {correction.script}")
print(f"Error output: {command.stderr}")from thefuck.types import Settings
# Create settings with both dict and attribute access
settings = Settings({
'rules': ['git_push', 'sudo'],
'wait_command': 3,
'require_confirmation': True,
'debug': False
})
# Access as dictionary
print(settings['rules'])
# Access as attributes
print(settings.wait_command)
print(settings.debug)
# Update settings
new_settings = settings.update(debug=True, wait_command=5)
print(new_settings.debug) # True
print(settings.debug) # False (original unchanged)from thefuck.types import Rule, RulesNamesList
# Create a rule
def match_git_typo(command, settings):
return 'pussh' in command.script
def fix_git_typo(command, settings):
return command.script.replace('pussh', 'push')
rule = Rule(
name='git_push_typo',
match=match_git_typo,
get_new_command=fix_git_typo,
enabled_by_default=True,
side_effect=None,
priority=1000,
requires_output=False
)
# Work with rule lists
rules_list = RulesNamesList(['git_push', 'sudo', 'cd_mkdir'])
print(rule in rules_list) # Checks by rule.namefrom thefuck.types import SortedCorrectedCommandsSequence, CorrectedCommand
# Simulate a generator of corrections
def generate_corrections():
yield CorrectedCommand("git push origin main", None, 1000)
yield CorrectedCommand("git push origin master", None, 2000)
yield CorrectedCommand("git push --set-upstream origin main", None, 1500)
# Create sorted sequence
settings = Settings({'debug': False})
commands = SortedCorrectedCommandsSequence(generate_corrections(), settings)
# Access first command immediately (no full generation)
first = commands[0]
print(f"First correction: {first.script}")
# Access other commands (triggers full generation and sorting)
print(f"Total corrections: {len(commands)}")
for cmd in commands:
print(f" {cmd.script} (priority: {cmd.priority})")The data types work together to form the correction system:
This type system provides the foundation for thefuck's command correction pipeline.
Install with Tessl CLI
npx tessl i tessl/pypi-thefuck