diff --git a/tests/statistics/__init__.py b/tests/statistics/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/statistics/test_statistics.py b/tests/statistics/test_statistics.py new file mode 100644 index 0000000..086085f --- /dev/null +++ b/tests/statistics/test_statistics.py @@ -0,0 +1,62 @@ +import pytest +import thefuck.const as const +from thefuck.types import CorrectedCommand +from thefuck.statistics import CommandRecords + + + +class TestCommandRecords(): + def test_default(self): + default = const.DEFAULT_RECORDS_DICT + assert CommandRecords().statistics == default + + def test_clear_records(self): + default = const.DEFAULT_RECORDS_DICT + records = CommandRecords() + records.statistics = {"not clear": "value"} + records.clear_records() + assert records.statistics == default + assert not records.statistics == {"not clear": "value"} + + def test_add_applied_rules(self): + records = CommandRecords() + commands = [ + CorrectedCommand('ls', None, 100), + CorrectedCommand('git init', None, 200), + CorrectedCommand('fuck', None, 300)] + records.add_records(const.APPLIED_RULES, command_list = commands) + assert records.statistics[const.APPLIED_RULES]['ls'] == 1 + assert records.statistics[const.APPLIED_RULES]['git init'] == 1 + assert records.statistics[const.APPLIED_RULES]['fuck'] == 1 + + records.add_records(const.APPLIED_RULES, command_list = commands) + assert records.statistics[const.APPLIED_RULES]['ls'] == 2 + assert records.statistics[const.APPLIED_RULES]['git init'] == 2 + assert records.statistics[const.APPLIED_RULES]['fuck'] == 2 + + records.clear_records() + + def test_add_selected_rules(self): + records = CommandRecords() + command = CorrectedCommand('ls', None, 100) + records.add_records(const.SELECTED_RULES, command_single = command) + assert records.statistics[const.SELECTED_RULES]['ls'] == 1 + + records.add_records(const.SELECTED_RULES, command_single = command) + assert records.statistics[const.SELECTED_RULES]['ls'] == 2 + + records.clear_records() + + def test_add_no_fucks_given(self): + records = CommandRecords() + records.clear_records() + records.add_records(const.NO_FUCKS_GIVEN) + assert records.statistics[const.NO_FUCKS_GIVEN] == 1 + + records.add_records(const.NO_FUCKS_GIVEN) + assert records.statistics[const.NO_FUCKS_GIVEN] == 2 + + records.clear_records() + + + diff --git a/thefuck/const.py b/thefuck/const.py index 8d33926..cda0847 100644 --- a/thefuck/const.py +++ b/thefuck/const.py @@ -89,3 +89,12 @@ DIFF_WITH_ALIAS = 0.5 SHELL_LOGGER_SOCKET_ENV = 'SHELL_LOGGER_SOCKET' SHELL_LOGGER_LIMIT = 5 + +APPLIED_RULES = 'Applied Rules' +SELECTED_RULES = 'Selected Rules' +NO_FUCKS_GIVEN = 'No fucks given' +DEFAULT_RECORDS_DICT = { + APPLIED_RULES: {}, + SELECTED_RULES: {}, + NO_FUCKS_GIVEN: 0 +} \ No newline at end of file diff --git a/thefuck/statistics/__init__.py b/thefuck/statistics/__init__.py new file mode 100644 index 0000000..75bed0c --- /dev/null +++ b/thefuck/statistics/__init__.py @@ -0,0 +1 @@ +from .statistics import CommandRecords \ No newline at end of file diff --git a/thefuck/statistics/statistics.py b/thefuck/statistics/statistics.py new file mode 100644 index 0000000..d957342 --- /dev/null +++ b/thefuck/statistics/statistics.py @@ -0,0 +1,46 @@ +import json +import thefuck.const as const + + +class CommandRecords(object): + """Object to interact with 'records.json' data""" + def __init__(self): + """Opens 'records.json' if available""" + try: + with open("records.json", "r") as records_file: + self.statistics = json.load(records.file) + except: + self.statistics = const.DEFAULT_RECORDS_DICT + + + def add_records(self, category, **kwargs): + """Creates new records from arguments + and dumps information to 'records.json' + + :type commands: Iterable[thefuck.types.CorrectedCommand] + :type category: Const string + """ + if category == const.APPLIED_RULES: + for command in kwargs['command_list']: + try: + self.statistics[const.APPLIED_RULES][command.script] +=1 + except KeyError: + self.statistics[const.APPLIED_RULES].update({command.script: 1}) + + elif category == const.SELECTED_RULES: + command = kwargs['command_single'] + try: + self.statistics[const.SELECTED_RULES][command.script] += 1 + except KeyError: + self.statistics[const.SELECTED_RULES].update({command.script: 1}) + + elif category == const.NO_FUCKS_GIVEN: + self.statistics[const.NO_FUCKS_GIVEN] += 1 + + def clear_records(self): + self.statistics = const.DEFAULT_RECORDS_DICT + self.save() + + def save(self): + with open("records.json", "w") as records_file: + json.dump(self.statistics, records_file) \ No newline at end of file diff --git a/thefuck/ui.py b/thefuck/ui.py index 9c05db3..19f1dbe 100644 --- a/thefuck/ui.py +++ b/thefuck/ui.py @@ -6,6 +6,7 @@ from .exceptions import NoRuleMatched from .system import get_key from .utils import get_alias from . import logs, const +from .statistics import CommandRecords def read_actions(): @@ -67,21 +68,41 @@ def select_command(corrected_commands): :rtype: thefuck.types.CorrectedCommand | None """ + records = CommandRecords() try: selector = CommandSelector(corrected_commands) + records.add_records( + command_list = [command for command in corrected_commands], + category = const.APPLIED_RULES + ) + records.save() except NoRuleMatched: logs.failed('No fucks given' if get_alias() == 'fuck' else 'Nothing found') + records.add_records( + category = const.NO_FUCKS_GIVEN + ) + records.save() return if not settings.require_confirmation: logs.show_corrected_command(selector.value) + records.add_records( + command_single = selector.value, + category = const.SELECTED_RULES + ) + records.save() return selector.value logs.confirm_text(selector.value) for action in read_actions(): if action == const.ACTION_SELECT: + records.add_records( + command_single = selector.value, + category = const.SELECTED_RULES + ) + records.save() sys.stderr.write('\n') return selector.value elif action == const.ACTION_ABORT: @@ -93,3 +114,4 @@ def select_command(corrected_commands): elif action == const.ACTION_NEXT: selector.next() logs.confirm_text(selector.value) + \ No newline at end of file