#611: Allow to configure alias automatically by calling fuck twice

This commit is contained in:
Vladimir Iakovlev
2017-03-13 21:50:13 +01:00
parent 2379573cf2
commit 14a9cd85aa
19 changed files with 336 additions and 54 deletions
+28 -1
View File
@@ -91,6 +91,33 @@ def how_to_configure_alias(configuration_details):
"changes with {bold}{reload}{reset} or restart your shell.".format(
bold=color(colorama.Style.BRIGHT),
reset=color(colorama.Style.RESET_ALL),
**configuration_details))
**configuration_details._asdict()))
if configuration_details.can_configure_automatically:
print(
"Or run {bold}fuck{reset} second time for configuring"
" it automatically.".format(
bold=color(colorama.Style.BRIGHT),
reset=color(colorama.Style.RESET_ALL)))
print('More details - https://github.com/nvbn/thefuck#manual-installation')
def already_configured(configuration_details):
print(
"Seems like {bold}fuck{reset} alias already configured!\n"
"For applying changes run {bold}{reload}{reset}"
" or restart your shell.".format(
bold=color(colorama.Style.BRIGHT),
reset=color(colorama.Style.RESET_ALL),
reload=configuration_details.reload))
def configured_successfully(configuration_details):
print(
"{bold}fuck{reset} alias configured successfully!\n"
"For applying changes run {bold}{reload}{reset}"
" or restart your shell.".format(
bold=color(colorama.Style.BRIGHT),
reset=color(colorama.Style.RESET_ALL),
reload=configuration_details.reload))
-10
View File
@@ -46,16 +46,6 @@ def print_alias():
print(shell.app_alias(alias))
def how_to_configure_alias():
"""Shows useful information about how-to configure alias.
It'll be only visible when user type fuck and when alias isn't configured.
"""
settings.init()
logs.how_to_configure_alias(shell.how_to_configure())
def main():
parser = ArgumentParser(prog='thefuck')
version = get_installation_info().version
+86
View File
@@ -0,0 +1,86 @@
# Initialize output before importing any module, that can use colorama.
from .system import init_output
init_output()
import os # noqa: E402
from psutil import Process # noqa: E402
from . import logs # noqa: E402
from .shells import shell # noqa: E402
from .conf import settings # noqa: E402
from .system import Path # noqa: E402
from .utils import get_cache_dir # noqa: E402
def _get_shell_pid():
"""Returns parent process pid."""
proc = Process(os.getpid())
try:
return proc.parent().pid
except TypeError:
return proc.parent.pid
def _get_not_configured_usage_tracker_path():
"""Returns path of special file where we store latest shell pid."""
return Path(get_cache_dir()).joinpath('thefuck.last_not_configured_run')
def _record_first_run():
"""Records shell pid to tracker file."""
with _get_not_configured_usage_tracker_path().open('w') as tracker:
tracker.write(str(_get_shell_pid()))
def _is_second_run():
"""Returns `True` when we know that `fuck` called second time."""
tracker_path = _get_not_configured_usage_tracker_path()
if not tracker_path.exists() or not shell.get_history()[-1] == 'fuck':
return False
current_pid = _get_shell_pid()
with tracker_path.open('r') as tracker:
return tracker.read() == str(current_pid)
def _is_already_configured(configuration_details):
"""Returns `True` when alias already in shell config."""
path = Path(configuration_details.path).expanduser()
with path.open('r') as shell_config:
return configuration_details.content in shell_config.read()
def _configure(configuration_details):
"""Adds alias to shell config."""
path = Path(configuration_details.path).expanduser()
with path.open('a') as shell_config:
shell_config.write('\n')
shell_config.write(configuration_details.content)
shell_config.write('\n')
def main():
"""Shows useful information about how-to configure alias on a first run
and configure automatically on a second.
It'll be only visible when user type fuck and when alias isn't configured.
"""
settings.init()
configuration_details = shell.how_to_configure()
if (
configuration_details and
configuration_details.can_configure_automatically
):
if _is_already_configured(configuration_details):
logs.already_configured(configuration_details)
return
elif _is_second_run():
_configure(configuration_details)
logs.configured_successfully(configuration_details)
return
else:
_record_first_run()
logs.how_to_configure_alias(configuration_details)
+4 -5
View File
@@ -45,8 +45,7 @@ class Bash(Generic):
else:
config = 'bash config'
return {
'content': 'eval $(thefuck --alias)',
'path': config,
'reload': u'source {}'.format(config),
}
return self._create_shell_configuration(
content='eval $(thefuck --alias)',
path=config,
reload=u'source {}'.format(config))
+4 -5
View File
@@ -67,11 +67,10 @@ class Fish(Generic):
return u'; and '.join(commands)
def how_to_configure(self):
return {
'content': r"eval (thefuck --alias | tr '\n' ';')",
'path': '~/.config/fish/config.fish',
'reload': 'fish',
}
return self._create_shell_configuration(
content=r"eval (thefuck --alias | tr '\n' ';')",
path='~/.config/fish/config.fish',
reload='fish')
def put_to_history(self, command):
try:
+13
View File
@@ -2,8 +2,14 @@ import io
import os
import shlex
import six
from collections import namedtuple
from ..utils import memoize
from ..conf import settings
from ..system import Path
ShellConfiguration = namedtuple('ShellConfiguration', (
'content', 'path', 'reload', 'can_configure_automatically'))
class Generic(object):
@@ -116,3 +122,10 @@ class Generic(object):
'shift', 'shopt', 'source', 'suspend', 'test', 'times', 'trap',
'type', 'typeset', 'ulimit', 'umask', 'unalias', 'unset',
'until', 'wait', 'while']
def _create_shell_configuration(self, content, path, reload):
return ShellConfiguration(
content=content,
path=path,
reload=reload,
can_configure_automatically=Path(path).expanduser().exists())
+6 -6
View File
@@ -1,4 +1,4 @@
from .generic import Generic
from .generic import Generic, ShellConfiguration
class Powershell(Generic):
@@ -18,8 +18,8 @@ class Powershell(Generic):
return u' -and '.join('({0})'.format(c) for c in commands)
def how_to_configure(self):
return {
'content': 'iex "thefuck --alias"',
'path': '$profile',
'reload': '& $profile',
}
return ShellConfiguration(
content='iex "thefuck --alias"',
path='$profile',
reload='& $profile',
can_configure_automatically=False)
+4 -5
View File
@@ -31,8 +31,7 @@ class Tcsh(Generic):
return u'#+{}\n{}\n'.format(int(time()), command_script)
def how_to_configure(self):
return {
'content': 'eval `thefuck --alias`',
'path': '~/.tcshrc',
'reload': 'tcsh',
}
return self._create_shell_configuration(
content='eval `thefuck --alias`',
path='~/.tcshrc',
reload='tcsh')
+4 -5
View File
@@ -45,8 +45,7 @@ class Zsh(Generic):
return ''
def how_to_configure(self):
return {
'content': 'eval $(thefuck --alias)',
'path': '~/.zshrc',
'reload': 'source ~/.zshrc',
}
return self._create_shell_configuration(
content='eval $(thefuck --alias)',
path='~/.zshrc',
reload='source ~/.zshrc')
+17 -16
View File
@@ -178,6 +178,21 @@ def for_app(*app_names, **kwargs):
return decorator(_for_app)
def get_cache_dir():
default_xdg_cache_dir = os.path.expanduser("~/.cache")
cache_dir = os.getenv("XDG_CACHE_HOME", default_xdg_cache_dir)
# Ensure the cache_path exists, Python 2 does not have the exist_ok
# parameter
try:
os.makedirs(cache_dir)
except OSError:
if not os.path.isdir(cache_dir):
raise
return cache_dir
def cache(*depends_on):
"""Caches function result in temporary file.
@@ -194,21 +209,6 @@ def cache(*depends_on):
except OSError:
return '0'
def _get_cache_path():
default_xdg_cache_dir = os.path.expanduser("~/.cache")
cache_dir = os.getenv("XDG_CACHE_HOME", default_xdg_cache_dir)
cache_path = Path(cache_dir).joinpath('thefuck').as_posix()
# Ensure the cache_path exists, Python 2 does not have the exist_ok
# parameter
try:
os.makedirs(cache_dir)
except OSError:
if not os.path.isdir(cache_dir):
raise
return cache_path
@decorator
def _cache(fn, *args, **kwargs):
if cache.disabled:
@@ -219,7 +219,8 @@ def cache(*depends_on):
key = '{}.{}'.format(fn.__module__, repr(fn).split('at')[0])
etag = '.'.join(_get_mtime(name) for name in depends_on)
cache_path = _get_cache_path()
cache_dir = get_cache_dir()
cache_path = Path(cache_dir).joinpath('thefuck').as_posix()
try:
with closing(shelve.open(cache_path)) as db: