<commit_before>"""Module with shell specific actions, each shell class should
implement `from_shell`, `to_shell`, `app_alias`, `put_to_history` and `get_aliases`
methods.

"""
from collections import defaultdict
from psutil import Process
from subprocess import Popen, PIPE
from time import time
import io
import os
from .utils import DEVNULL, memoize


class Generic(object):

    def get_aliases(self):
        return {}

    def _expand_aliases(self, command_script):
        aliases = self.get_aliases()
        binary = command_script.split(' ')[0]
        if binary in aliases:
            return command_script.replace(binary, aliases[binary], 1)
        else:
            return command_script

    def from_shell(self, command_script):
        """Prepares command before running in app."""
        return self._expand_aliases(command_script)

    def to_shell(self, command_script):
        """Prepares command for running in shell."""
        return command_script

    def app_alias(self, fuck):
        return "alias {0}='TF_ALIAS={0} eval $(thefuck $(fc -ln -1))'".format(fuck)

    def _get_history_file_name(self):
        return ''

    def _get_history_line(self, command_script):
        return ''

    def put_to_history(self, command_script):
        """Puts command script to shell history."""
        history_file_name = self._get_history_file_name()
        if os.path.isfile(history_file_name):
            with open(history_file_name, 'a') as history:
                history.write(self._get_history_line(command_script))

    def _script_from_history(self, line):
        """Returns prepared history line.

        Should return a blank line if history line is corrupted or empty.

        """
        return ''

    def get_history(self):
        """Returns list of history entries."""
        history_file_name = self._get_history_file_name()
        if os.path.isfile(history_file_name):
            with io.open(history_file_name, 'r',
                         encoding='utf-8', errors='ignore') as history:
                for line in history:
                    prepared = self._script_from_history(line)\
                                   .strip()
                    if prepared:
                        yield prepared

    def and_(self, *commands):
        return u' && '.join(commands)


class Bash(Generic):
    def app_alias(self, fuck):
        return "TF_ALIAS={0} alias {0}='eval $(thefuck $(fc -ln -1));" \
               " history -r'".format(fuck)

    def _parse_alias(self, alias):
        name, value = alias.replace('alias ', '', 1).split('=', 1)
        if value[0] == value[-1] == '"' or value[0] == value[-1] == "'":
            value = value[1:-1]
        return name, value

    def get_aliases(self):
        proc = Popen('bash -ic alias', stdout=PIPE, stderr=DEVNULL,
                     shell=True)
        return dict(
            self._parse_alias(alias)
            for alias in proc.stdout.read().decode('utf-8').split('\n')
            if alias and '=' in alias)

    def _get_history_file_name(self):
        return os.environ.get("HISTFILE",
                              os.path.expanduser('~/.bash_history'))

    def _get_history_line(self, command_script):
        return u'{}\n'.format(command_script)

    def _script_from_history(self, line):
        print(line)
        return line


