1
0
mirror of https://github.com/nvbn/thefuck.git synced 2024-10-05 18:31:10 +01:00

Add yarn_command_not_found rule

This addresses https://github.com/nvbn/thefuck/pull/607#issuecomment-283945505

The code was adapted from the `grunt_task_not_found` rule
This commit is contained in:
Joseph Frazier 2017-03-03 23:38:20 -05:00
parent ef5ff6210a
commit df5428c5e4
3 changed files with 145 additions and 0 deletions

View File

@ -249,6 +249,7 @@ using the matched rule and runs it. Rules enabled by default are as follows:
* `whois` – fixes `whois` command;
* `workon_doesnt_exists` – fixes `virtualenvwrapper` env name os suggests to create new.
* `yarn_alias` – fixes aliased `yarn` commands like `yarn ls`;
* `yarn_command_not_found` – fixes misspelled `yarn` commands;
Enabled by default only on specific platforms:

View File

@ -0,0 +1,111 @@
# -*- encoding: utf-8 -*-
from io import BytesIO
import pytest
from tests.utils import Command
from thefuck.rules.yarn_command_not_found import match, get_new_command
stderr = '''
error Command "{}" not found.
'''.format
yarn_help_stdout = b'''
Usage: yarn [command] [flags]
Options:
-h, --help output usage information
-V, --version output the version number
--verbose output verbose messages on internal operations
--offline trigger an error if any required dependencies are not available in local cache
--prefer-offline use network only if dependencies are not available in local cache
--strict-semver
--json
--ignore-scripts don't run lifecycle scripts
--har save HAR output of network traffic
--ignore-platform ignore platform checks
--ignore-engines ignore engines check
--ignore-optional ignore optional dependencies
--force ignore all caches
--no-bin-links don't generate bin links when setting up packages
--flat only allow one version of a package
--prod, --production [prod]
--no-lockfile don't read or generate a lockfile
--pure-lockfile don't generate a lockfile
--frozen-lockfile don't generate a lockfile and fail if an update is needed
--link-duplicates create hardlinks to the repeated modules in node_modules
--global-folder <path>
--modules-folder <path> rather than installing modules into the node_modules folder relative to the cwd, output them here
--cache-folder <path> specify a custom folder to store the yarn cache
--mutex <type>[:specifier] use a mutex to ensure only one yarn instance is executing
--no-emoji disable emoji in output
--proxy <host>
--https-proxy <host>
--no-progress disable progress bar
--network-concurrency <number> maximum number of concurrent network requests
Commands:
- access
- add
- bin
- cache
- check
- clean
- config
- generate-lock-entry
- global
- import
- info
- init
- install
- licenses
- link
- list
- login
- logout
- outdated
- owner
- pack
- publish
- remove
- run
- tag
- team
- unlink
- upgrade
- upgrade-interactive
- version
- versions
- why
Run `yarn help COMMAND` for more information on specific commands.
Visit https://yarnpkg.com/en/docs/cli/ to learn more about Yarn.
'''
@pytest.fixture(autouse=True)
def yarn_help(mocker):
patch = mocker.patch('thefuck.rules.yarn_command_not_found.Popen')
patch.return_value.stdout = BytesIO(yarn_help_stdout)
return patch
@pytest.mark.parametrize('command', [
Command('yarn whyy webpack', stderr=stderr('whyy'))])
def test_match(command):
assert match(command)
@pytest.mark.parametrize('command', [
Command('npm nuild', stderr=stderr('nuild')),
Command('yarn install')])
def test_not_match(command):
assert not match(command)
@pytest.mark.parametrize('command, result', [
(Command('yarn whyy webpack', stderr=stderr('whyy')), 'yarn why webpack')])
def test_get_new_command(command, result):
assert get_new_command(command) == result

View File

@ -0,0 +1,33 @@
import re
from subprocess import Popen, PIPE
from thefuck.utils import for_app, eager, get_closest
regex = re.compile(r'error Command "(.*)" not found.')
@for_app('yarn')
def match(command):
return regex.findall(command.stderr)
@eager
def _get_all_tasks():
proc = Popen(['yarn', '--help'], stdout=PIPE)
should_yield = False
for line in proc.stdout.readlines():
line = line.decode().strip()
if 'Commands:' in line:
should_yield = True
continue
if should_yield and '- ' in line:
yield line.split(' ')[-1]
def get_new_command(command):
misspelled_task = regex.findall(command.stderr)[0]
tasks = _get_all_tasks()
fixed = get_closest(misspelled_task, tasks)
return command.script.replace(' {}'.format(misspelled_task),
' {}'.format(fixed))