diff --git a/thefuck/shells/__init__.py b/thefuck/shells/__init__.py index 3da6497db..fe51bcf3f 100644 --- a/thefuck/shells/__init__.py +++ b/thefuck/shells/__init__.py @@ -10,6 +10,7 @@ from .tcsh import Tcsh from .zsh import Zsh from .powershell import Powershell +from .nushell import Nushell shells = {'bash': Bash, 'fish': Fish, @@ -17,7 +18,8 @@ 'csh': Tcsh, 'tcsh': Tcsh, 'powershell': Powershell, - 'pwsh': Powershell} + 'pwsh': Powershell, + 'nu': Nushell} def _get_shell_from_env(): diff --git a/thefuck/shells/nushell.py b/thefuck/shells/nushell.py new file mode 100644 index 000000000..2bdbc9284 --- /dev/null +++ b/thefuck/shells/nushell.py @@ -0,0 +1,72 @@ +from subprocess import Popen, PIPE +import os +import six +import sys +from .. import logs +from ..utils import DEVNULL +from .generic import Generic + + +class Nushell(Generic): + friendly_name = 'Nushell Shell' + + def get_aliases(self): + aliases = {} + command = 'help aliases | select name expansion | each { |row| $row.name + " ; " + $row.expansion } | str join (char nl)' + proc = Popen(['nu', '-l', '-c', command], stdout=PIPE, stderr=DEVNULL) + if proc.stdout is None: + return aliases + alias_out = proc.stdout.read().decode('utf-8').strip() + for alias in alias_out.split('\n'): + split_alias = alias.split(" ; ") + if len(split_alias) == 2: + name, value = split_alias + aliases[name] = value + return aliases + + def app_alias(self, alias_name): + return 'alias {0} = thefuck $"(history | last 1 | get command | get 0)"'.format(alias_name) + + def _get_history_file_name(self): + return os.path.expanduser('~/.config/nushell/history.txt') + + def _get_history_line(self, command_script): + return command_script + + def and_(self, *commands): + return u' and '.join(commands) + + def or_(self, *commands): + return u' or '.join(commands) + + def how_to_configure(self): + return self._create_shell_configuration( + content='alias fuck = thefuck $"(history | last 1 | get command | get 0)"', + path="$nu.config-path", + reload="source $nu.config-path" + ) + + def _script_from_history(self, line): + return line + + def put_to_history(self, command): + """Adds fixed command to shell history.""" + try: + history_file_name = self._get_history_file_name() + if os.path.isfile(history_file_name): + with open(history_file_name, 'a') as history: + entry = self._get_history_line(command) + if six.PY2: + history.write(entry.encode('utf-8')) + else: + history.write(entry) + except IOError: + logs.exception("Can't update history", sys.exc_info()) + + def _get_version(self): + """Returns the version of the current shell""" + proc = Popen(['nu', '--version'], stdout=PIPE, stderr=DEVNULL) + if proc.stdout: + return proc.stdout.read().decode('utf-8') + else: + raise Exception("Could not get the version of the current shell") diff --git a/thefuck/types.py b/thefuck/types.py index b3b64c35d..457790cf5 100644 --- a/thefuck/types.py +++ b/thefuck/types.py @@ -1,5 +1,7 @@ import os +import subprocess import sys +from .shells import Nushell from . import logs from .shells import shell from .conf import settings, load_source @@ -257,5 +259,10 @@ def run(self, old_cmd): # This depends on correct setting of PYTHONIOENCODING by the alias: logs.debug(u'PYTHONIOENCODING: {}'.format( os.environ.get('PYTHONIOENCODING', '!!not-set!!'))) - - sys.stdout.write(self._get_script()) + script = self._get_script() + if isinstance(shell, Nushell): + # TODO: fix for better option, the lack of '-l' flag + # means we lose any ENV that could be needed + subprocess.run(["nu", "-c", script]) + else: + sys.stdout.write(script)