class Fish(Generic):

    def _get_overridden_aliases(self):
        overridden_aliases = os.environ.get('TF_OVERRIDDEN_ALIASES', '').strip()
        if overridden_aliases:
            return [alias.strip() for alias in overridden_aliases.split(',')]
        else:
            return ['cd', 'grep', 'ls', 'man', 'open']

    def app_alias(self, fuck):
        return ("set TF_ALIAS {0}\n"
                "function {0} -d 'Correct your previous console command'\n"
                "    set -l exit_code $status\n"
                "    set -l eval_script"
                " (mktemp 2>/dev/null ; or mktemp -t 'thefuck')\n"
                "    set -l fucked_up_commandd $history[1]\n"
                "    thefuck $fucked_up_commandd > $eval_script\n"
                "    . $eval_script\n"
                "    rm $eval_script\n"
                "    if test $exit_code -ne 0\n"<commit_msg>#301 Fix bash support on non-eng systems<commit_after>"""Module with shell specific actions, each shell class should
implement `from_shell`, `to_shell`, `app_alias`, `put_to_history` and `get_aliases`
methods.

"""
from collections import defaultdict
from psutil import Process
from subprocess import Popen, PIPE
from time import time
import io
import os
from .utils import DEVNULL, memoize


class Generic(object):

    def get_aliases(self):
        return {}

    def _expand_aliases(self, command_script):
        aliases = self.get_aliases()
        binary = command_script.split(' ')[0]
        if binary in aliases:
            return command_script.replace(binary, aliases[binary], 1)
        else:
            return command_script

    def from_shell(self, command_script):
        """Prepares command before running in app."""
        return self._expand_aliases(command_script)

    def to_shell(self, command_script):
        """Prepares command for running in shell."""
        return command_script

    def app_alias(self, fuck):
        return "alias {0}='TF_ALIAS={0} eval $(thefuck $(fc -ln -1))'".format(fuck)

    def _get_history_file_name(self):
        return ''

    def _get_history_line(self, command_script):
        return ''

    def put_to_history(self, command_script):
        """Puts command script to shell history."""
        history_file_name = self._get_history_file_name()
        if os.path.isfile(history_file_name):
            with open(history_file_name, 'a') as history:
                history.write(self._get_history_line(command_script))

    def _script_from_history(self, line):
        """Returns prepared history line.

        Should return a blank line if history line is corrupted or empty.

        """
        return ''

    def get_history(self):
        """Returns list of history entries."""
        history_file_name = self._get_history_file_name()
        if os.path.isfile(history_file_name):
            with io.open(history_file_name, 'r',
                         encoding='utf-8', errors='ignore') as history:
                for line in history:
                    prepared = self._script_from_history(line)\
                                   .strip()
                    if prepared:
                        yield prepared

    def and_(self, *commands):
        return u' && '.join(commands)


class Bash(Generic):
    def app_alias(self, fuck):
        return "TF_ALIAS={0} alias {0}='eval $(thefuck $(fc -ln -1));" \
               " history -r'".format(fuck)

    def _parse_alias(self, alias):
        name, value = alias.replace('alias ', '', 1).split('=', 1)
        if value[0] == value[-1] == '"' or value[0] == value[-1] == "'":
            value = value[1:-1]
        return name, value

    def get_aliases(self):
        proc = Popen('bash -ic alias', stdout=PIPE, stderr=DEVNULL,
                     shell=True)
        return dict(
            self._parse_alias(alias)
            for alias in proc.stdout.read().decode('utf-8').split('\n')
            if alias and '=' in alias)

    def _get_history_file_name(self):
        return os.environ.get("HISTFILE",
                              os.path.expanduser('~/.bash_history'))

    def _get_history_line(self, command_script):
        return u'{}\n'.format(command_script)

    def _script_from_history(self, line):
        return line


class Fish(Generic):

    def _get_overridden_aliases(self):
        overridden_aliases = os.environ.get('TF_OVERRIDDEN_ALIASES', '').strip()
        if overridden_aliases:
            return [alias.strip() for alias in overridden_aliases.split(',')]
        else:
            return ['cd', 'grep', 'ls', 'man', 'open']

    def app_alias(self, fuck):
        return ("set TF_ALIAS {0}\n"
                "function {0} -d 'Correct your previous console command'\n"
                "    set -l exit_code $status\n"
                "    set -l eval_script"
                " (mktemp 2>/dev/null ; or mktemp -t 'thefuck')\n"
                "    set -l fucked_up_commandd $history[1]\n"
                "    thefuck $fucked_up_commandd > $eval_script\n"
                "    . $eval_script\n"
                "    rm $eval_script\n"
                "    if test $exit_code -ne 0\n"
{'fraction_non_alphanumeric': 0.11734273956496179, 'fraction_numerical': 0.005761316872427984, 'mean_word_length': 2.1798130841121495, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7175357', 'n_tokens_mistral': 2599, 'n_tokens_neox': 2481, 'n_words': 638}