#611: Allow to configure alias automatically by calling fuck twice
This commit is contained in:
+28
-1
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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))
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user