[
  {
    "path": ".devcontainer/Dockerfile",
    "content": "# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.163.1/containers/python-3/.devcontainer/base.Dockerfile\n\n# [Choice] Python version: 3, 3.9, 3.8, 3.7, 3.6\nARG VARIANT=\"3\"\nFROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}\n\n# [Optional] If your pip requirements rarely change, uncomment this section to add them to the image.\nCOPY requirements.txt /tmp/pip-tmp/\nRUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \\\n   && rm -rf /tmp/pip-tmp\n"
  },
  {
    "path": ".devcontainer/devcontainer.json",
    "content": "// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:\n// https://github.com/microsoft/vscode-dev-containers/tree/v0.163.1/containers/python-3\n{\n\t\"name\": \"Python 3\",\n\t\"build\": {\n\t\t\"dockerfile\": \"Dockerfile\",\n\t\t\"context\": \"..\"\n\t},\n\n\t// Set *default* container specific settings.json values on container create.\n\t\"settings\": {\n\t\t\"terminal.integrated.profiles.linux\": {\n\t\t\t\"bash (login)\": {\n\t\t\t\t\"path\": \"bash\",\n\t\t\t\t\"args\": [\"-l\"]\n\t\t\t}\n\t\t},\n\t\t\"python.pythonPath\": \"/usr/local/bin/python\",\n\t\t\"python.linting.enabled\": true,\n\t\t\"python.linting.pylintEnabled\": true,\n\t\t\"python.formatting.autopep8Path\": \"/usr/local/py-utils/bin/autopep8\",\n\t\t\"python.formatting.blackPath\": \"/usr/local/py-utils/bin/black\",\n\t\t\"python.formatting.yapfPath\": \"/usr/local/py-utils/bin/yapf\",\n\t\t\"python.linting.banditPath\": \"/usr/local/py-utils/bin/bandit\",\n\t\t\"python.linting.flake8Path\": \"/usr/local/py-utils/bin/flake8\",\n\t\t\"python.linting.mypyPath\": \"/usr/local/py-utils/bin/mypy\",\n\t\t\"python.linting.pycodestylePath\": \"/usr/local/py-utils/bin/pycodestyle\",\n\t\t\"python.linting.pydocstylePath\": \"/usr/local/py-utils/bin/pydocstyle\",\n\t\t\"python.linting.pylintPath\": \"/usr/local/py-utils/bin/pylint\"\n\t},\n\n\t// Add the IDs of extensions you want installed when the container is created.\n\t\"extensions\": [\n\t\t\"ms-python.python\"\n\t],\n\n\t// Use 'postCreateCommand' to run commands after the container is created.\n\t\"postCreateCommand\": \"pip3 install -r requirements.txt && python3 setup.py develop\"\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\nindent_style = space\nindent_size = 4\n\n[*.py]\nmax_line_length = 119\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "<!-- If you have any issue with The Fuck, sorry about that, but we will do what we\ncan to fix that. Actually, maybe we already have, so first thing to do is to\nupdate The Fuck and see if the bug is still there. -->\n\n<!-- If it is (sorry again), check if the problem has not already been reported and\nif not, just open an issue on [GitHub](https://github.com/nvbn/thefuck) with\nthe following basic information: -->\n\nThe output of `thefuck --version` (something like `The Fuck 3.1 using Python\n3.5.0 and Bash 4.4.12(1)-release`):\n\n    FILL THIS IN\n\nYour system (Debian 7, ArchLinux, Windows, etc.):\n\n    FILL THIS IN\n\nHow to reproduce the bug:\n\n    FILL THIS IN\n\nThe output of The Fuck with `THEFUCK_DEBUG=true` exported (typically execute `export THEFUCK_DEBUG=true` in your shell before The Fuck):\n\n    FILL THIS IN\n\nIf the bug only appears with a specific application, the output of that application and its version:\n\n    FILL THIS IN\n\nAnything else you think is relevant:\n\n    FILL THIS IN\n\n<!-- It's only with enough information that we can do something to fix the problem. -->\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Tests\n\non: [push, pull_request]\n\nenv:\n  PYTHON_LATEST: \"3.11\"\n\njobs:\n  test:\n    strategy:\n      matrix:\n        os: [ubuntu-latest, macos-latest, windows-latest]\n        python-version: [\"3.7\", \"3.8\", \"3.9\", \"3.10\", \"3.11\", \"3.12-dev\"]\n      fail-fast: false\n    runs-on: ${{ matrix.os }}\n    steps:\n      - uses: actions/checkout@v2\n      - name: Set up Python\n        uses: actions/setup-python@v2\n        with:\n          python-version: ${{ matrix.python-version }}\n      - name: Cache dependencies\n        id: cache-deps\n        uses: actions/cache@v2\n        with:\n          path: |\n            ${{ env.pythonLocation }}/bin/*\n            ${{ env.pythonLocation }}/lib/*\n            ${{ env.pythonLocation }}/scripts/*\n          key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('setup.py', 'requirements.txt') }}\n      - name: Install The Fuck with all dependencies\n        if: steps.cache-deps.outputs.cache-hit != 'true'\n        run: |\n          pip install -Ur requirements.txt coveralls\n          python setup.py develop\n      - name: Lint\n        if: matrix.os == 'ubuntu-latest' && matrix.python-version == env.PYTHON_LATEST\n        run: flake8\n      - name: Run tests\n        if: matrix.os != 'ubuntu-latest' || matrix.python-version != env.PYTHON_LATEST\n        run: coverage run --source=thefuck,tests -m pytest -v --capture=sys tests\n      - name: Run tests (including functional)\n        if: matrix.os == 'ubuntu-latest' && matrix.python-version == env.PYTHON_LATEST\n        run: |\n          docker build -t thefuck/python3 -f tests/Dockerfile --build-arg PYTHON_VERSION=3 .\n          docker build -t thefuck/python2 -f tests/Dockerfile --build-arg PYTHON_VERSION=2 .\n          coverage run --source=thefuck,tests -m pytest -v --capture=sys tests --enable-functional\n      - name: Post coverage results\n        if: matrix.os == 'ubuntu-latest' && matrix.python-version == env.PYTHON_LATEST\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: coveralls --service=github\n  test-deprecated:\n    strategy:\n      matrix:\n        python-version: [\"2.7\", \"3.6\"]\n    runs-on: ubuntu-latest\n    container: python:${{ matrix.python-version }}\n    steps:\n      - uses: actions/checkout@v2\n      - name: Install The Fuck with all dependencies\n        run: |\n          pip install -Ur requirements.txt coveralls\n          python setup.py develop\n      - name: Lint\n        run: flake8\n      - name: Run tests\n        run: coverage run --source=thefuck,tests -m pytest -v --capture=sys tests\n"
  },
  {
    "path": ".gitignore",
    "content": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n\n# C extensions\n*.so\n\n# Distribution / packaging\n.Python\nenv/\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib/\nlib64/\nparts/\nsdist/\nvar/\n*.egg-info/\n.installed.cfg\n*.egg\n\n# PyInstaller\n#  Usually these files are written by a python script from a template\n#  before PyInstaller builds the exe, so as to inject date/other infos into it.\n*.manifest\n*.spec\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.coverage\n.coverage.*\n.cache\nnosetests.xml\ncoverage.xml\n*,cover\n\n# Translations\n*.mo\n*.pot\n\n# Django stuff:\n*.log\n\n# Sphinx documentation\ndocs/_build/\n\n# PyBuilder\ntarget/\n\n.env\n.idea\n\n# vim temporary files\n.*.swp\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Report issues\nIf you have any issue with The Fuck, sorry about that, but we will do what we\ncan to fix that. Actually, maybe we already have, so first thing to do is to\nupdate The Fuck and see if the bug is still there.\n\nIf it is (sorry again), check if the problem has not already been reported and\nif not, just open an issue on [GitHub](https://github.com/nvbn/thefuck) with\nthe following basic information:\n  - the output of `thefuck --version` (something like `The Fuck 3.1 using\n    Python 3.5.0`);\n  - your shell and its version (`bash`, `zsh`, *Windows PowerShell*, etc.);\n  - your system (Debian 7, ArchLinux, Windows, etc.);\n  - how to reproduce the bug;\n  - the output of The Fuck with `THEFUCK_DEBUG=true` exported (typically execute\n    `export THEFUCK_DEBUG=true` in your shell before The Fuck);\n  - if the bug only appears with a specific application, the output of that\n    application and its version;\n  - anything else you think is relevant.\n\nIt's only with enough information that we can do something to fix the problem.\n\n# Make a pull request\nWe gladly accept pull request on the [official\nrepository](https://github.com/nvbn/thefuck) for new rules, new features, bug\nfixes, etc.\n\n# Developing\n\nIn order to develop locally, there are two options:\n\n- Develop using a local installation of Python 3 and setting up a virtual environment\n- Develop using an automated VSCode Dev Container.\n\n## Develop using local Python installation\n\n[Create and activate a Python 3 virtual environment.](https://docs.python.org/3/tutorial/venv.html)\n\nInstall `The Fuck` for development:\n\n```bash\npip install -r requirements.txt\npython setup.py develop\n```\n\nRun code style checks:\n\n```bash\nflake8\n```\n\nRun unit tests:\n\n```bash\npytest\n```\n\nRun unit and functional tests (requires docker):\n\n```bash\npytest --enable-functional\n```\n\nFor sending package to pypi:\n\n```bash\nsudo apt-get install pandoc\n./release.py\n```\n\n## Develop using Dev Container\n\nTo make local development easier a [VSCode Devcontainer](https://code.visualstudio.com/docs/remote/remote-overview) is included with this repository. This will allows you to spin up a Docker container with all the necessary prerequisites for this project pre-installed ready to go, no local Python install/setup required.\n\n### Prerequisites\n\nTo use the container you require:\n- [Docker](https://www.docker.com/products/docker-desktop)\n- [VSCode](https://code.visualstudio.com/)\n- [VSCode Remote Development Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack)\n- [Windows Users Only]: [Installation of WSL2 and configuration of Docker to use it](https://docs.docker.com/docker-for-windows/wsl/)\n\nFull notes about [installation are here](https://code.visualstudio.com/docs/remote/containers#_installation)\n\n### Running the container\n\nAssuming you have the prerequisites:\n\n1. Open VSCode\n1. Open command palette (CMD+SHIFT+P (mac) or CTRL+SHIFT+P (windows))\n1. Select `Remote-Containers: Reopen in Container`.\n1. Container will be built, install all pip requirements and your VSCode will mount into it automagically.\n1. Your VSCode and container now essentially become a throw away environment.\n"
  },
  {
    "path": "LICENSE.md",
    "content": "The MIT License (MIT)\n=====================\n\nCopyright (c) 2015-2022 Vladimir Iakovlev\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "MANIFEST.in",
    "content": "include LICENSE.md\ninclude fastentrypoints.py\n"
  },
  {
    "path": "README.md",
    "content": "# The Fuck [![Version][version-badge]][version-link] [![Build Status][workflow-badge]][workflow-link] [![Coverage][coverage-badge]][coverage-link] [![MIT License][license-badge]](LICENSE.md)\n\n*The Fuck* is a magnificent app, inspired by a [@liamosaur](https://twitter.com/liamosaur/)\n[tweet](https://twitter.com/liamosaur/status/506975850596536320),\nthat corrects errors in previous console commands.\n\n\nIs *The Fuck* too slow? [Try the experimental instant mode!](#experimental-instant-mode)\n\n[![gif with examples][examples-link]][examples-link]\n\nMore examples:\n\n```bash\n➜ apt-get install vim\nE: Could not open lock file /var/lib/dpkg/lock - open (13: Permission denied)\nE: Unable to lock the administration directory (/var/lib/dpkg/), are you root?\n\n➜ fuck\nsudo apt-get install vim [enter/↑/↓/ctrl+c]\n[sudo] password for nvbn:\nReading package lists... Done\n...\n```\n\n```bash\n➜ git push\nfatal: The current branch master has no upstream branch.\nTo push the current branch and set the remote as upstream, use\n\n    git push --set-upstream origin master\n\n\n➜ fuck\ngit push --set-upstream origin master [enter/↑/↓/ctrl+c]\nCounting objects: 9, done.\n...\n```\n\n```bash\n➜ puthon\nNo command 'puthon' found, did you mean:\n Command 'python' from package 'python-minimal' (main)\n Command 'python' from package 'python3' (main)\nzsh: command not found: puthon\n\n➜ fuck\npython [enter/↑/↓/ctrl+c]\nPython 3.4.2 (default, Oct  8 2014, 13:08:17)\n...\n```\n\n```bash\n➜ git brnch\ngit: 'brnch' is not a git command. See 'git --help'.\n\nDid you mean this?\n    branch\n\n➜ fuck\ngit branch [enter/↑/↓/ctrl+c]\n* master\n```\n\n```bash\n➜ lein rpl\n'rpl' is not a task. See 'lein help'.\n\nDid you mean this?\n         repl\n\n➜ fuck\nlein repl [enter/↑/↓/ctrl+c]\nnREPL server started on port 54848 on host 127.0.0.1 - nrepl://127.0.0.1:54848\nREPL-y 0.3.1\n...\n```\n\nIf you're not afraid of blindly running corrected commands, the\n`require_confirmation` [settings](#settings) option can be disabled:\n\n```bash\n➜ apt-get install vim\nE: Could not open lock file /var/lib/dpkg/lock - open (13: Permission denied)\nE: Unable to lock the administration directory (/var/lib/dpkg/), are you root?\n\n➜ fuck\nsudo apt-get install vim\n[sudo] password for nvbn:\nReading package lists... Done\n...\n```\n\n## Contents\n\n1. [Requirements](#requirements)\n2. [Installations](#installation)\n3. [Updating](#updating)\n4. [How it works](#how-it-works)\n5. [Creating your own rules](#creating-your-own-rules)\n6. [Settings](#settings)\n7. [Third party packages with rules](#third-party-packages-with-rules)\n8. [Experimental instant mode](#experimental-instant-mode)\n9. [Developing](#developing)\n10. [License](#license-mit)\n\n## Requirements\n\n- python (3.5+)\n- pip\n- python-dev\n\n##### [Back to Contents](#contents)\n\n## Installation\n\nOn macOS or Linux, you can install *The Fuck* via [Homebrew][homebrew]:\n\n```bash\nbrew install thefuck\n```\n\nOn Ubuntu / Mint, install *The Fuck* with the following commands:\n```bash\nsudo apt update\nsudo apt install python3-dev python3-pip python3-setuptools\npip3 install thefuck --user\n```\n\nOn FreeBSD, install *The Fuck* with the following commands:\n```bash\npkg install thefuck\n```\n\nOn ChromeOS, install *The Fuck* using [chromebrew](https://github.com/skycocker/chromebrew) with the following command:\n```bash\ncrew install thefuck\n```\n\nOn Arch based systems, install *The Fuck* with the following command:\n```\nsudo pacman -S thefuck\n```\n\nOn other systems, install *The Fuck*  by using `pip`:\n\n```bash\npip install thefuck\n```\n\n[Alternatively, you may use an OS package manager (OS X, Ubuntu, Arch).](https://github.com/nvbn/thefuck/wiki/Installation)\n\n<a href='#manual-installation' name='manual-installation'>#</a>\nIt is recommended that you place this command in your `.bash_profile`,\n`.bashrc`, `.zshrc` or other startup script:\n\n```bash\neval $(thefuck --alias)\n# You can use whatever you want as an alias, like for Mondays:\neval $(thefuck --alias FUCK)\n```\n\n[Or in your shell config (Bash, Zsh, Fish, Powershell, tcsh).](https://github.com/nvbn/thefuck/wiki/Shell-aliases)\n\nChanges are only available in a new shell session. To make changes immediately\navailable, run `source ~/.bashrc` (or your shell config file like `.zshrc`).\n\nTo run fixed commands without confirmation, use the `--yeah` option (or just `-y` for short, or `--hard` if you're especially frustrated):\n\n```bash\nfuck --yeah\n```\n\nTo fix commands recursively until succeeding, use the `-r` option:\n\n```bash\nfuck -r\n```\n\n##### [Back to Contents](#contents)\n\n## Updating\n\n```bash\npip3 install thefuck --upgrade\n```\n\n**Note: Alias functionality was changed in v1.34 of *The Fuck***\n\n## Uninstall\n\nTo remove *The Fuck*, reverse the installation process:\n- erase or comment *thefuck* alias line from your Bash, Zsh, Fish, Powershell, tcsh, ... shell config\n- use your package manager (brew, pip3, pkg, crew, pip) to uninstall the binaries\n\n## How it works\n\n*The Fuck* attempts to match the previous command with a rule. If a match is\nfound, a new command is created using the matched rule and executed. The\nfollowing rules are enabled by default:\n\n* `adb_unknown_command` &ndash; fixes misspelled commands like `adb logcta`;\n* `ag_literal` &ndash; adds `-Q` to `ag` when suggested;\n* `aws_cli` &ndash; fixes misspelled commands like `aws dynamdb scan`;\n* `az_cli` &ndash; fixes misspelled commands like `az providers`;\n* `cargo` &ndash; runs `cargo build` instead of `cargo`;\n* `cargo_no_command` &ndash; fixes wrong commands like `cargo buid`;\n* `cat_dir` &ndash; replaces `cat` with `ls` when you try to `cat` a directory;\n* `cd_correction` &ndash; spellchecks and corrects failed cd commands;\n* `cd_cs` &ndash; changes `cs` to `cd`;\n* `cd_mkdir` &ndash; creates directories before cd'ing into them;\n* `cd_parent` &ndash; changes `cd..` to `cd ..`;\n* `chmod_x` &ndash; adds execution bit;\n* `choco_install` &ndash; appends common suffixes for chocolatey packages;\n* `composer_not_command` &ndash; fixes composer command name;\n* `conda_mistype` &ndash; fixes conda commands;\n* `cp_create_destination` &ndash; creates a new directory when you attempt to `cp` or `mv` to a non-existent one\n* `cp_omitting_directory` &ndash; adds `-a` when you `cp` directory;\n* `cpp11` &ndash; adds missing `-std=c++11` to `g++` or `clang++`;\n* `dirty_untar` &ndash; fixes `tar x` command that untarred in the current directory;\n* `dirty_unzip` &ndash; fixes `unzip` command that unzipped in the current directory;\n* `django_south_ghost` &ndash; adds `--delete-ghost-migrations` to failed because ghosts django south migration;\n* `django_south_merge` &ndash; adds `--merge` to inconsistent django south migration;\n* `docker_login` &ndash; executes a `docker login` and repeats the previous command;\n* `docker_not_command` &ndash; fixes wrong docker commands like `docker tags`;\n* `docker_image_being_used_by_container` &dash; removes the container that is using the image before removing the image;\n* `dry` &ndash; fixes repetitions like `git git push`;\n* `fab_command_not_found` &ndash; fixes misspelled fabric commands;\n* `fix_alt_space` &ndash; replaces Alt+Space with Space character;\n* `fix_file` &ndash; opens a file with an error in your `$EDITOR`;\n* `gem_unknown_command` &ndash; fixes wrong `gem` commands;\n* `git_add` &ndash; fixes *\"pathspec 'foo' did not match any file(s) known to git.\"*;\n* `git_add_force` &ndash; adds `--force` to `git add <pathspec>...` when paths are .gitignore'd;\n* `git_bisect_usage` &ndash; fixes `git bisect strt`, `git bisect goood`, `git bisect rset`, etc. when bisecting;\n* `git_branch_delete` &ndash; changes `git branch -d` to `git branch -D`;\n* `git_branch_delete_checked_out` &ndash; changes `git branch -d` to `git checkout master && git branch -D` when trying to delete a checked out branch;\n* `git_branch_exists` &ndash; offers `git branch -d foo`, `git branch -D foo` or `git checkout foo` when creating a branch that already exists;\n* `git_branch_list` &ndash; catches `git branch list` in place of `git branch` and removes created branch;\n* `git_branch_0flag` &ndash; fixes commands such as `git branch 0v` and `git branch 0r` removing the created branch;\n* `git_checkout` &ndash; fixes branch name or creates new branch;\n* `git_clone_git_clone` &ndash; replaces `git clone git clone ...` with `git clone ...`\n* `git_clone_missing` &ndash; adds `git clone` to URLs that appear to link to a git repository.\n* `git_commit_add` &ndash; offers `git commit -a ...` or `git commit -p ...` after previous commit if it failed because nothing was staged;\n* `git_commit_amend` &ndash; offers `git commit --amend` after previous commit;\n* `git_commit_reset` &ndash; offers `git reset HEAD~` after previous commit;\n* `git_diff_no_index` &ndash; adds `--no-index` to previous `git diff` on untracked files;\n* `git_diff_staged` &ndash; adds `--staged` to previous `git diff` with unexpected output;\n* `git_fix_stash` &ndash; fixes `git stash` commands (misspelled subcommand and missing `save`);\n* `git_flag_after_filename` &ndash; fixes `fatal: bad flag '...' after filename`\n* `git_help_aliased` &ndash; fixes `git help <alias>` commands replacing <alias> with the aliased command;\n* `git_hook_bypass` &ndash; adds `--no-verify` flag previous to `git am`, `git commit`, or `git push` command;\n* `git_lfs_mistype` &ndash; fixes mistyped `git lfs <command>` commands;\n* `git_main_master` &ndash; fixes incorrect branch name between `main` and `master`\n* `git_merge` &ndash; adds remote to branch names;\n* `git_merge_unrelated` &ndash; adds `--allow-unrelated-histories` when required\n* `git_not_command` &ndash; fixes wrong git commands like `git brnch`;\n* `git_pull` &ndash; sets upstream before executing previous `git pull`;\n* `git_pull_clone` &ndash; clones instead of pulling when the repo does not exist;\n* `git_pull_uncommitted_changes` &ndash; stashes changes before pulling and pops them afterwards;\n* `git_push` &ndash; adds `--set-upstream origin $branch` to previous failed `git push`;\n* `git_push_different_branch_names` &ndash; fixes pushes when local branch name does not match remote branch name;\n* `git_push_pull` &ndash; runs `git pull` when `push` was rejected;\n* `git_push_without_commits` &ndash; creates an initial commit if you forget and only `git add .`, when setting up a new project;\n* `git_rebase_no_changes` &ndash; runs `git rebase --skip` instead of `git rebase --continue` when there are no changes;\n* `git_remote_delete` &ndash; replaces `git remote delete remote_name` with `git remote remove remote_name`;\n* `git_rm_local_modifications` &ndash; adds `-f` or `--cached` when you try to `rm` a locally modified file;\n* `git_rm_recursive` &ndash; adds `-r` when you try to `rm` a directory;\n* `git_rm_staged` &ndash;  adds `-f` or `--cached` when you try to `rm` a file with staged changes\n* `git_rebase_merge_dir` &ndash; offers `git rebase (--continue | --abort | --skip)` or removing the `.git/rebase-merge` dir when a rebase is in progress;\n* `git_remote_seturl_add` &ndash; runs `git remote add` when `git remote set_url` on nonexistent remote;\n* `git_stash` &ndash; stashes your local modifications before rebasing or switching branch;\n* `git_stash_pop` &ndash; adds your local modifications before popping stash, then resets;\n* `git_tag_force` &ndash; adds `--force` to `git tag <tagname>` when the tag already exists;\n* `git_two_dashes` &ndash; adds a missing dash to commands like `git commit -amend` or `git rebase -continue`;\n* `go_run` &ndash; appends `.go` extension when compiling/running Go programs;\n* `go_unknown_command` &ndash; fixes wrong `go` commands, for example `go bulid`;\n* `gradle_no_task` &ndash; fixes not found or ambiguous `gradle` task;\n* `gradle_wrapper` &ndash; replaces `gradle` with `./gradlew`;\n* `grep_arguments_order` &ndash; fixes `grep` arguments order for situations like `grep -lir . test`;\n* `grep_recursive` &ndash; adds `-r` when you try to `grep` directory;\n* `grunt_task_not_found` &ndash; fixes misspelled `grunt` commands;\n* `gulp_not_task` &ndash; fixes misspelled `gulp` tasks;\n* `has_exists_script` &ndash; prepends `./` when script/binary exists;\n* `heroku_multiple_apps` &ndash; adds `--app <app>` to `heroku` commands like `heroku pg`;\n* `heroku_not_command` &ndash; fixes wrong `heroku` commands like `heroku log`;\n* `history` &ndash; tries to replace command with the most similar command from history;\n* `hostscli` &ndash; tries to fix `hostscli` usage;\n* `ifconfig_device_not_found` &ndash; fixes wrong device names like `wlan0` to `wlp2s0`;\n* `java` &ndash; removes `.java` extension when running Java programs;\n* `javac` &ndash; appends missing `.java` when compiling Java files;\n* `lein_not_task` &ndash; fixes wrong `lein` tasks like `lein rpl`;\n* `long_form_help` &ndash; changes `-h` to `--help` when the short form version is not supported\n* `ln_no_hard_link` &ndash; catches hard link creation on directories, suggest symbolic link;\n* `ln_s_order` &ndash; fixes `ln -s` arguments order;\n* `ls_all` &ndash; adds `-A` to `ls` when output is empty;\n* `ls_lah` &ndash; adds `-lah` to `ls`;\n* `man` &ndash; changes manual section;\n* `man_no_space` &ndash; fixes man commands without spaces, for example `mandiff`;\n* `mercurial` &ndash; fixes wrong `hg` commands;\n* `missing_space_before_subcommand` &ndash; fixes command with missing space like `npminstall`;\n* `mkdir_p` &ndash; adds `-p` when you try to create a directory without a parent;\n* `mvn_no_command` &ndash; adds `clean package` to `mvn`;\n* `mvn_unknown_lifecycle_phase` &ndash; fixes misspelled life cycle phases with `mvn`;\n* `npm_missing_script` &ndash; fixes `npm` custom script name in `npm run-script <script>`;\n* `npm_run_script` &ndash; adds missing `run-script` for custom `npm` scripts;\n* `npm_wrong_command` &ndash; fixes wrong npm commands like `npm urgrade`;\n* `no_command` &ndash; fixes wrong console commands, for example `vom/vim`;\n* `no_such_file` &ndash; creates missing directories with `mv` and `cp` commands;\n* `omnienv_no_such_command` &ndash; fixes wrong commands for `goenv`, `nodenv`, `pyenv` and `rbenv` (eg.: `pyenv isntall` or `goenv list`);\n* `open` &ndash; either prepends `http://` to address passed to `open` or creates a new file or directory and passes it to `open`;\n* `pip_install` &ndash; fixes permission issues with `pip install` commands by adding `--user` or prepending `sudo` if necessary;\n* `pip_unknown_command` &ndash; fixes wrong `pip` commands, for example `pip instatl/pip install`;\n* `php_s` &ndash; replaces `-s` by `-S` when trying to run a local php server;\n* `port_already_in_use` &ndash; kills process that bound port;\n* `prove_recursively` &ndash; adds `-r` when called with directory;\n* `python_command` &ndash; prepends `python` when you try to run non-executable/without `./` python script;\n* `python_execute` &ndash; appends missing `.py` when executing Python files;\n* `python_module_error` &ndash; fixes ModuleNotFoundError by trying to `pip install` that module;\n* `quotation_marks` &ndash; fixes uneven usage of `'` and `\"` when containing args';\n* `path_from_history` &ndash; replaces not found path with a similar absolute path from history;\n* `rails_migrations_pending` &ndash; runs pending migrations;\n* `react_native_command_unrecognized` &ndash; fixes unrecognized `react-native` commands;\n* `remove_shell_prompt_literal` &ndash; removes leading shell prompt symbol `$`, common when copying commands from documentations;\n* `remove_trailing_cedilla` &ndash; removes trailing cedillas `ç`, a common typo for European keyboard layouts;\n* `rm_dir` &ndash; adds `-rf` when you try to remove a directory;\n* `scm_correction` &ndash; corrects wrong scm like `hg log` to `git log`;\n* `sed_unterminated_s` &ndash; adds missing '/' to `sed`'s `s` commands;\n* `sl_ls` &ndash; changes `sl` to `ls`;\n* `ssh_known_hosts` &ndash; removes host from `known_hosts` on warning;\n* `sudo` &ndash; prepends `sudo` to the previous command if it failed because of permissions;\n* `sudo_command_from_user_path` &ndash; runs commands from users `$PATH` with `sudo`;\n* `switch_lang` &ndash; switches command from your local layout to en;\n* `systemctl` &ndash; correctly orders parameters of confusing `systemctl`;\n* `terraform_init.py` &ndash; runs `terraform init` before plan or apply;\n* `terraform_no_command.py` &ndash; fixes unrecognized `terraform` commands;\n* `test.py` &ndash; runs `pytest` instead of `test.py`;\n* `touch` &ndash; creates missing directories before \"touching\";\n* `tsuru_login` &ndash; runs `tsuru login` if not authenticated or session expired;\n* `tsuru_not_command` &ndash; fixes wrong `tsuru` commands like `tsuru shell`;\n* `tmux` &ndash; fixes `tmux` commands;\n* `unknown_command` &ndash; fixes hadoop hdfs-style \"unknown command\", for example adds missing '-' to the command on `hdfs dfs ls`;\n* `unsudo` &ndash; removes `sudo` from previous command if a process refuses to run on superuser privilege.\n* `vagrant_up` &ndash; starts up the vagrant instance;\n* `whois` &ndash; fixes `whois` command;\n* `workon_doesnt_exists` &ndash; fixes `virtualenvwrapper` env name os suggests to create new.\n* `wrong_hyphen_before_subcommand` &ndash; removes an improperly placed hyphen (`apt-install` -> `apt install`, `git-log` -> `git log`, etc.)\n* `yarn_alias` &ndash; fixes aliased `yarn` commands like `yarn ls`;\n* `yarn_command_not_found` &ndash; fixes misspelled `yarn` commands;\n* `yarn_command_replaced` &ndash; fixes replaced `yarn` commands;\n* `yarn_help` &ndash; makes it easier to open `yarn` documentation;\n\n##### [Back to Contents](#contents)\n\nThe following rules are enabled by default on specific platforms only:\n\n* `apt_get` &ndash; installs app from apt if it not installed (requires `python-commandnotfound` / `python3-commandnotfound`);\n* `apt_get_search` &ndash; changes trying to search using `apt-get` with searching using `apt-cache`;\n* `apt_invalid_operation` &ndash; fixes invalid `apt` and `apt-get` calls, like `apt-get isntall vim`;\n* `apt_list_upgradable` &ndash; helps you run `apt list --upgradable` after `apt update`;\n* `apt_upgrade` &ndash; helps you run `apt upgrade` after `apt list --upgradable`;\n* `brew_cask_dependency` &ndash; installs cask dependencies;\n* `brew_install` &ndash; fixes formula name for `brew install`;\n* `brew_reinstall` &ndash; turns `brew install <formula>` into `brew reinstall <formula>`;\n* `brew_link` &ndash; adds `--overwrite --dry-run` if linking fails;\n* `brew_uninstall` &ndash; adds `--force` to `brew uninstall` if multiple versions were installed;\n* `brew_unknown_command` &ndash; fixes wrong brew commands, for example `brew docto/brew doctor`;\n* `brew_update_formula` &ndash; turns `brew update <formula>` into `brew upgrade <formula>`;\n* `dnf_no_such_command` &ndash; fixes mistyped DNF commands;\n* `nixos_cmd_not_found` &ndash; installs apps on NixOS;\n* `pacman` &ndash; installs app with `pacman` if it is not installed (uses `yay`, `pikaur` or `yaourt` if available);\n* `pacman_invalid_option` &ndash; replaces lowercase `pacman` options with uppercase.\n* `pacman_not_found` &ndash; fixes package name with `pacman`, `yay`, `pikaur` or `yaourt`.\n* `yum_invalid_operation` &ndash; fixes invalid `yum` calls, like `yum isntall vim`;\n\nThe following commands are bundled with *The Fuck*, but are not enabled by\ndefault:\n\n* `git_push_force` &ndash; adds `--force-with-lease` to a `git push` (may conflict with `git_push_pull`);\n* `rm_root` &ndash; adds `--no-preserve-root` to `rm -rf /` command.\n\n##### [Back to Contents](#contents)\n\n## Creating your own rules\n\nTo add your own rule, create a file named `your-rule-name.py`\nin `~/.config/thefuck/rules`. The rule file must contain two functions:\n\n```python\nmatch(command: Command) -> bool\nget_new_command(command: Command) -> str | list[str]\n```\n\nAdditionally, rules can contain optional functions:\n\n```python\nside_effect(old_command: Command, fixed_command: str) -> None\n```\nRules can also contain the optional variables `enabled_by_default`, `requires_output` and `priority`.\n\n`Command` has three attributes: `script`, `output` and `script_parts`.\nYour rule should not change `Command`.\n\n\n**Rules api changed in 3.0:** To access a rule's settings, import it with\n `from thefuck.conf import settings`\n\n`settings` is a special object assembled from `~/.config/thefuck/settings.py`,\nand values from env ([see more below](#settings)).\n\nA simple example rule for running a script with `sudo`:\n\n```python\ndef match(command):\n    return ('permission denied' in command.output.lower()\n            or 'EACCES' in command.output)\n\n\ndef get_new_command(command):\n    return 'sudo {}'.format(command.script)\n\n# Optional:\nenabled_by_default = True\n\ndef side_effect(command, fixed_command):\n    subprocess.call('chmod 777 .', shell=True)\n\npriority = 1000  # Lower first, default is 1000\n\nrequires_output = True\n```\n\n[More examples of rules](https://github.com/nvbn/thefuck/tree/master/thefuck/rules),\n[utility functions for rules](https://github.com/nvbn/thefuck/tree/master/thefuck/utils.py),\n[app/os-specific helpers](https://github.com/nvbn/thefuck/tree/master/thefuck/specific/).\n\n##### [Back to Contents](#contents)\n\n## Settings\n\nSeveral *The Fuck* parameters can be changed in the file `$XDG_CONFIG_HOME/thefuck/settings.py`\n(`$XDG_CONFIG_HOME` defaults to `~/.config`):\n\n* `rules` &ndash; list of enabled rules, by default `thefuck.const.DEFAULT_RULES`;\n* `exclude_rules` &ndash; list of disabled rules, by default `[]`;\n* `require_confirmation` &ndash; requires confirmation before running new command, by default `True`;\n* `wait_command` &ndash; the max amount of time in seconds for getting previous command output;\n* `no_colors` &ndash; disable colored output;\n* `priority` &ndash; dict with rules priorities, rule with lower `priority` will be matched first;\n* `debug` &ndash; enables debug output, by default `False`;\n* `history_limit` &ndash; the numeric value of how many history commands will be scanned, like `2000`;\n* `alter_history` &ndash; push fixed command to history, by default `True`;\n* `wait_slow_command` &ndash; max amount of time in seconds for getting previous command output if it in `slow_commands` list;\n* `slow_commands` &ndash; list of slow commands;\n* `num_close_matches` &ndash; the maximum number of close matches to suggest, by default `3`.\n* `excluded_search_path_prefixes` &ndash; path prefixes to ignore when searching for commands, by default `[]`.\n\nAn example of `settings.py`:\n\n```python\nrules = ['sudo', 'no_command']\nexclude_rules = ['git_push']\nrequire_confirmation = True\nwait_command = 10\nno_colors = False\npriority = {'sudo': 100, 'no_command': 9999}\ndebug = False\nhistory_limit = 9999\nwait_slow_command = 20\nslow_commands = ['react-native', 'gradle']\nnum_close_matches = 5\n```\n\nOr via environment variables:\n\n* `THEFUCK_RULES` &ndash; list of enabled rules, like `DEFAULT_RULES:rm_root` or `sudo:no_command`;\n* `THEFUCK_EXCLUDE_RULES` &ndash; list of disabled rules, like `git_pull:git_push`;\n* `THEFUCK_REQUIRE_CONFIRMATION` &ndash; require confirmation before running new command, `true/false`;\n* `THEFUCK_WAIT_COMMAND` &ndash; the max amount of time in seconds for getting previous command output;\n* `THEFUCK_NO_COLORS` &ndash; disable colored output, `true/false`;\n* `THEFUCK_PRIORITY` &ndash; priority of the rules, like `no_command=9999:apt_get=100`,\nrule with lower `priority` will be matched first;\n* `THEFUCK_DEBUG` &ndash; enables debug output, `true/false`;\n* `THEFUCK_HISTORY_LIMIT` &ndash; how many history commands will be scanned, like `2000`;\n* `THEFUCK_ALTER_HISTORY` &ndash; push fixed command to history `true/false`;\n* `THEFUCK_WAIT_SLOW_COMMAND` &ndash; the max amount of time in seconds for getting previous command output if it in `slow_commands` list;\n* `THEFUCK_SLOW_COMMANDS` &ndash; list of slow commands, like `lein:gradle`;\n* `THEFUCK_NUM_CLOSE_MATCHES` &ndash; the maximum number of close matches to suggest, like `5`.\n* `THEFUCK_EXCLUDED_SEARCH_PATH_PREFIXES` &ndash; path prefixes to ignore when searching for commands, by default `[]`.\n\nFor example:\n\n```bash\nexport THEFUCK_RULES='sudo:no_command'\nexport THEFUCK_EXCLUDE_RULES='git_pull:git_push'\nexport THEFUCK_REQUIRE_CONFIRMATION='true'\nexport THEFUCK_WAIT_COMMAND=10\nexport THEFUCK_NO_COLORS='false'\nexport THEFUCK_PRIORITY='no_command=9999:apt_get=100'\nexport THEFUCK_HISTORY_LIMIT='2000'\nexport THEFUCK_NUM_CLOSE_MATCHES='5'\n```\n\n##### [Back to Contents](#contents)\n\n## Third-party packages with rules\n\nIf you'd like to make a specific set of non-public rules, but would still like\nto share them with others, create a package named `thefuck_contrib_*` with\nthe following structure:\n\n```\nthefuck_contrib_foo\n  thefuck_contrib_foo\n    rules\n      __init__.py\n      *third-party rules*\n    __init__.py\n    *third-party-utils*\n  setup.py\n```\n\n*The Fuck* will find rules located in the `rules` module.\n\n##### [Back to Contents](#contents)\n\n## Experimental instant mode\n\nThe default behavior of *The Fuck* requires time to re-run previous commands.\nWhen in instant mode, *The Fuck* saves time by logging output with [script](https://en.wikipedia.org/wiki/Script_(Unix)),\nthen reading the log.\n\n[![gif with instant mode][instant-mode-gif-link]][instant-mode-gif-link]\n\nCurrently, instant mode only supports Python 3 with bash or zsh. zsh's autocorrect function also needs to be disabled in order for thefuck to work properly.\n\nTo enable instant mode, add `--enable-experimental-instant-mode`\nto the alias initialization in `.bashrc`, `.bash_profile` or `.zshrc`.\n\nFor example:\n\n```bash\neval $(thefuck --alias --enable-experimental-instant-mode)\n```\n\n##### [Back to Contents](#contents)\n\n## Developing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md)\n\n## License MIT\nProject License can be found [here](LICENSE.md).\n\n\n[version-badge]:   https://img.shields.io/pypi/v/thefuck.svg?label=version\n[version-link]:    https://pypi.python.org/pypi/thefuck/\n[workflow-badge]:  https://github.com/nvbn/thefuck/workflows/Tests/badge.svg\n[workflow-link]:   https://github.com/nvbn/thefuck/actions?query=workflow%3ATests\n[coverage-badge]:  https://img.shields.io/coveralls/nvbn/thefuck.svg\n[coverage-link]:   https://coveralls.io/github/nvbn/thefuck\n[license-badge]:   https://img.shields.io/badge/license-MIT-007EC7.svg\n[examples-link]:   https://raw.githubusercontent.com/nvbn/thefuck/master/example.gif\n[instant-mode-gif-link]:   https://raw.githubusercontent.com/nvbn/thefuck/master/example_instant_mode.gif\n[homebrew]:        https://brew.sh/\n\n##### [Back to Contents](#contents)\n"
  },
  {
    "path": "fastentrypoints.py",
    "content": "# Copyright (c) 2016, Aaron Christianson\n# All rights reserved.\n#\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are\n# met:\n#\n# 1. Redistributions of source code must retain the above copyright\n#    notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright\n#    notice, this list of conditions and the following disclaimer in the\n#    documentation and/or other materials provided with the distribution.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n# IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\n# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n'''\nMonkey patch setuptools to write faster console_scripts with this format:\n\n    import sys\n    from mymodule import entry_function\n    sys.exit(entry_function())\n\nThis is better.\n\n(c) 2016, Aaron Christianson\nhttp://github.com/ninjaaron/fast-entry_points\n'''\nfrom setuptools.command import easy_install\nimport re\nTEMPLATE = r'''\\\n# -*- coding: utf-8 -*-\n# EASY-INSTALL-ENTRY-SCRIPT: '{3}','{4}','{5}'\n__requires__ = '{3}'\nimport re\nimport sys\n\nfrom {0} import {1}\n\nif __name__ == '__main__':\n    sys.argv[0] = re.sub(r'(-script\\.pyw?|\\.exe)?$', '', sys.argv[0])\n    sys.exit({2}())'''\n\n\n@classmethod\ndef get_args(cls, dist, header=None):\n    \"\"\"\n    Yield write_script() argument tuples for a distribution's\n    console_scripts and gui_scripts entry points.\n    \"\"\"\n    if header is None:\n        header = cls.get_header()\n    spec = str(dist.as_requirement())\n    for type_ in 'console', 'gui':\n        group = type_ + '_scripts'\n        for name, ep in dist.get_entry_map(group).items():\n            # ensure_safe_name\n            if re.search(r'[\\\\/]', name):\n                raise ValueError(\"Path separators not allowed in script names\")\n            script_text = TEMPLATE.format(\n                          ep.module_name, ep.attrs[0], '.'.join(ep.attrs),\n                          spec, group, name)\n            args = cls._get_script_args(type_, name, header, script_text)\n            for res in args:\n                yield res\n\n\neasy_install.ScriptWriter.get_args = get_args\n\n\ndef main():\n    import os\n    import re\n    import shutil\n    import sys\n    dests = sys.argv[1:] or ['.']\n    filename = re.sub(r'\\.pyc$', '.py', __file__)\n\n    for dst in dests:\n        shutil.copy(filename, dst)\n        manifest_path = os.path.join(dst, 'MANIFEST.in')\n        setup_path = os.path.join(dst, 'setup.py')\n\n        # Insert the include statement to MANIFEST.in if not present\n        with open(manifest_path, 'a+') as manifest:\n            manifest.seek(0)\n            manifest_content = manifest.read()\n            if not 'include fastentrypoints.py' in manifest_content:\n                manifest.write(('\\n' if manifest_content else '')\n                               + 'include fastentrypoints.py')\n\n        # Insert the import statement to setup.py if not present\n        with open(setup_path, 'a+') as setup:\n            setup.seek(0)\n            setup_content = setup.read()\n            if not 'import fastentrypoints' in setup_content:\n                setup.seek(0)\n                setup.truncate()\n                setup.write('import fastentrypoints\\n' + setup_content)\n\nprint(__name__)\n"
  },
  {
    "path": "install.sh",
    "content": "#!/bin/sh\n\necho \"Installation script is deprecated!\"\necho \"For installation instruction please visit https://github.com/nvbn/thefuck\"\n"
  },
  {
    "path": "release.py",
    "content": "#!/usr/bin/env python\nfrom subprocess import call\nimport os\nimport re\n\n\nversion = None\n\n\ndef get_new_setup_py_lines():\n    global version\n    with open('setup.py', 'r') as sf:\n        current_setup = sf.readlines()\n    for line in current_setup:\n        if line.startswith('VERSION = '):\n            major, minor = re.findall(r\"VERSION = '(\\d+)\\.(\\d+)'\", line)[0]\n            version = \"{}.{}\".format(major, int(minor) + 1)\n            yield \"VERSION = '{}'\\n\".format(version)\n        else:\n            yield line\n\n\nlines = list(get_new_setup_py_lines())\nwith open('setup.py', 'w') as sf:\n    sf.writelines(lines)\n\ncall('git pull', shell=True)\ncall('git commit -am \"Bump to {}\"'.format(version), shell=True)\ncall('git tag {}'.format(version), shell=True)\ncall('git push', shell=True)\ncall('git push --tags', shell=True)\n\nenv = os.environ\nenv['CONVERT_README'] = 'true'\ncall('rm -rf dist/*', shell=True, env=env)\ncall('python setup.py sdist bdist_wheel', shell=True, env=env)\ncall('twine upload dist/*', shell=True, env=env)\n"
  },
  {
    "path": "requirements.txt",
    "content": "flake8\npytest\nmock\npytest-mock\nwheel\nsetuptools>=17.1\npexpect\npypandoc\npytest-benchmark\npytest-docker-pexpect\ntwine\n"
  },
  {
    "path": "scripts/fuck.bat",
    "content": "@set PYTHONIOENCODING=utf-8\n@powershell -noprofile -c \"cmd /c \\\"$(thefuck %* $(doskey /history)[-2])\\\"; [Console]::ResetColor();\"\n"
  },
  {
    "path": "scripts/fuck.ps1",
    "content": "if ((Get-Command \"fuck\").CommandType -eq \"Function\") {\n\tfuck @args;\n\t[Console]::ResetColor()\n\texit\n}\n\n\"First time use of thefuck detected. \"\n\nif ((Get-Content $PROFILE -Raw -ErrorAction Ignore) -like \"*thefuck*\") {\n} else {\n\t\"  - Adding thefuck intialization to user `$PROFILE\"\n\t$script = \"`n`$env:PYTHONIOENCODING='utf-8' `niex `\"`$(thefuck --alias)`\"\";\n\tWrite-Output $script | Add-Content $PROFILE\n}\n\n\"  - Adding fuck() function to current session...\"\n$env:PYTHONIOENCODING='utf-8'\niex \"$($(thefuck --alias).Replace(\"function fuck\", \"function global:fuck\"))\"\n\n\"  - Invoking fuck()`n\"\nfuck @args;\n[Console]::ResetColor()\n"
  },
  {
    "path": "setup.cfg",
    "content": "[bdist_wheel]\nuniversal = 1\n"
  },
  {
    "path": "setup.py",
    "content": "#!/usr/bin/env python\nfrom setuptools import setup, find_packages\nimport pkg_resources\nimport sys\nimport os\nimport fastentrypoints\n\n\ntry:\n    if int(pkg_resources.get_distribution(\"pip\").version.split('.')[0]) < 6:\n        print('pip older than 6.0 not supported, please upgrade pip with:\\n\\n'\n              '    pip install -U pip')\n        sys.exit(-1)\nexcept pkg_resources.DistributionNotFound:\n    pass\n\nif os.environ.get('CONVERT_README'):\n    import pypandoc\n\n    long_description = pypandoc.convert('README.md', 'rst')\nelse:\n    long_description = ''\n\nversion = sys.version_info[:2]\nif version < (2, 7):\n    print('thefuck requires Python version 2.7 or later' +\n          ' ({}.{} detected).'.format(*version))\n    sys.exit(-1)\nelif (3, 0) < version < (3, 5):\n    print('thefuck requires Python version 3.5 or later' +\n          ' ({}.{} detected).'.format(*version))\n    sys.exit(-1)\n\nVERSION = '3.32'\n\ninstall_requires = ['psutil', 'colorama', 'six']\nextras_require = {':python_version<\"3.4\"': ['pathlib2'],\n                  ':python_version<\"3.3\"': ['backports.shutil_get_terminal_size'],\n                  ':python_version<=\"2.7\"': ['decorator<5', 'pyte<0.8.1'],\n                  ':python_version>\"2.7\"': ['decorator', 'pyte'],\n                  \":sys_platform=='win32'\": ['win_unicode_console']}\n\nif sys.platform == \"win32\":\n    scripts = ['scripts\\\\fuck.bat', 'scripts\\\\fuck.ps1']\n    entry_points = {'console_scripts': [\n                  'thefuck = thefuck.entrypoints.main:main',\n                  'thefuck_firstuse = thefuck.entrypoints.not_configured:main']}\nelse:\n    scripts = []\n    entry_points = {'console_scripts': [\n                  'thefuck = thefuck.entrypoints.main:main',\n                  'fuck = thefuck.entrypoints.not_configured:main']}\n\nsetup(name='thefuck',\n      version=VERSION,\n      description=\"Magnificent app which corrects your previous console command\",\n      long_description=long_description,\n      author='Vladimir Iakovlev',\n      author_email='nvbn.rm@gmail.com',\n      url='https://github.com/nvbn/thefuck',\n      license='MIT',\n      packages=find_packages(exclude=['ez_setup', 'examples',\n                                      'tests', 'tests.*', 'release']),\n      include_package_data=True,\n      zip_safe=False,\n      python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*',\n      install_requires=install_requires,\n      extras_require=extras_require,\n      scripts=scripts,\n      entry_points=entry_points)\n"
  },
  {
    "path": "snapcraft.yaml",
    "content": "name: thefuck\nversion: stable\nversion-script: git -C parts/thefuck/build describe --abbrev=0 --tags\nsummary: Magnificent app which corrects your previous console command.\ndescription: |\n  The Fuck tries to match a rule for the previous command,\n  creates a new command using the matched rule and runs it.\n\ngrade: stable\nconfinement: classic\n\napps:\n  thefuck:\n    command: bin/thefuck\n    environment:\n        PYTHONIOENCODING: utf-8\n  fuck:\n    command: bin/fuck\n    environment:\n        PYTHONIOENCODING: utf-8\n\nparts:\n  thefuck:\n    source: https://github.com/nvbn/thefuck.git\n    plugin: python\n"
  },
  {
    "path": "tests/Dockerfile",
    "content": "ARG PYTHON_VERSION\nFROM python:${PYTHON_VERSION}\nRUN apt-get update -y\nRUN apt-get install -yy --no-install-recommends --no-install-suggests fish tcsh zsh\nRUN pip install --upgrade pip\nCOPY . /src\nRUN pip install /src\n"
  },
  {
    "path": "tests/__init__.py",
    "content": ""
  },
  {
    "path": "tests/conftest.py",
    "content": "import os\nimport pytest\nfrom thefuck import shells\nfrom thefuck import conf, const\nfrom thefuck.system import Path\n\nshells.shell = shells.Generic()\n\n\ndef pytest_configure(config):\n    config.addinivalue_line(\"markers\", \"functional: mark test as functional\")\n\n\ndef pytest_addoption(parser):\n    \"\"\"Adds `--enable-functional` argument.\"\"\"\n    group = parser.getgroup(\"thefuck\")\n    group.addoption('--enable-functional', action=\"store_true\", default=False,\n                    help=\"Enable functional tests\")\n\n\n@pytest.fixture\ndef no_memoize(monkeypatch):\n    monkeypatch.setattr('thefuck.utils.memoize.disabled', True)\n\n\n@pytest.fixture(autouse=True)\ndef settings(request):\n    def _reset_settings():\n        conf.settings.clear()\n        conf.settings.update(const.DEFAULT_SETTINGS)\n\n    request.addfinalizer(_reset_settings)\n    conf.settings.user_dir = Path('~/.thefuck')\n    return conf.settings\n\n\n@pytest.fixture\ndef no_colors(settings):\n    settings.no_colors = True\n\n\n@pytest.fixture(autouse=True)\ndef no_cache(monkeypatch):\n    monkeypatch.setattr('thefuck.utils.cache.disabled', True)\n\n\n@pytest.fixture(autouse=True)\ndef functional(request):\n    if request.node.get_closest_marker('functional') \\\n            and not request.config.getoption('enable_functional'):\n        pytest.skip('functional tests are disabled')\n\n\n@pytest.fixture\ndef source_root():\n    return Path(__file__).parent.parent.resolve()\n\n\n@pytest.fixture\ndef set_shell(monkeypatch):\n    def _set(cls):\n        shell = cls()\n        monkeypatch.setattr('thefuck.shells.shell', shell)\n        return shell\n\n    return _set\n\n\n@pytest.fixture(autouse=True)\ndef os_environ(monkeypatch):\n    env = {'PATH': os.environ['PATH']}\n    monkeypatch.setattr('os.environ', env)\n    return env\n"
  },
  {
    "path": "tests/entrypoints/__init__.py",
    "content": ""
  },
  {
    "path": "tests/entrypoints/test_alias.py",
    "content": "from mock import Mock\nimport pytest\nfrom thefuck.entrypoints.alias import _get_alias, print_alias\n\n\n@pytest.mark.parametrize(\n    'py2, enable_experimental_instant_mode, which, is_instant', [\n        (False, True, True, True),\n        (False, False, True, False),\n        (False, True, False, False),\n        (True, True, True, False),\n        (True, True, False, False),\n        (True, False, True, False)])\ndef test_get_alias(monkeypatch, mocker, py2,\n                   enable_experimental_instant_mode,\n                   which, is_instant):\n    monkeypatch.setattr('six.PY2', py2)\n    args = Mock(\n        enable_experimental_instant_mode=enable_experimental_instant_mode,\n        alias='fuck', )\n    mocker.patch('thefuck.entrypoints.alias.which', return_value=which)\n    shell = Mock(app_alias=lambda _: 'app_alias',\n                 instant_mode_alias=lambda _: 'instant_mode_alias')\n    monkeypatch.setattr('thefuck.entrypoints.alias.shell', shell)\n\n    alias = _get_alias(args)\n    if is_instant:\n        assert alias == 'instant_mode_alias'\n    else:\n        assert alias == 'app_alias'\n\n\ndef test_print_alias(mocker):\n    settings_mock = mocker.patch('thefuck.entrypoints.alias.settings')\n    _get_alias_mock = mocker.patch('thefuck.entrypoints.alias._get_alias')\n    known_args = Mock()\n    print_alias(known_args)\n    settings_mock.init.assert_called_once_with(known_args)\n    _get_alias_mock.assert_called_once_with(known_args)\n"
  },
  {
    "path": "tests/entrypoints/test_fix_command.py",
    "content": "import pytest\nfrom mock import Mock\nfrom thefuck.entrypoints.fix_command import _get_raw_command\n\n\nclass TestGetRawCommand(object):\n    def test_from_force_command_argument(self):\n        known_args = Mock(force_command='git brunch')\n        assert _get_raw_command(known_args) == ['git brunch']\n\n    def test_from_command_argument(self, os_environ):\n        os_environ['TF_HISTORY'] = None\n        known_args = Mock(force_command=None,\n                          command=['sl'])\n        assert _get_raw_command(known_args) == ['sl']\n\n    @pytest.mark.parametrize('history, result', [\n        ('git br', 'git br'),\n        ('git br\\nfcuk', 'git br'),\n        ('git br\\nfcuk\\nls', 'ls'),\n        ('git br\\nfcuk\\nls\\nfuk', 'ls')])\n    def test_from_history(self, os_environ, history, result):\n        os_environ['TF_HISTORY'] = history\n        known_args = Mock(force_command=None,\n                          command=None)\n        assert _get_raw_command(known_args) == [result]\n"
  },
  {
    "path": "tests/entrypoints/test_not_configured.py",
    "content": "import pytest\nimport json\nfrom six import StringIO\nfrom mock import MagicMock\nfrom thefuck.shells.generic import ShellConfiguration\nfrom thefuck.entrypoints.not_configured import main\n\n\n@pytest.fixture(autouse=True)\ndef usage_tracker(mocker):\n    return mocker.patch(\n        'thefuck.entrypoints.not_configured._get_not_configured_usage_tracker_path',\n        new_callable=MagicMock)\n\n\n@pytest.fixture(autouse=True)\ndef usage_tracker_io(usage_tracker):\n    io = StringIO()\n    usage_tracker.return_value \\\n                 .open.return_value \\\n                 .__enter__.return_value = io\n    return io\n\n\n@pytest.fixture(autouse=True)\ndef usage_tracker_exists(usage_tracker):\n    usage_tracker.return_value \\\n                 .exists.return_value = True\n    return usage_tracker.return_value.exists\n\n\ndef _assert_tracker_updated(usage_tracker_io, pid):\n    usage_tracker_io.seek(0)\n    info = json.load(usage_tracker_io)\n    assert info['pid'] == pid\n\n\ndef _change_tracker(usage_tracker_io, pid):\n    usage_tracker_io.truncate(0)\n    info = {'pid': pid, 'time': 0}\n    json.dump(info, usage_tracker_io)\n    usage_tracker_io.seek(0)\n\n\n@pytest.fixture(autouse=True)\ndef shell_pid(mocker):\n    return mocker.patch('thefuck.entrypoints.not_configured._get_shell_pid',\n                        new_callable=MagicMock)\n\n\n@pytest.fixture(autouse=True)\ndef shell(mocker):\n    shell = mocker.patch('thefuck.entrypoints.not_configured.shell',\n                         new_callable=MagicMock)\n    shell.get_history.return_value = []\n    shell.how_to_configure.return_value = ShellConfiguration(\n        content='eval $(thefuck --alias)',\n        path='/tmp/.bashrc',\n        reload='bash',\n        can_configure_automatically=True)\n    return shell\n\n\n@pytest.fixture(autouse=True)\ndef shell_config(mocker):\n    path_mock = mocker.patch('thefuck.entrypoints.not_configured.Path',\n                             new_callable=MagicMock)\n    return path_mock.return_value \\\n        .expanduser.return_value \\\n        .open.return_value \\\n        .__enter__.return_value\n\n\n@pytest.fixture(autouse=True)\ndef logs(mocker):\n    return mocker.patch('thefuck.entrypoints.not_configured.logs',\n                        new_callable=MagicMock)\n\n\ndef test_for_generic_shell(shell, logs):\n    shell.how_to_configure.return_value = None\n    main()\n    logs.how_to_configure_alias.assert_called_once()\n\n\ndef test_on_first_run(usage_tracker_io, usage_tracker_exists, shell_pid, logs):\n    shell_pid.return_value = 12\n    main()\n    usage_tracker_exists.return_value = False\n    _assert_tracker_updated(usage_tracker_io, 12)\n    logs.how_to_configure_alias.assert_called_once()\n\n\ndef test_on_run_after_other_commands(usage_tracker_io, shell_pid, shell, logs):\n    shell_pid.return_value = 12\n    shell.get_history.return_value = ['fuck', 'ls']\n    _change_tracker(usage_tracker_io, 12)\n    main()\n    logs.how_to_configure_alias.assert_called_once()\n\n\ndef test_on_first_run_from_current_shell(usage_tracker_io, shell_pid,\n                                         shell, logs):\n    shell.get_history.return_value = ['fuck']\n    shell_pid.return_value = 12\n    main()\n    _assert_tracker_updated(usage_tracker_io, 12)\n    logs.how_to_configure_alias.assert_called_once()\n\n\ndef test_when_cant_configure_automatically(shell_pid, shell, logs):\n    shell_pid.return_value = 12\n    shell.how_to_configure.return_value = ShellConfiguration(\n        content='eval $(thefuck --alias)',\n        path='/tmp/.bashrc',\n        reload='bash',\n        can_configure_automatically=False)\n    main()\n    logs.how_to_configure_alias.assert_called_once()\n\n\ndef test_when_already_configured(usage_tracker_io, shell_pid,\n                                 shell, shell_config, logs):\n    shell.get_history.return_value = ['fuck']\n    shell_pid.return_value = 12\n    _change_tracker(usage_tracker_io, 12)\n    shell_config.read.return_value = 'eval $(thefuck --alias)'\n    main()\n    logs.already_configured.assert_called_once()\n\n\ndef test_when_successfully_configured(usage_tracker_io, shell_pid,\n                                      shell, shell_config, logs):\n    shell.get_history.return_value = ['fuck']\n    shell_pid.return_value = 12\n    _change_tracker(usage_tracker_io, 12)\n    shell_config.read.return_value = ''\n    main()\n    shell_config.write.assert_any_call('eval $(thefuck --alias)')\n    logs.configured_successfully.assert_called_once()\n"
  },
  {
    "path": "tests/functional/__init__.py",
    "content": ""
  },
  {
    "path": "tests/functional/conftest.py",
    "content": "import pytest\n\nfrom pytest_docker_pexpect.docker import run as pexpect_docker_run, \\\n    stats as pexpect_docker_stats\n\n\n@pytest.fixture(autouse=True)\ndef build_container_mock(mocker):\n    return mocker.patch('pytest_docker_pexpect.docker.build_container')\n\n\ndef run_side_effect(*args, **kwargs):\n    container_id = pexpect_docker_run(*args, **kwargs)\n    pexpect_docker_stats(container_id)\n    return container_id\n\n\n@pytest.fixture(autouse=True)\ndef run_mock(mocker):\n    return mocker.patch('pytest_docker_pexpect.docker.run', side_effect=run_side_effect)\n"
  },
  {
    "path": "tests/functional/plots.py",
    "content": "def _set_confirmation(proc, require):\n    proc.sendline(u'mkdir -p ~/.thefuck')\n    proc.sendline(\n        u'echo \"require_confirmation = {}\" > ~/.thefuck/settings.py'.format(\n            require))\n\n\ndef with_confirmation(proc, TIMEOUT):\n    \"\"\"Ensures that command can be fixed when confirmation enabled.\"\"\"\n    _set_confirmation(proc, True)\n\n    proc.sendline(u'ehco test')\n\n    proc.sendline(u'fuck')\n    assert proc.expect([TIMEOUT, u'echo test'])\n    assert proc.expect([TIMEOUT, u'enter'])\n    assert proc.expect_exact([TIMEOUT, u'ctrl+c'])\n    proc.send('\\n')\n\n    assert proc.expect([TIMEOUT, u'test'])\n\n\ndef history_changed(proc, TIMEOUT, *to):\n    \"\"\"Ensures that history changed.\"\"\"\n    proc.send('\\033[A')\n    pattern = [TIMEOUT]\n    pattern.extend(to)\n    assert proc.expect(pattern)\n\n\ndef history_not_changed(proc, TIMEOUT):\n    \"\"\"Ensures that history not changed.\"\"\"\n    proc.send('\\033[A')\n    assert proc.expect([TIMEOUT, u'fuck'])\n\n\ndef select_command_with_arrows(proc, TIMEOUT):\n    \"\"\"Ensures that command can be selected with arrow keys.\"\"\"\n    _set_confirmation(proc, True)\n\n    proc.sendline(u'git h')\n    assert proc.expect([TIMEOUT, u\"git: 'h' is not a git command.\"])\n\n    proc.sendline(u'fuck')\n    assert proc.expect([TIMEOUT, u'git show'])\n    proc.send('\\033[B')\n    assert proc.expect([TIMEOUT, u'git push'])\n    proc.send('\\033[B')\n    assert proc.expect([TIMEOUT, u'git help', u'git hook'])\n    proc.send('\\033[A')\n    assert proc.expect([TIMEOUT, u'git push'])\n    proc.send('\\033[B')\n    assert proc.expect([TIMEOUT, u'git help', u'git hook'])\n    proc.send('\\n')\n\n    assert proc.expect([TIMEOUT, u'usage', u'fatal: not a git repository'])\n\n\ndef refuse_with_confirmation(proc, TIMEOUT):\n    \"\"\"Ensures that fix can be refused when confirmation enabled.\"\"\"\n    _set_confirmation(proc, True)\n\n    proc.sendline(u'ehco test')\n\n    proc.sendline(u'fuck')\n    assert proc.expect([TIMEOUT, u'echo test'])\n    assert proc.expect([TIMEOUT, u'enter'])\n    assert proc.expect_exact([TIMEOUT, u'ctrl+c'])\n    proc.send('\\003')\n\n    assert proc.expect([TIMEOUT, u'Aborted'])\n\n\ndef without_confirmation(proc, TIMEOUT):\n    \"\"\"Ensures that command can be fixed when confirmation disabled.\"\"\"\n    _set_confirmation(proc, False)\n\n    proc.sendline(u'ehco test')\n\n    proc.sendline(u'fuck')\n    assert proc.expect([TIMEOUT, u'echo test'])\n    assert proc.expect([TIMEOUT, u'test'])\n\n\ndef how_to_configure(proc, TIMEOUT):\n    proc.sendline(u'fuck')\n    assert proc.expect([TIMEOUT, u\"alias isn't configured\"])\n"
  },
  {
    "path": "tests/functional/test_bash.py",
    "content": "import pytest\nfrom tests.functional.plots import with_confirmation, without_confirmation, \\\n    refuse_with_confirmation, history_changed, history_not_changed, \\\n    select_command_with_arrows, how_to_configure\n\n\npython_3 = (u'thefuck/python3',\n            u'',\n            u'sh')\n\npython_2 = (u'thefuck/python2',\n            u'',\n            u'sh')\n\n\ninit_bashrc = u'''echo '\nexport SHELL=/bin/bash\nexport PS1=\"$ \"\necho > $HISTFILE\neval $(thefuck --alias {})\necho \"instant mode ready: $THEFUCK_INSTANT_MODE\"\n' > ~/.bashrc'''\n\n\n@pytest.fixture(params=[(python_3, False),\n                        (python_3, True),\n                        (python_2, False)])\ndef proc(request, spawnu, TIMEOUT):\n    container, instant_mode = request.param\n    proc = spawnu(*container)\n    proc.sendline(init_bashrc.format(\n        u'--enable-experimental-instant-mode' if instant_mode else ''))\n    proc.sendline(u\"bash\")\n    if instant_mode:\n        assert proc.expect([TIMEOUT, u'instant mode ready: True'])\n    return proc\n\n\n@pytest.mark.functional\ndef test_with_confirmation(proc, TIMEOUT):\n    with_confirmation(proc, TIMEOUT)\n    history_changed(proc, TIMEOUT, u'echo test')\n\n\n@pytest.mark.functional\ndef test_select_command_with_arrows(proc, TIMEOUT):\n    select_command_with_arrows(proc, TIMEOUT)\n    history_changed(proc, TIMEOUT, u'git help', u'git hook')\n\n\n@pytest.mark.functional\ndef test_refuse_with_confirmation(proc, TIMEOUT):\n    refuse_with_confirmation(proc, TIMEOUT)\n    history_not_changed(proc, TIMEOUT)\n\n\n@pytest.mark.functional\ndef test_without_confirmation(proc, TIMEOUT):\n    without_confirmation(proc, TIMEOUT)\n    history_changed(proc, TIMEOUT, u'echo test')\n\n\n@pytest.mark.functional\ndef test_how_to_configure_alias(proc, TIMEOUT):\n    proc.sendline('unset -f fuck')\n    how_to_configure(proc, TIMEOUT)\n"
  },
  {
    "path": "tests/functional/test_fish.py",
    "content": "import pytest\nfrom tests.functional.plots import with_confirmation, without_confirmation, \\\n    refuse_with_confirmation, select_command_with_arrows\n\ncontainers = ((u'thefuck/python3', u'', u'fish'),\n              (u'thefuck/python2', u'', u'fish'))\n\n\n@pytest.fixture(params=containers)\ndef proc(request, spawnu, TIMEOUT):\n    proc = spawnu(*request.param)\n    proc.sendline(u'thefuck --alias > ~/.config/fish/config.fish')\n    proc.sendline(u'fish')\n    return proc\n\n\n@pytest.mark.functional\ndef test_with_confirmation(proc, TIMEOUT):\n    with_confirmation(proc, TIMEOUT)\n\n\n@pytest.mark.functional\ndef test_select_command_with_arrows(proc, TIMEOUT):\n    select_command_with_arrows(proc, TIMEOUT)\n\n\n@pytest.mark.functional\ndef test_refuse_with_confirmation(proc, TIMEOUT):\n    refuse_with_confirmation(proc, TIMEOUT)\n\n\n@pytest.mark.functional\ndef test_without_confirmation(proc, TIMEOUT):\n    without_confirmation(proc, TIMEOUT)\n\n# TODO: ensure that history changes.\n"
  },
  {
    "path": "tests/functional/test_tcsh.py",
    "content": "import pytest\nfrom tests.functional.plots import with_confirmation, without_confirmation, \\\n    refuse_with_confirmation, select_command_with_arrows\n\ncontainers = ((u'thefuck/python3', u'', u'tcsh'),\n              (u'thefuck/python2', u'', u'tcsh'))\n\n\n@pytest.fixture(params=containers)\ndef proc(request, spawnu, TIMEOUT):\n    proc = spawnu(*request.param)\n    proc.sendline(u'tcsh')\n    proc.sendline(u'setenv PYTHONIOENCODING utf8')\n    proc.sendline(u'eval `thefuck --alias`')\n    return proc\n\n\n@pytest.mark.functional\ndef test_with_confirmation(proc, TIMEOUT):\n    with_confirmation(proc, TIMEOUT)\n\n\n@pytest.mark.functional\ndef test_select_command_with_arrows(proc, TIMEOUT):\n    select_command_with_arrows(proc, TIMEOUT)\n\n\n@pytest.mark.functional\ndef test_refuse_with_confirmation(proc, TIMEOUT):\n    refuse_with_confirmation(proc, TIMEOUT)\n\n\n@pytest.mark.functional\ndef test_without_confirmation(proc, TIMEOUT):\n    without_confirmation(proc, TIMEOUT)\n\n# TODO: ensure that history changes.\n"
  },
  {
    "path": "tests/functional/test_zsh.py",
    "content": "import pytest\nfrom tests.functional.plots import with_confirmation, without_confirmation, \\\n    refuse_with_confirmation, history_changed, history_not_changed, \\\n    select_command_with_arrows, how_to_configure\n\n\npython_3 = (u'thefuck/python3', u'', u'sh')\npython_2 = (u'thefuck/python2', u'', u'sh')\n\n\ninit_zshrc = u'''echo '\nexport SHELL=/usr/bin/zsh\nexport HISTFILE=~/.zsh_history\necho > $HISTFILE\nexport SAVEHIST=100\nexport HISTSIZE=100\neval $(thefuck --alias {})\nsetopt INC_APPEND_HISTORY\necho \"instant mode ready: $THEFUCK_INSTANT_MODE\"\n' > ~/.zshrc'''\n\n\n@pytest.fixture(params=[(python_3, False),\n                        (python_3, True),\n                        (python_2, False)])\ndef proc(request, spawnu, TIMEOUT):\n    container, instant_mode = request.param\n    proc = spawnu(*container)\n    proc.sendline(init_zshrc.format(\n        u'--enable-experimental-instant-mode' if instant_mode else ''))\n    proc.sendline(u\"zsh\")\n    if instant_mode:\n        assert proc.expect([TIMEOUT, u'instant mode ready: True'])\n    return proc\n\n\n@pytest.mark.functional\ndef test_with_confirmation(proc, TIMEOUT):\n    with_confirmation(proc, TIMEOUT)\n    history_changed(proc, TIMEOUT, u'echo test')\n\n\n@pytest.mark.functional\ndef test_select_command_with_arrows(proc, TIMEOUT):\n    select_command_with_arrows(proc, TIMEOUT)\n    history_changed(proc, TIMEOUT, u'git help', u'git hook')\n\n\n@pytest.mark.functional\ndef test_refuse_with_confirmation(proc, TIMEOUT):\n    refuse_with_confirmation(proc, TIMEOUT)\n    history_not_changed(proc, TIMEOUT)\n\n\n@pytest.mark.functional\ndef test_without_confirmation(proc, TIMEOUT):\n    without_confirmation(proc, TIMEOUT)\n    history_changed(proc, TIMEOUT, u'echo test')\n\n\n@pytest.mark.functional\ndef test_how_to_configure_alias(proc, TIMEOUT):\n    proc.sendline(u'unfunction fuck')\n    how_to_configure(proc, TIMEOUT)\n"
  },
  {
    "path": "tests/output_readers/test_rerun.py",
    "content": "# -*- encoding: utf-8 -*-\n\nimport pytest\nimport sys\nfrom mock import Mock, patch\nfrom psutil import AccessDenied, TimeoutExpired\n\nfrom thefuck.output_readers import rerun\n\n\nclass TestRerun(object):\n    def setup_method(self, test_method):\n        self.patcher = patch('thefuck.output_readers.rerun.Process')\n        process_mock = self.patcher.start()\n        self.proc_mock = process_mock.return_value = Mock()\n\n    def teardown_method(self, test_method):\n        self.patcher.stop()\n\n    @patch('thefuck.output_readers.rerun._wait_output', return_value=False)\n    @patch('thefuck.output_readers.rerun.Popen')\n    def test_get_output(self, popen_mock, wait_output_mock):\n        popen_mock.return_value.stdout.read.return_value = b'output'\n        assert rerun.get_output('', '') is None\n        wait_output_mock.assert_called_once()\n\n    @patch('thefuck.output_readers.rerun.Popen')\n    def test_get_output_invalid_continuation_byte(self, popen_mock):\n        output = b'ls: illegal option -- \\xc3\\nusage: ls [-@ABC...] [file ...]\\n'\n        expected = u'ls: illegal option -- \\ufffd\\nusage: ls [-@ABC...] [file ...]\\n'\n        popen_mock.return_value.stdout.read.return_value = output\n        actual = rerun.get_output('', '')\n        assert actual == expected\n\n    @pytest.mark.skipif(sys.platform == 'win32', reason=\"skip when running on Windows\")\n    @patch('thefuck.output_readers.rerun._wait_output')\n    def test_get_output_unicode_misspell(self, wait_output_mock):\n        rerun.get_output(u'pácman', u'pácman')\n        wait_output_mock.assert_called_once()\n\n    def test_wait_output_is_slow(self, settings):\n        assert rerun._wait_output(Mock(), True)\n        self.proc_mock.wait.assert_called_once_with(settings.wait_slow_command)\n\n    def test_wait_output_is_not_slow(self, settings):\n        assert rerun._wait_output(Mock(), False)\n        self.proc_mock.wait.assert_called_once_with(settings.wait_command)\n\n    @patch('thefuck.output_readers.rerun._kill_process')\n    def test_wait_output_timeout(self, kill_process_mock):\n        self.proc_mock.wait.side_effect = TimeoutExpired(3)\n        self.proc_mock.children.return_value = []\n        assert not rerun._wait_output(Mock(), False)\n        kill_process_mock.assert_called_once_with(self.proc_mock)\n\n    @patch('thefuck.output_readers.rerun._kill_process')\n    def test_wait_output_timeout_children(self, kill_process_mock):\n        self.proc_mock.wait.side_effect = TimeoutExpired(3)\n        self.proc_mock.children.return_value = [Mock()] * 2\n        assert not rerun._wait_output(Mock(), False)\n        assert kill_process_mock.call_count == 3\n\n    def test_kill_process(self):\n        proc = Mock()\n        rerun._kill_process(proc)\n        proc.kill.assert_called_once_with()\n\n    @patch('thefuck.output_readers.rerun.logs')\n    def test_kill_process_access_denied(self, logs_mock):\n        proc = Mock()\n        proc.kill.side_effect = AccessDenied()\n        rerun._kill_process(proc)\n        proc.kill.assert_called_once_with()\n        logs_mock.debug.assert_called_once()\n"
  },
  {
    "path": "tests/rules/__init__.py",
    "content": ""
  },
  {
    "path": "tests/rules/test_adb_unknown_command.py",
    "content": "import pytest\nfrom thefuck.rules.adb_unknown_command import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output():\n    return '''Android Debug Bridge version 1.0.31\n\n -d                            - directs command to the only connected USB device\n                                 returns an error if more than one USB device is present.\n -e                            - directs command to the only running emulator.\n                                 returns an error if more than one emulator is running.\n -s <specific device>          - directs command to the device or emulator with the given\n                                 serial number or qualifier. Overrides ANDROID_SERIAL\n                                 environment variable.\n'''\n\n\n@pytest.mark.parametrize('script', [\n    ('adb lgcat'),\n    ('adb puhs')])\ndef test_match(output, script):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script', [\n    'git branch foo',\n    'abd push'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script, new_command', [\n    ('adb puhs test.bin /sdcard/test.bin', 'adb push test.bin /sdcard/test.bin'),\n    ('adb -s 1111 logcta', 'adb -s 1111 logcat'),\n    ('adb -P 666 pulll /sdcard/test.bin', 'adb -P 666 pull /sdcard/test.bin'),\n    ('adb -d logcatt', 'adb -d logcat'),\n    ('adb -e reboott', 'adb -e reboot')])\ndef test_get_new_command(script, output, new_command):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_ag_literal.py",
    "content": "import pytest\nfrom thefuck.rules.ag_literal import get_new_command, match\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output():\n    return ('ERR: Bad regex! pcre_compile() failed at position 1: missing )\\n'\n            'If you meant to search for a literal string, run ag with -Q\\n')\n\n\n@pytest.mark.parametrize('script', ['ag \\\\('])\ndef test_match(script, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script', ['ag foo'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script, new_cmd', [\n    ('ag \\\\(', 'ag -Q \\\\(')])\ndef test_get_new_command(script, new_cmd, output):\n    assert get_new_command((Command(script, output))) == new_cmd\n"
  },
  {
    "path": "tests/rules/test_apt_get.py",
    "content": "import pytest\nfrom thefuck.rules.apt_get import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command, packages', [\n    (Command('vim', 'vim: command not found'),\n     [('vim', 'main'), ('vim-tiny', 'main')]),\n    (Command('sudo vim', 'vim: command not found'),\n     [('vim', 'main'), ('vim-tiny', 'main')]),\n    (Command('vim', \"The program 'vim' is currently not installed. You can install it by typing: sudo apt install vim\"),\n     [('vim', 'main'), ('vim-tiny', 'main')])])\ndef test_match(mocker, command, packages):\n    mocker.patch('thefuck.rules.apt_get.which', return_value=None)\n    mocker.patch('thefuck.rules.apt_get._get_packages',\n                 create=True, return_value=packages)\n\n    assert match(command)\n\n\n@pytest.mark.parametrize('command, packages, which', [\n    (Command('a_bad_cmd', 'a_bad_cmd: command not found'),\n     [], None),\n    (Command('vim', ''), [], None),\n    (Command('', ''), [], None),\n    (Command('vim', 'vim: command not found'),\n     ['vim'], '/usr/bin/vim'),\n    (Command('sudo vim', 'vim: command not found'),\n     ['vim'], '/usr/bin/vim')])\ndef test_not_match(mocker, command, packages, which):\n    mocker.patch('thefuck.rules.apt_get.which', return_value=which)\n    mocker.patch('thefuck.rules.apt_get._get_packages',\n                 create=True, return_value=packages)\n\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command, packages', [\n    (Command('vim', ''), 'sudo apt-get install vim && vim',\n     [('vim', 'main'), ('vim-tiny', 'main')]),\n    (Command('convert', ''), 'sudo apt-get install imagemagick && convert',\n     [('imagemagick', 'main'),\n      ('graphicsmagick-imagemagick-compat', 'universe')]),\n    (Command('sudo vim', ''), 'sudo apt-get install vim && sudo vim',\n     [('vim', 'main'), ('vim-tiny', 'main')]),\n    (Command('sudo convert', ''), 'sudo apt-get install imagemagick && sudo convert',\n     [('imagemagick', 'main'),\n      ('graphicsmagick-imagemagick-compat', 'universe')])])\ndef test_get_new_command(mocker, command, new_command, packages):\n    mocker.patch('thefuck.rules.apt_get._get_packages',\n                 create=True, return_value=packages)\n\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_apt_get_search.py",
    "content": "import pytest\nfrom thefuck.rules.apt_get_search import get_new_command, match\nfrom thefuck.types import Command\n\n\ndef test_match():\n    assert match(Command('apt-get search foo', ''))\n\n\n@pytest.mark.parametrize('command', [\n    Command('apt-cache search foo', ''),\n    Command('aptitude search foo', ''),\n    Command('apt search foo', ''),\n    Command('apt-get install foo', ''),\n    Command('apt-get source foo', ''),\n    Command('apt-get clean', ''),\n    Command('apt-get remove', ''),\n    Command('apt-get update', '')\n])\ndef test_not_match(command):\n    assert not match(command)\n\n\ndef test_get_new_command():\n    new_command = get_new_command(Command('apt-get search foo', ''))\n    assert new_command == 'apt-cache search foo'\n"
  },
  {
    "path": "tests/rules/test_apt_invalid_operation.py",
    "content": "from io import BytesIO\nimport pytest\nfrom thefuck.types import Command\nfrom thefuck.rules.apt_invalid_operation import match, get_new_command, \\\n    _get_operations\n\ninvalid_operation = 'E: Invalid operation {}'.format\napt_help = b'''apt 1.0.10.2ubuntu1 for amd64 compiled on Oct  5 2015 15:55:05\nUsage: apt [options] command\n\nCLI for apt.\nBasic commands:\n list - list packages based on package names\n search - search in package descriptions\n show - show package details\n\n update - update list of available packages\n\n install - install packages\n remove  - remove packages\n\n upgrade - upgrade the system by installing/upgrading packages\n full-upgrade - upgrade the system by removing/installing/upgrading packages\n\n edit-sources - edit the source information file\n'''\napt_operations = ['list', 'search', 'show', 'update', 'install', 'remove',\n                  'upgrade', 'full-upgrade', 'edit-sources']\n\napt_get_help = b'''apt 1.0.10.2ubuntu1 for amd64 compiled on Oct  5 2015 15:55:05\nUsage: apt-get [options] command\n       apt-get [options] install|remove pkg1 [pkg2 ...]\n       apt-get [options] source pkg1 [pkg2 ...]\n\napt-get is a simple command line interface for downloading and\ninstalling packages. The most frequently used commands are update\nand install.\n\nCommands:\n   update - Retrieve new lists of packages\n   upgrade - Perform an upgrade\n   install - Install new packages (pkg is libc6 not libc6.deb)\n   remove - Remove packages\n   autoremove - Remove automatically all unused packages\n   purge - Remove packages and config files\n   source - Download source archives\n   build-dep - Configure build-dependencies for source packages\n   dist-upgrade - Distribution upgrade, see apt-get(8)\n   dselect-upgrade - Follow dselect selections\n   clean - Erase downloaded archive files\n   autoclean - Erase old downloaded archive files\n   check - Verify that there are no broken dependencies\n   changelog - Download and display the changelog for the given package\n   download - Download the binary package into the current directory\n\nOptions:\n  -h  This help text.\n  -q  Loggable output - no progress indicator\n  -qq No output except for errors\n  -d  Download only - do NOT install or unpack archives\n  -s  No-act. Perform ordering simulation\n  -y  Assume Yes to all queries and do not prompt\n  -f  Attempt to correct a system with broken dependencies in place\n  -m  Attempt to continue if archives are unlocatable\n  -u  Show a list of upgraded packages as well\n  -b  Build the source package after fetching it\n  -V  Show verbose version numbers\n  -c=? Read this configuration file\n  -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\nSee the apt-get(8), sources.list(5) and apt.conf(5) manual\npages for more information and options.\n                       This APT has Super Cow Powers.\n'''\napt_get_operations = ['update', 'upgrade', 'install', 'remove', 'autoremove',\n                      'purge', 'source', 'build-dep', 'dist-upgrade',\n                      'dselect-upgrade', 'clean', 'autoclean', 'check',\n                      'changelog', 'download']\n\nnew_apt_get_help = b'''apt 1.6.12 (amd64)\nUsage: apt-get [options] command\n       apt-get [options] install|remove pkg1 [pkg2 ...]\n       apt-get [options] source pkg1 [pkg2 ...]\n\napt-get is a command line interface for retrieval of packages\nand information about them from authenticated sources and\nfor installation, upgrade and removal of packages together\nwith their dependencies.\n\nMost used commands:\n  update - Retrieve new lists of packages\n  upgrade - Perform an upgrade\n  install - Install new packages (pkg is libc6 not libc6.deb)\n  remove - Remove packages\n  purge - Remove packages and config files\n  autoremove - Remove automatically all unused packages\n  dist-upgrade - Distribution upgrade, see apt-get(8)\n  dselect-upgrade - Follow dselect selections\n  build-dep - Configure build-dependencies for source packages\n  clean - Erase downloaded archive files\n  autoclean - Erase old downloaded archive files\n  check - Verify that there are no broken dependencies\n  source - Download source archives\n  download - Download the binary package into the current directory\n  changelog - Download and display the changelog for the given package\n\nSee apt-get(8) for more information about the available commands.\nConfiguration options and syntax is detailed in apt.conf(5).\nInformation about how to configure sources can be found in sources.list(5).\nPackage and version choices can be expressed via apt_preferences(5).\nSecurity details are available in apt-secure(8).\n                                        This APT has Super Cow Powers.\n'''\nnew_apt_get_operations = ['update', 'upgrade', 'install', 'remove', 'purge',\n                          'autoremove', 'dist-upgrade', 'dselect-upgrade',\n                          'build-dep', 'clean', 'autoclean', 'check',\n                          'source', 'download', 'changelog']\n\n\n@pytest.mark.parametrize('script, output', [\n    ('apt', invalid_operation('saerch')),\n    ('apt-get', invalid_operation('isntall')),\n    ('apt-cache', invalid_operation('rumove'))])\ndef test_match(script, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output', [\n    ('vim', invalid_operation('vim')),\n    ('apt-get', \"\")])\ndef test_not_match(script, output):\n    assert not match(Command(script, output))\n\n\n@pytest.fixture\ndef set_help(mocker):\n    mock = mocker.patch('subprocess.Popen')\n\n    def _set_text(text):\n        mock.return_value.stdout = BytesIO(text)\n\n    return _set_text\n\n\n@pytest.mark.parametrize('app, help_text, operations', [\n    ('apt', apt_help, apt_operations),\n    ('apt-get', apt_get_help, apt_get_operations),\n    ('apt-get', new_apt_get_help, new_apt_get_operations)\n])\ndef test_get_operations(set_help, app, help_text, operations):\n    set_help(help_text)\n    assert _get_operations(app) == operations\n\n\n@pytest.mark.parametrize('script, output, help_text, result', [\n    ('apt-get isntall vim', invalid_operation('isntall'),\n     apt_get_help, 'apt-get install vim'),\n    ('apt saerch vim', invalid_operation('saerch'),\n     apt_help, 'apt search vim'),\n    ('apt uninstall vim', invalid_operation('uninstall'),\n     apt_help, 'apt remove vim'),\n])\ndef test_get_new_command(set_help, output, script, help_text, result):\n    set_help(help_text)\n    assert get_new_command(Command(script, output))[0] == result\n"
  },
  {
    "path": "tests/rules/test_apt_list_upgradable.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport pytest\nfrom thefuck.rules.apt_list_upgradable import get_new_command, match\nfrom thefuck.types import Command\n\nfull_english_output = '''\nHit:1 http://us.archive.ubuntu.com/ubuntu zesty InRelease\nHit:2 http://us.archive.ubuntu.com/ubuntu zesty-updates InRelease\nGet:3 http://us.archive.ubuntu.com/ubuntu zesty-backports InRelease [89.2 kB]\nHit:4 http://security.ubuntu.com/ubuntu zesty-security InRelease\nHit:5 http://ppa.launchpad.net/ubuntu-mozilla-daily/ppa/ubuntu zesty InRelease\nHit:6 https://download.docker.com/linux/ubuntu zesty InRelease\nHit:7 https://cli-assets.heroku.com/branches/stable/apt ./ InRelease\nFetched 89.2 kB in 0s (122 kB/s)\nReading package lists... Done\nBuilding dependency tree\nReading state information... Done\n8 packages can be upgraded. Run 'apt list --upgradable' to see them.\n'''\n\nmatch_output = [\n    full_english_output,\n    'Führen Sie »apt list --upgradable« aus, um sie anzuzeigen.'  # German\n]\n\nno_match_output = '''\nHit:1 http://us.archive.ubuntu.com/ubuntu zesty InRelease\nGet:2 http://us.archive.ubuntu.com/ubuntu zesty-updates InRelease [89.2 kB]\nGet:3 http://us.archive.ubuntu.com/ubuntu zesty-backports InRelease [89.2 kB]\nGet:4 http://security.ubuntu.com/ubuntu zesty-security InRelease [89.2 kB]\nHit:5 https://cli-assets.heroku.com/branches/stable/apt ./ InRelease\nHit:6 http://ppa.launchpad.net/ubuntu-mozilla-daily/ppa/ubuntu zesty InRelease\nHit:7 https://download.docker.com/linux/ubuntu zesty InRelease\nGet:8 http://us.archive.ubuntu.com/ubuntu zesty-updates/main i386 Packages [232 kB]\nGet:9 http://us.archive.ubuntu.com/ubuntu zesty-updates/main amd64 Packages [235 kB]\nGet:10 http://us.archive.ubuntu.com/ubuntu zesty-updates/main amd64 DEP-11 Metadata [55.2 kB]\nGet:11 http://us.archive.ubuntu.com/ubuntu zesty-updates/main DEP-11 64x64 Icons [32.3 kB]\nGet:12 http://us.archive.ubuntu.com/ubuntu zesty-updates/universe amd64 Packages [156 kB]\nGet:13 http://us.archive.ubuntu.com/ubuntu zesty-updates/universe i386 Packages [156 kB]\nGet:14 http://us.archive.ubuntu.com/ubuntu zesty-updates/universe amd64 DEP-11 Metadata [175 kB]\nGet:15 http://us.archive.ubuntu.com/ubuntu zesty-updates/universe DEP-11 64x64 Icons [253 kB]\nGet:16 http://us.archive.ubuntu.com/ubuntu zesty-updates/multiverse amd64 DEP-11 Metadata [5,840 B]\nGet:17 http://us.archive.ubuntu.com/ubuntu zesty-backports/universe amd64 DEP-11 Metadata [4,588 B]\nGet:18 http://security.ubuntu.com/ubuntu zesty-security/main amd64 DEP-11 Metadata [12.7 kB]\nGet:19 http://security.ubuntu.com/ubuntu zesty-security/main DEP-11 64x64 Icons [17.6 kB]\nGet:20 http://security.ubuntu.com/ubuntu zesty-security/universe amd64 DEP-11 Metadata [21.6 kB]\nGet:21 http://security.ubuntu.com/ubuntu zesty-security/universe DEP-11 64x64 Icons [47.7 kB]\nGet:22 http://security.ubuntu.com/ubuntu zesty-security/multiverse amd64 DEP-11 Metadata [208 B]\nFetched 1,673 kB in 0s (1,716 kB/s)\nReading package lists... Done\nBuilding dependency tree\nReading state information... Done\nAll packages are up to date.\n'''\n\n\n@pytest.mark.parametrize('output', match_output)\ndef test_match(output):\n    assert match(Command('sudo apt update', output))\n\n\n@pytest.mark.parametrize('command', [\n    Command('apt-cache search foo', ''),\n    Command('aptitude search foo', ''),\n    Command('apt search foo', ''),\n    Command('apt-get install foo', ''),\n    Command('apt-get source foo', ''),\n    Command('apt-get clean', ''),\n    Command('apt-get remove', ''),\n    Command('apt-get update', ''),\n    Command('sudo apt update', no_match_output)\n])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('output', match_output)\ndef test_get_new_command(output):\n    new_command = get_new_command(Command('sudo apt update', output))\n    assert new_command == 'sudo apt list --upgradable'\n\n    new_command = get_new_command(Command('apt update', output))\n    assert new_command == 'apt list --upgradable'\n"
  },
  {
    "path": "tests/rules/test_apt_upgrade.py",
    "content": "import pytest\nfrom thefuck.rules.apt_upgrade import get_new_command, match\nfrom thefuck.types import Command\n\nmatch_output = '''\nListing... Done\nheroku/stable 6.15.2-1 amd64 [upgradable from: 6.14.43-1]\nresolvconf/zesty-updates,zesty-updates 1.79ubuntu4.1 all [upgradable from: 1.79ubuntu4]\nsquashfs-tools/zesty-updates 1:4.3-3ubuntu2.17.04.1 amd64 [upgradable from: 1:4.3-3ubuntu2]\nunattended-upgrades/zesty-updates,zesty-updates 0.93.1ubuntu2.4 all [upgradable from: 0.93.1ubuntu2.3]\n'''\n\nno_match_output = '''\nListing... Done\n'''\n\n\ndef test_match():\n    assert match(Command('apt list --upgradable', match_output))\n    assert match(Command('sudo apt list --upgradable', match_output))\n\n\n@pytest.mark.parametrize('command', [\n    Command('apt list --upgradable', no_match_output),\n    Command('sudo apt list --upgradable', no_match_output)\n])\ndef test_not_match(command):\n    assert not match(command)\n\n\ndef test_get_new_command():\n    new_command = get_new_command(Command('apt list --upgradable', match_output))\n    assert new_command == 'apt upgrade'\n\n    new_command = get_new_command(Command('sudo apt list --upgradable', match_output))\n    assert new_command == 'sudo apt upgrade'\n"
  },
  {
    "path": "tests/rules/test_aws_cli.py",
    "content": "import pytest\n\nfrom thefuck.rules.aws_cli import match, get_new_command\nfrom thefuck.types import Command\n\n\nno_suggestions = '''\\\nusage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]\nTo see help text, you can run:\n\n  aws help\n  aws <command> help\n  aws <command> <subcommand> help\naws: error: argument command: Invalid choice, valid choices are:\n\ndynamodb                                 | dynamodbstreams\nec2                                      | ecr\n'''\n\n\nmisspelled_command = '''\\\nusage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]\nTo see help text, you can run:\n\n  aws help\n  aws <command> help\n  aws <command> <subcommand> help\naws: error: argument command: Invalid choice, valid choices are:\n\ndynamodb                                 | dynamodbstreams\nec2                                      | ecr\n\n\nInvalid choice: 'dynamdb', maybe you meant:\n\n  * dynamodb\n'''\n\n\nmisspelled_subcommand = '''\\\nusage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]\nTo see help text, you can run:\n\n  aws help\n  aws <command> help\n  aws <command> <subcommand> help\naws: error: argument operation: Invalid choice, valid choices are:\n\nquery                                    | scan\nupdate-item                              | update-table\n\n\nInvalid choice: 'scn', maybe you meant:\n\n  * scan\n'''\n\n\nmisspelled_subcommand_with_multiple_options = '''\\\nusage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]\nTo see help text, you can run:\n\n  aws help\n  aws <command> help\n  aws <command> <subcommand> help\naws: error: argument operation: Invalid choice, valid choices are:\n\ndescribe-table                           | get-item\nlist-tables                              | put-item\n\n\nInvalid choice: 't-item', maybe you meant:\n\n  * put-item\n  * get-item\n'''\n\n\n@pytest.mark.parametrize('command', [\n    Command('aws dynamdb scan', misspelled_command),\n    Command('aws dynamodb scn', misspelled_subcommand),\n    Command('aws dynamodb t-item',\n            misspelled_subcommand_with_multiple_options)])\ndef test_match(command):\n    assert match(command)\n\n\ndef test_not_match():\n    assert not match(Command('aws dynamodb invalid', no_suggestions))\n\n\n@pytest.mark.parametrize('command, result', [\n    (Command('aws dynamdb scan', misspelled_command),\n     ['aws dynamodb scan']),\n    (Command('aws dynamodb scn', misspelled_subcommand),\n     ['aws dynamodb scan']),\n    (Command('aws dynamodb t-item',\n             misspelled_subcommand_with_multiple_options),\n     ['aws dynamodb put-item', 'aws dynamodb get-item'])])\ndef test_get_new_command(command, result):\n    assert get_new_command(command) == result\n"
  },
  {
    "path": "tests/rules/test_az_cli.py",
    "content": "import pytest\n\nfrom thefuck.rules.az_cli import match, get_new_command\nfrom thefuck.types import Command\n\n\nno_suggestions = '''\\\naz provider: error: the following arguments are required: _subcommand\nusage: az provider [-h] {list,show,register,unregister,operation} ...\n'''\n\n\nmisspelled_command = '''\\\naz: 'providers' is not in the 'az' command group. See 'az --help'.\n\nThe most similar choice to 'providers' is:\n    provider\n'''\n\nmisspelled_subcommand = '''\\\naz provider: 'lis' is not in the 'az provider' command group. See 'az provider --help'.\n\nThe most similar choice to 'lis' is:\n    list\n'''\n\n\n@pytest.mark.parametrize('command', [\n    Command('az providers', misspelled_command),\n    Command('az provider lis', misspelled_subcommand)])\ndef test_match(command):\n    assert match(command)\n\n\ndef test_not_match():\n    assert not match(Command('az provider', no_suggestions))\n\n\n@pytest.mark.parametrize('command, result', [\n    (Command('az providers list', misspelled_command), ['az provider list']),\n    (Command('az provider lis', misspelled_subcommand), ['az provider list'])\n])\ndef test_get_new_command(command, result):\n    assert get_new_command(command) == result\n"
  },
  {
    "path": "tests/rules/test_brew_cask_dependency.py",
    "content": "import pytest\nfrom thefuck.rules.brew_cask_dependency import match, get_new_command\nfrom thefuck.types import Command\n\n\noutput = '''sshfs: OsxfuseRequirement unsatisfied!\n\nYou can install with Homebrew-Cask:\n  brew cask install osxfuse\n\nYou can download from:\n  https://osxfuse.github.io/\nError: An unsatisfied requirement failed this build.'''\n\n\ndef test_match():\n    command = Command('brew install sshfs', output)\n    assert match(command)\n\n\n@pytest.mark.parametrize('script, output', [\n    ('brew link sshfs', output),\n    ('cat output', output),\n    ('brew install sshfs', '')])\ndef test_not_match(script, output):\n    command = Command(script, output)\n    assert not match(command)\n\n\n@pytest.mark.parametrize('before, after', [\n    ('brew install sshfs',\n     'brew cask install osxfuse && brew install sshfs')])\ndef test_get_new_command(before, after):\n    command = Command(before, output)\n    assert get_new_command(command) == after\n"
  },
  {
    "path": "tests/rules/test_brew_install.py",
    "content": "import pytest\nfrom thefuck.rules.brew_install import match, get_new_command, _get_suggestions\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef brew_no_available_formula_one():\n    return '''Warning: No available formula with the name \"giss\". Did you mean gist?'''\n\n\n@pytest.fixture\ndef brew_no_available_formula_two():\n    return '''Warning: No available formula with the name \"elasticserar\". Did you mean elasticsearch or elasticsearch@6?'''\n\n\n@pytest.fixture\ndef brew_no_available_formula_three():\n    return '''Warning: No available formula with the name \"gitt\". Did you mean git, gitg or gist?'''\n\n\n@pytest.fixture\ndef brew_install_no_argument():\n    return '''Install a formula or cask. Additional options specific to a formula may be'''\n\n\n@pytest.fixture\ndef brew_already_installed():\n    return '''Warning: git-2.3.5 already installed'''\n\n\ndef test_suggestions():\n    assert _get_suggestions(\"one\") == ['one']\n    assert _get_suggestions(\"one or two\") == ['one', 'two']\n    assert _get_suggestions(\"one, two or three\") == ['one', 'two', 'three']\n\n\ndef test_match(brew_no_available_formula_one, brew_no_available_formula_two,\n               brew_no_available_formula_three, brew_already_installed,\n               brew_install_no_argument):\n    assert match(Command('brew install giss',\n                         brew_no_available_formula_one))\n    assert match(Command('brew install elasticserar',\n                         brew_no_available_formula_two))\n    assert match(Command('brew install gitt',\n                         brew_no_available_formula_three))\n    assert not match(Command('brew install git',\n                             brew_already_installed))\n    assert not match(Command('brew install', brew_install_no_argument))\n\n\ndef test_get_new_command(brew_no_available_formula_one, brew_no_available_formula_two,\n                         brew_no_available_formula_three):\n    assert get_new_command(Command('brew install giss',\n                                   brew_no_available_formula_one))\\\n        == ['brew install gist']\n    assert get_new_command(Command('brew install elasticsear',\n                                   brew_no_available_formula_two))\\\n        == ['brew install elasticsearch', 'brew install elasticsearch@6']\n    assert get_new_command(Command('brew install gitt',\n                                   brew_no_available_formula_three))\\\n        == ['brew install git', 'brew install gitg', 'brew install gist']\n\n    assert get_new_command(Command('brew install aa',\n                                   brew_no_available_formula_one))\\\n        != 'brew install aha'\n"
  },
  {
    "path": "tests/rules/test_brew_link.py",
    "content": "import pytest\nfrom thefuck.types import Command\nfrom thefuck.rules.brew_link import get_new_command, match\n\n\n@pytest.fixture\ndef output():\n    return (\"Error: Could not symlink bin/gcp\\n\"\n            \"Target /usr/local/bin/gcp\\n\"\n            \"already exists. You may want to remove it:\\n\"\n            \"  rm '/usr/local/bin/gcp'\\n\"\n            \"\\n\"\n            \"To force the link and overwrite all conflicting files:\\n\"\n            \"  brew link --overwrite coreutils\\n\"\n            \"\\n\"\n            \"To list all files that would be deleted:\\n\"\n            \"  brew link --overwrite --dry-run coreutils\\n\")\n\n\n@pytest.fixture\ndef new_command(formula):\n    return 'brew link --overwrite --dry-run {}'.format(formula)\n\n\n@pytest.mark.parametrize('script', ['brew link coreutils', 'brew ln coreutils'])\ndef test_match(output, script):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script', ['brew link coreutils'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script, formula, ', [('brew link coreutils', 'coreutils')])\ndef test_get_new_command(output, new_command, script, formula):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_brew_reinstall.py",
    "content": "import pytest\nfrom thefuck.types import Command\nfrom thefuck.rules.brew_reinstall import get_new_command, match\n\n\noutput = (\"Warning: thefuck 9.9 is already installed and up-to-date\\nTo \"\n          \"reinstall 9.9, run `brew reinstall thefuck`\")\n\n\ndef test_match():\n    command = Command('brew install thefuck', output)\n    assert match(command)\n\n\n@pytest.mark.parametrize('script', [\n    'brew reinstall thefuck',\n    'brew install foo'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script, formula, ', [\n    ('brew install foo', 'foo'),\n    ('brew install bar zap', 'bar zap')])\ndef test_get_new_command(script, formula):\n    command = Command(script, output)\n    new_command = 'brew reinstall {}'.format(formula)\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_brew_uninstall.py",
    "content": "import pytest\nfrom thefuck.types import Command\nfrom thefuck.rules.brew_uninstall import get_new_command, match\n\n\n@pytest.fixture\ndef output():\n    return (\"Uninstalling /usr/local/Cellar/tbb/4.4-20160916... (118 files, 1.9M)\\n\"\n            \"tbb 4.4-20160526, 4.4-20160722 are still installed.\\n\"\n            \"Remove all versions with `brew uninstall --force tbb`.\\n\")\n\n\n@pytest.fixture\ndef new_command(formula):\n    return 'brew uninstall --force {}'.format(formula)\n\n\n@pytest.mark.parametrize('script', ['brew uninstall tbb', 'brew rm tbb', 'brew remove tbb'])\ndef test_match(output, script):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script', ['brew remove gnuplot'])\ndef test_not_match(script):\n    output = 'Uninstalling /usr/local/Cellar/gnuplot/5.0.4_1... (44 files, 2.3M)\\n'\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, formula, ', [('brew uninstall tbb', 'tbb')])\ndef test_get_new_command(output, new_command, script, formula):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_brew_unknown_command.py",
    "content": "import pytest\nfrom thefuck.rules.brew_unknown_command import match, get_new_command\nfrom thefuck.rules.brew_unknown_command import _brew_commands\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef brew_unknown_cmd():\n    return '''Error: Unknown command: inst'''\n\n\n@pytest.fixture\ndef brew_unknown_cmd2():\n    return '''Error: Unknown command: instaa'''\n\n\ndef test_match(brew_unknown_cmd):\n    assert match(Command('brew inst', brew_unknown_cmd))\n    for command in _brew_commands():\n        assert not match(Command('brew ' + command, ''))\n\n\ndef test_get_new_command(brew_unknown_cmd, brew_unknown_cmd2):\n    assert (get_new_command(Command('brew inst', brew_unknown_cmd))\n            == ['brew list', 'brew install', 'brew uninstall'])\n\n    cmds = get_new_command(Command('brew instaa', brew_unknown_cmd2))\n    assert 'brew install' in cmds\n    assert 'brew uninstall' in cmds\n"
  },
  {
    "path": "tests/rules/test_brew_update_formula.py",
    "content": "import pytest\nfrom thefuck.types import Command\nfrom thefuck.rules.brew_update_formula import get_new_command, match\n\n\noutput = (\"Error: This command updates brew itself, and does not take formula\"\n          \" names.\\nUse `brew upgrade thefuck`.\")\n\n\ndef test_match():\n    command = Command('brew update thefuck', output)\n    assert match(command)\n\n\n@pytest.mark.parametrize('script', [\n    'brew upgrade foo',\n    'brew update'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script, formula, ', [\n    ('brew update foo', 'foo'),\n    ('brew update bar zap', 'bar zap')])\ndef test_get_new_command(script, formula):\n    command = Command(script, output)\n    new_command = 'brew upgrade {}'.format(formula)\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_cargo_no_command.py",
    "content": "import pytest\nfrom thefuck.rules.cargo_no_command import match, get_new_command\nfrom thefuck.types import Command\n\n\nno_such_subcommand_old = \"\"\"No such subcommand\n\n        Did you mean `build`?\n\"\"\"\n\nno_such_subcommand = \"\"\"error: no such subcommand\n\n\\tDid you mean `build`?\n\"\"\"\n\n\n@pytest.mark.parametrize('command', [\n    Command('cargo buid', no_such_subcommand_old),\n    Command('cargo buils', no_such_subcommand)])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('cargo buid', no_such_subcommand_old), 'cargo build'),\n    (Command('cargo buils', no_such_subcommand), 'cargo build')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_cat_dir.py",
    "content": "import pytest\nfrom thefuck.rules.cat_dir import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef isdir(mocker):\n    return mocker.patch('thefuck.rules.cat_dir'\n                        '.os.path.isdir')\n\n\n@pytest.mark.parametrize('command', [\n    Command('cat foo', 'cat: foo: Is a directory\\n'),\n    Command('cat /foo/bar/', 'cat: /foo/bar/: Is a directory\\n'),\n    Command('cat cat/', 'cat: cat/: Is a directory\\n'),\n])\ndef test_match(command, isdir):\n    isdir.return_value = True\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('cat foo', 'foo bar baz'),\n    Command('cat foo bar', 'foo bar baz'),\n    Command('notcat foo bar', 'some output'),\n])\ndef test_not_match(command, isdir):\n    isdir.return_value = False\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('cat foo', 'cat: foo: Is a directory\\n'), 'ls foo'),\n    (Command('cat /foo/bar/', 'cat: /foo/bar/: Is a directory\\n'), 'ls /foo/bar/'),\n    (Command('cat cat', 'cat: cat: Is a directory\\n'), 'ls cat'),\n])\ndef test_get_new_command(command, new_command):\n    isdir.return_value = True\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_cd_correction.py",
    "content": "import pytest\nfrom thefuck.rules.cd_correction import match\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('cd foo', 'cd: foo: No such file or directory'),\n    Command('cd foo/bar/baz',\n            'cd: foo: No such file or directory'),\n    Command('cd foo/bar/baz', 'cd: can\\'t cd to foo/bar/baz'),\n    Command('cd /foo/bar/', 'cd: The directory \"/foo/bar/\" does not exist')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('cd foo', ''), Command('', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n# Note that get_new_command uses local filesystem, so not testing it here.\n# Instead, see the functional test `functional.test_cd_correction`\n"
  },
  {
    "path": "tests/rules/test_cd_cs.py",
    "content": "from thefuck.rules.cd_cs import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef test_match():\n    assert match(Command('cs', 'cs: command not found'))\n    assert match(Command('cs /etc/', 'cs: command not found'))\n\n\ndef test_get_new_command():\n    assert get_new_command(Command('cs /etc/', 'cs: command not found')) == 'cd /etc/'\n"
  },
  {
    "path": "tests/rules/test_cd_mkdir.py",
    "content": "import pytest\nfrom thefuck.rules.cd_mkdir import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('cd foo', 'cd: foo: No such file or directory'),\n    Command('cd foo/bar/baz',\n            'cd: foo: No such file or directory'),\n    Command('cd foo/bar/baz', 'cd: can\\'t cd to foo/bar/baz'),\n    Command('cd /foo/bar/', 'cd: The directory \"/foo/bar/\" does not exist')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('cd foo', ''), Command('', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('cd foo', ''), 'mkdir -p foo && cd foo'),\n    (Command('cd foo/bar/baz', ''), 'mkdir -p foo/bar/baz && cd foo/bar/baz')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_cd_parent.py",
    "content": "from thefuck.rules.cd_parent import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef test_match():\n    assert match(Command('cd..', 'cd..: command not found'))\n    assert not match(Command('', ''))\n\n\ndef test_get_new_command():\n    assert get_new_command(Command('cd..', '')) == 'cd ..'\n"
  },
  {
    "path": "tests/rules/test_chmod_x.py",
    "content": "import pytest\nfrom thefuck.types import Command\nfrom thefuck.rules.chmod_x import match, get_new_command\n\n\n@pytest.fixture\ndef file_exists(mocker):\n    return mocker.patch('os.path.exists', return_value=True)\n\n\n@pytest.fixture\ndef file_access(mocker):\n    return mocker.patch('os.access', return_value=False)\n\n\n@pytest.mark.usefixtures('file_exists', 'file_access')\n@pytest.mark.parametrize('script, output', [\n    ('./gradlew build', 'gradlew: Permission denied'),\n    ('./install.sh --help', 'install.sh: permission denied')])\ndef test_match(script, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output, exists, callable', [\n    ('./gradlew build', 'gradlew: Permission denied', True, True),\n    ('./gradlew build', 'gradlew: Permission denied', False, False),\n    ('./gradlew build', 'gradlew: error', True, False),\n    ('gradlew build', 'gradlew: Permission denied', True, False)])\ndef test_not_match(file_exists, file_access, script, output, exists, callable):\n    file_exists.return_value = exists\n    file_access.return_value = callable\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, result', [\n    ('./gradlew build', 'chmod +x gradlew && ./gradlew build'),\n    ('./install.sh --help', 'chmod +x install.sh && ./install.sh --help')])\ndef test_get_new_command(script, result):\n    assert get_new_command(Command(script, '')) == result\n"
  },
  {
    "path": "tests/rules/test_choco_install.py",
    "content": "import pytest\nfrom thefuck.rules.choco_install import match, get_new_command\nfrom thefuck.types import Command\n\n\npackage_not_found_error = (\n    'Chocolatey v0.10.15\\n'\n    'Installing the following packages:\\n'\n    'logstitcher\\n'\n    'By installing you accept licenses for the packages.\\n'\n    'logstitcher not installed. The package was not found with the source(s) listed.\\n'\n    ' Source(s): \\'https://chocolatey.org/api/v2/\\'\\n'\n    ' NOTE: When you specify explicit sources, it overrides default sources.\\n'\n    'If the package version is a prerelease and you didn\\'t specify `--pre`,\\n'\n    ' the package may not be found.\\n'\n    'Please see https://chocolatey.org/docs/troubleshooting for more\\n'\n    ' assistance.\\n'\n    '\\n'\n    'Chocolatey installed 0/1 packages. 1 packages failed.\\n'\n    ' See the log for details (C:\\\\ProgramData\\\\chocolatey\\\\logs\\\\chocolatey.log).\\n'\n    '\\n'\n    'Failures\\n'\n    ' - logstitcher - logstitcher not installed. The package was not found with the source(s) listed.\\n'\n    ' Source(s): \\'https://chocolatey.org/api/v2/\\'\\n'\n    ' NOTE: When you specify explicit sources, it overrides default sources.\\n'\n    'If the package version is a prerelease and you didn\\'t specify `--pre`,\\n'\n    ' the package may not be found.\\n'\n    'Please see https://chocolatey.org/docs/troubleshooting for more\\n'\n    ' assistance.\\n'\n)\n\n\n@pytest.mark.parametrize('command', [\n    Command('choco install logstitcher', package_not_found_error),\n    Command('cinst logstitcher', package_not_found_error),\n    Command('choco install logstitcher -y', package_not_found_error),\n    Command('cinst logstitcher -y', package_not_found_error),\n    Command('choco install logstitcher -y -n=test', package_not_found_error),\n    Command('cinst logstitcher -y -n=test', package_not_found_error),\n    Command('choco install logstitcher -y -n=test /env', package_not_found_error),\n    Command('cinst logstitcher -y -n=test /env', package_not_found_error),\n    Command('choco install chocolatey -y', package_not_found_error),\n    Command('cinst chocolatey -y', package_not_found_error)])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('choco /?', ''),\n    Command('choco upgrade logstitcher', ''),\n    Command('cup logstitcher', ''),\n    Command('choco upgrade logstitcher -y', ''),\n    Command('cup logstitcher -y', ''),\n    Command('choco upgrade logstitcher -y -n=test', ''),\n    Command('cup logstitcher -y -n=test', ''),\n    Command('choco upgrade logstitcher -y -n=test /env', ''),\n    Command('cup logstitcher -y -n=test /env', ''),\n    Command('choco upgrade chocolatey -y', ''),\n    Command('cup chocolatey -y', ''),\n    Command('choco uninstall logstitcher', ''),\n    Command('cuninst logstitcher', ''),\n    Command('choco uninstall logstitcher -y', ''),\n    Command('cuninst logstitcher -y', ''),\n    Command('choco uninstall logstitcher -y -n=test', ''),\n    Command('cuninst logstitcher -y -n=test', ''),\n    Command('choco uninstall logstitcher -y -n=test /env', ''),\n    Command('cuninst logstitcher -y -n=test /env', ''),\n    Command('choco uninstall chocolatey -y', ''),\n    Command('cuninst chocolatey -y', '')])\ndef not_test_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('before, after', [\n    ('choco install logstitcher', 'choco install logstitcher.install'),\n    ('cinst logstitcher', 'cinst logstitcher.install'),\n    ('choco install logstitcher -y', 'choco install logstitcher.install -y'),\n    ('cinst logstitcher -y', 'cinst logstitcher.install -y'),\n    ('choco install logstitcher -y -n=test', 'choco install logstitcher.install -y -n=test'),\n    ('cinst logstitcher -y -n=test', 'cinst logstitcher.install -y -n=test'),\n    ('choco install logstitcher -y -n=test /env', 'choco install logstitcher.install -y -n=test /env'),\n    ('cinst logstitcher -y -n=test /env', 'cinst logstitcher.install -y -n=test /env'),\n    ('choco install chocolatey -y', 'choco install chocolatey.install -y'),\n    ('cinst chocolatey -y', 'cinst chocolatey.install -y'), ])\ndef test_get_new_command(before, after):\n    assert (get_new_command(Command(before, '')) == after)\n"
  },
  {
    "path": "tests/rules/test_composer_not_command.py",
    "content": "import pytest\nfrom thefuck.rules.composer_not_command import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef composer_not_command():\n    # that weird spacing is part of the actual command output\n    return (\n        '\\n'\n        '\\n'\n        '                                    \\n'\n        '  [InvalidArgumentException]        \\n'\n        '  Command \"udpate\" is not defined.  \\n'\n        '  Did you mean this?                \\n'\n        '      update                        \\n'\n        '                                    \\n'\n        '\\n'\n        '\\n'\n    )\n\n\n@pytest.fixture\ndef composer_not_command_one_of_this():\n    # that weird spacing is part of the actual command output\n    return (\n        '\\n'\n        '\\n'\n        '                                   \\n'\n        '  [InvalidArgumentException]       \\n'\n        '  Command \"pdate\" is not defined.  \\n'\n        '  Did you mean one of these?       \\n'\n        '      selfupdate                   \\n'\n        '      self-update                  \\n'\n        '      update                       \\n'\n        '                                   \\n'\n        '\\n'\n        '\\n'\n    )\n\n\n@pytest.fixture\ndef composer_require_instead_of_install():\n    return 'Invalid argument package. Use \"composer require package\" instead to add packages to your composer.json.'\n\n\ndef test_match(composer_not_command, composer_not_command_one_of_this, composer_require_instead_of_install):\n    assert match(Command('composer udpate',\n                         composer_not_command))\n    assert match(Command('composer pdate',\n                         composer_not_command_one_of_this))\n    assert match(Command('composer install package',\n                         composer_require_instead_of_install))\n    assert not match(Command('ls update', composer_not_command))\n\n\ndef test_get_new_command(composer_not_command, composer_not_command_one_of_this, composer_require_instead_of_install):\n    assert (get_new_command(Command('composer udpate',\n                                    composer_not_command))\n            == 'composer update')\n    assert (get_new_command(Command('composer pdate',\n                                    composer_not_command_one_of_this))\n            == 'composer selfupdate')\n    assert (get_new_command(Command('composer install package',\n                                    composer_require_instead_of_install))\n            == 'composer require package')\n"
  },
  {
    "path": "tests/rules/test_conda_mistype.py",
    "content": "import pytest\n\nfrom thefuck.rules.conda_mistype import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef mistype_response():\n    return \"\"\"\n\nCommandNotFoundError: No command 'conda lst'.\nDid you mean 'conda list'?\n\n    \"\"\"\n\n\ndef test_match(mistype_response):\n    assert match(Command('conda lst', mistype_response))\n    err_response = 'bash: codna: command not found'\n    assert not match(Command('codna list', err_response))\n\n\ndef test_get_new_command(mistype_response):\n    assert (get_new_command(Command('conda lst', mistype_response)) == ['conda list'])\n"
  },
  {
    "path": "tests/rules/test_cp_create_destination.py",
    "content": "import pytest\nfrom thefuck.rules.cp_create_destination import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize(\n    \"script, output\",\n    [(\"cp\", \"cp: directory foo does not exist\\n\"), (\"mv\", \"No such file or directory\")],\n)\ndef test_match(script, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize(\n    \"script, output\", [(\"cp\", \"\"), (\"mv\", \"\"), (\"ls\", \"No such file or directory\")]\n)\ndef test_not_match(script, output):\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize(\n    \"script, output, new_command\",\n    [\n        (\"cp foo bar/\", \"cp: directory foo does not exist\\n\", \"mkdir -p bar/ && cp foo bar/\"),\n        (\"mv foo bar/\", \"No such file or directory\", \"mkdir -p bar/ && mv foo bar/\"),\n        (\"cp foo bar/baz/\", \"cp: directory foo does not exist\\n\", \"mkdir -p bar/baz/ && cp foo bar/baz/\"),\n    ],\n)\ndef test_get_new_command(script, output, new_command):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_cp_omitting_directory.py",
    "content": "import pytest\nfrom thefuck.rules.cp_omitting_directory import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('script, output', [\n    ('cp dir', 'cp: dor: is a directory'),\n    ('cp dir', \"cp: omitting directory 'dir'\")])\ndef test_match(script, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output', [\n    ('some dir', 'cp: dor: is a directory'),\n    ('some dir', \"cp: omitting directory 'dir'\"),\n    ('cp dir', '')])\ndef test_not_match(script, output):\n    assert not match(Command(script, output))\n\n\ndef test_get_new_command():\n    assert get_new_command(Command('cp dir', '')) == 'cp -a dir'\n"
  },
  {
    "path": "tests/rules/test_dirty_untar.py",
    "content": "import os\nimport pytest\nimport tarfile\nfrom thefuck.rules.dirty_untar import match, get_new_command, side_effect, \\\n                                      tar_extensions  # noqa: E126\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef tar_error(tmpdir):\n    def fixture(filename):\n        path = os.path.join(str(tmpdir), filename)\n\n        def reset(path):\n            os.mkdir('d')\n            with tarfile.TarFile(path, 'w') as archive:\n                for file in ('a', 'b', 'c', 'd/e'):\n                    with open(file, 'w') as f:\n                        f.write('*')\n\n                    archive.add(file)\n\n                    os.remove(file)\n\n            with tarfile.TarFile(path, 'r') as archive:\n                archive.extractall()\n\n        os.chdir(str(tmpdir))\n        reset(path)\n\n        assert set(os.listdir('.')) == {filename, 'a', 'b', 'c', 'd'}\n        assert set(os.listdir('./d')) == {'e'}\n\n    return fixture\n\n\nparametrize_extensions = pytest.mark.parametrize('ext', tar_extensions)\n\n# (filename as typed by the user, unquoted filename, quoted filename as per shells.quote)\nparametrize_filename = pytest.mark.parametrize('filename, unquoted, quoted', [\n    ('foo{}', 'foo{}', 'foo{}'),\n    ('\"foo bar{}\"', 'foo bar{}', \"'foo bar{}'\")])\n\nparametrize_script = pytest.mark.parametrize('script, fixed', [\n    ('tar xvf {}', 'mkdir -p {dir} && tar xvf {filename} -C {dir}'),\n    ('tar -xvf {}', 'mkdir -p {dir} && tar -xvf {filename} -C {dir}'),\n    ('tar --extract -f {}', 'mkdir -p {dir} && tar --extract -f {filename} -C {dir}')])\n\n\n@parametrize_extensions\n@parametrize_filename\n@parametrize_script\ndef test_match(ext, tar_error, filename, unquoted, quoted, script, fixed):\n    tar_error(unquoted.format(ext))\n    assert match(Command(script.format(filename.format(ext)), ''))\n\n\n@parametrize_extensions\n@parametrize_filename\n@parametrize_script\ndef test_side_effect(ext, tar_error, filename, unquoted, quoted, script, fixed):\n    tar_error(unquoted.format(ext))\n    side_effect(Command(script.format(filename.format(ext)), ''), None)\n    assert set(os.listdir('.')) == {unquoted.format(ext), 'd'}\n\n\n@parametrize_extensions\n@parametrize_filename\n@parametrize_script\ndef test_get_new_command(ext, tar_error, filename, unquoted, quoted, script, fixed):\n    tar_error(unquoted.format(ext))\n    assert (get_new_command(Command(script.format(filename.format(ext)), ''))\n            == fixed.format(dir=quoted.format(''), filename=filename.format(ext)))\n"
  },
  {
    "path": "tests/rules/test_dirty_unzip.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport os\nimport pytest\nimport zipfile\nfrom thefuck.rules.dirty_unzip import match, get_new_command, side_effect\nfrom thefuck.types import Command\nfrom unicodedata import normalize\n\n\n@pytest.fixture\ndef zip_error(tmpdir):\n    def zip_error_inner(filename):\n        path = os.path.join(str(tmpdir), filename)\n\n        def reset(path):\n            with zipfile.ZipFile(path, 'w') as archive:\n                archive.writestr('a', '1')\n                archive.writestr('b', '2')\n                archive.writestr('c', '3')\n\n                archive.writestr('d/e', '4')\n\n                archive.extractall()\n\n        os.chdir(str(tmpdir))\n        reset(path)\n\n        dir_list = os.listdir(u'.')\n        if filename not in dir_list:\n            filename = normalize('NFD', filename)\n\n        assert set(dir_list) == {filename, 'a', 'b', 'c', 'd'}\n        assert set(os.listdir('./d')) == {'e'}\n    return zip_error_inner\n\n\n@pytest.mark.parametrize('script,filename', [\n    (u'unzip café', u'café.zip'),\n    (u'unzip café.zip', u'café.zip'),\n    (u'unzip foo', u'foo.zip'),\n    (u'unzip foo.zip', u'foo.zip')])\ndef test_match(zip_error, script, filename):\n    zip_error(filename)\n    assert match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script,filename', [\n    (u'unzip café', u'café.zip'),\n    (u'unzip café.zip', u'café.zip'),\n    (u'unzip foo', u'foo.zip'),\n    (u'unzip foo.zip', u'foo.zip')])\ndef test_side_effect(zip_error, script, filename):\n    zip_error(filename)\n    side_effect(Command(script, ''), None)\n\n    dir_list = os.listdir(u'.')\n    if filename not in set(dir_list):\n        filename = normalize('NFD', filename)\n\n    assert set(dir_list) == {filename, 'd'}\n\n\n@pytest.mark.parametrize('script,fixed,filename', [\n    (u'unzip café', u\"unzip café -d 'café'\", u'café.zip'),\n    (u'unzip foo', u'unzip foo -d foo', u'foo.zip'),\n    (u\"unzip 'foo bar.zip'\", u\"unzip 'foo bar.zip' -d 'foo bar'\", u'foo.zip'),\n    (u'unzip foo.zip', u'unzip foo.zip -d foo', u'foo.zip')])\ndef test_get_new_command(zip_error, script, fixed, filename):\n    zip_error(filename)\n    assert get_new_command(Command(script, '')) == fixed\n"
  },
  {
    "path": "tests/rules/test_django_south_ghost.py",
    "content": "import pytest\nfrom thefuck.rules.django_south_ghost import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output():\n    return '''Traceback (most recent call last):\n  File \"/home/nvbn/work/.../bin/python\", line 42, in <module>\n    exec(compile(__file__f.read(), __file__, \"exec\"))\n  File \"/home/nvbn/work/.../app/manage.py\", line 34, in <module>\n    execute_from_command_line(sys.argv)\n  File \"/home/nvbn/work/.../lib/django/core/management/__init__.py\", line 443, in execute_from_command_line\n    utility.execute()\n  File \"/home/nvbn/work/.../lib/django/core/management/__init__.py\", line 382, in execute\n    self.fetch_command(subcommand).run_from_argv(self.argv)\n  File \"/home/nvbn/work/.../lib/django/core/management/base.py\", line 196, in run_from_argv\n    self.execute(*args, **options.__dict__)\n  File \"/home/nvbn/work/.../lib/django/core/management/base.py\", line 232, in execute\n    output = self.handle(*args, **options)\n  File \"/home/nvbn/work/.../app/lib/south/management/commands/migrate.py\", line 108, in handle\n    ignore_ghosts = ignore_ghosts,\n  File \"/home/nvbn/work/.../app/lib/south/migration/__init__.py\", line 193, in migrate_app\n    applied_all = check_migration_histories(applied_all, delete_ghosts, ignore_ghosts)\n  File \"/home/nvbn/work/.../app/lib/south/migration/__init__.py\", line 88, in check_migration_histories\n    raise exceptions.GhostMigrations(ghosts)\nsouth.exceptions.GhostMigrations: \n\n ! These migrations are in the database but not on disk:\n    <app1: 0033_auto__...>\n    <app1: 0034_fill_...>\n    <app1: 0035_rename_...>\n    <app2: 0003_add_...>\n    <app2: 0004_denormalize_...>\n    <app1: 0033_auto....>\n    <app1: 0034_fill...>\n ! I'm not trusting myself; either fix this yourself by fiddling\n ! with the south_migrationhistory table, or pass --delete-ghost-migrations\n ! to South to have it delete ALL of these records (this may not be good).\n'''  # noqa\n\n\ndef test_match(output):\n    assert match(Command('./manage.py migrate', output))\n    assert match(Command('python manage.py migrate', output))\n    assert not match(Command('./manage.py migrate', ''))\n    assert not match(Command('app migrate', output))\n    assert not match(Command('./manage.py test', output))\n\n\ndef test_get_new_command():\n    assert get_new_command(Command('./manage.py migrate auth', ''))\\\n        == './manage.py migrate auth --delete-ghost-migrations'\n"
  },
  {
    "path": "tests/rules/test_django_south_merge.py",
    "content": "import pytest\nfrom thefuck.rules.django_south_merge import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output():\n    return '''Running migrations for app:\n ! Migration app:0003_auto... should not have been applied before app:0002_auto__add_field_query_due_date_ but was.\nTraceback (most recent call last):\n  File \"/home/nvbn/work/.../bin/python\", line 42, in <module>\n    exec(compile(__file__f.read(), __file__, \"exec\"))\n  File \"/home/nvbn/work/.../app/manage.py\", line 34, in <module>\n    execute_from_command_line(sys.argv)\n  File \"/home/nvbn/work/.../lib/django/core/management/__init__.py\", line 443, in execute_from_command_line\n    utility.execute()\n  File \"/home/nvbn/work/.../lib/django/core/management/__init__.py\", line 382, in execute\n    self.fetch_command(subcommand).run_from_argv(self.argv)\n  File \"/home/nvbn/work/.../lib/django/core/management/base.py\", line 196, in run_from_argv\n    self.execute(*args, **options.__dict__)\n  File \"/home/nvbn/work/.../lib/django/core/management/base.py\", line 232, in execute\n    output = self.handle(*args, **options)\n  File \"/home/nvbn/work/.../app/lib/south/management/commands/migrate.py\", line 108, in handle\n    ignore_ghosts = ignore_ghosts,\n  File \"/home/nvbn/work/.../app/lib/south/migration/__init__.py\", line 207, in migrate_app\n    raise exceptions.InconsistentMigrationHistory(problems)\nsouth.exceptions.InconsistentMigrationHistory: Inconsistent migration history\nThe following options are available:\n    --merge: will just attempt the migration ignoring any potential dependency conflicts.\n'''\n\n\ndef test_match(output):\n    assert match(Command('./manage.py migrate', output))\n    assert match(Command('python manage.py migrate', output))\n    assert not match(Command('./manage.py migrate', ''))\n    assert not match(Command('app migrate', output))\n    assert not match(Command('./manage.py test', output))\n\n\ndef test_get_new_command():\n    assert (get_new_command(Command('./manage.py migrate auth', ''))\n            == './manage.py migrate auth --merge')\n"
  },
  {
    "path": "tests/rules/test_dnf_no_such_command.py",
    "content": "from io import BytesIO\nimport pytest\nfrom thefuck.types import Command\nfrom thefuck.rules.dnf_no_such_command import match, get_new_command, _get_operations\n\n\nhelp_text = b'''usage: dnf [options] COMMAND\n\nList of Main Commands:\n\nautoremove                remove all unneeded packages that were originally installed as dependencies\ncheck                     check for problems in the packagedb\ncheck-update              check for available package upgrades\nclean                     remove cached data\ndeplist                   List package's dependencies and what packages provide them\ndistro-sync               synchronize installed packages to the latest available versions\ndowngrade                 Downgrade a package\ngroup                     display, or use, the groups information\nhelp                      display a helpful usage message\nhistory                   display, or use, the transaction history\ninfo                      display details about a package or group of packages\ninstall                   install a package or packages on your system\nlist                      list a package or groups of packages\nmakecache                 generate the metadata cache\nmark                      mark or unmark installed packages as installed by user.\nprovides                  find what package provides the given value\nreinstall                 reinstall a package\nremove                    remove a package or packages from your system\nrepolist                  display the configured software repositories\nrepoquery                 search for packages matching keyword\nrepository-packages       run commands on top of all packages in given repository\nsearch                    search package details for the given string\nshell                     run an interactive DNF shell\nswap                      run an interactive dnf mod for remove and install one spec\nupdateinfo                display advisories about packages\nupgrade                   upgrade a package or packages on your system\nupgrade-minimal           upgrade, but only 'newest' package match which fixes a problem that affects your system\n\nList of Plugin Commands:\n\nbuilddep                  Install build dependencies for package or spec file\nconfig-manager            manage dnf configuration options and repositories\ncopr                      Interact with Copr repositories.\ndebug-dump                dump information about installed rpm packages to file\ndebug-restore             restore packages recorded in debug-dump file\ndebuginfo-install         install debuginfo packages\ndownload                  Download package to current directory\nneeds-restarting          determine updated binaries that need restarting\nplayground                Interact with Playground repository.\nrepoclosure               Display a list of unresolved dependencies for repositories\nrepograph                 Output a full package dependency graph in dot format\nrepomanage                Manage a directory of rpm packages\nreposync                  download all packages from remote repo\n\nOptional arguments:\n  -c [config file], --config [config file]\n                        config file location\n  -q, --quiet           quiet operation\n  -v, --verbose         verbose operation\n  --version             show DNF version and exit\n  --installroot [path]  set install root\n  --nodocs              do not install documentations\n  --noplugins           disable all plugins\n  --enableplugin [plugin]\n                        enable plugins by name\n  --disableplugin [plugin]\n                        disable plugins by name\n  --releasever RELEASEVER\n                        override the value of $releasever in config and repo\n                        files\n  --setopt SETOPTS      set arbitrary config and repo options\n  --skip-broken         resolve depsolve problems by skipping packages\n  -h, --help, --help-cmd\n                        show command help\n  --allowerasing        allow erasing of installed packages to resolve\n                        dependencies\n  -b, --best            try the best available package versions in\n                        transactions.\n  -C, --cacheonly       run entirely from system cache, don't update cache\n  -R [minutes], --randomwait [minutes]\n                        maximum command wait time\n  -d [debug level], --debuglevel [debug level]\n                        debugging output level\n  --debugsolver         dumps detailed solving results into files\n  --showduplicates      show duplicates, in repos, in list/search commands\n  -e ERRORLEVEL, --errorlevel ERRORLEVEL\n                        error output level\n  --obsoletes           enables dnf's obsoletes processing logic for upgrade\n                        or display capabilities that the package obsoletes for\n                        info, list and repoquery\n  --rpmverbosity [debug level name]\n                        debugging output level for rpm\n  -y, --assumeyes       automatically answer yes for all questions\n  --assumeno            automatically answer no for all questions\n  --enablerepo [repo]\n  --disablerepo [repo]\n  --repo [repo], --repoid [repo]\n                        enable just specific repositories by an id or a glob,\n                        can be specified multiple times\n  -x [package], --exclude [package], --excludepkgs [package]\n                        exclude packages by name or glob\n  --disableexcludes [repo], --disableexcludepkgs [repo]\n                        disable excludepkgs\n  --repofrompath [repo,path]\n                        label and path to additional repository, can be\n                        specified multiple times.\n  --noautoremove        disable removal of dependencies that are no longer\n                        used\n  --nogpgcheck          disable gpg signature checking\n  --color COLOR         control whether colour is used\n  --refresh             set metadata as expired before running the command\n  -4                    resolve to IPv4 addresses only\n  -6                    resolve to IPv6 addresses only\n  --destdir DESTDIR, --downloaddir DESTDIR\n                        set directory to copy packages to\n  --downloadonly        only download packages\n  --bugfix              Include bugfix relevant packages, in updates\n  --enhancement         Include enhancement relevant packages, in updates\n  --newpackage          Include newpackage relevant packages, in updates\n  --security            Include security relevant packages, in updates\n  --advisory ADVISORY, --advisories ADVISORY\n                        Include packages needed to fix the given advisory, in\n                        updates\n  --bzs BUGZILLA        Include packages needed to fix the given BZ, in\n                        updates\n  --cves CVES           Include packages needed to fix the given CVE, in\n                        updates\n  --sec-severity {Critical,Important,Moderate,Low}, --secseverity {Critical,Important,Moderate,Low}\n                        Include security relevant packages matching the\n                        severity, in updates\n  --forcearch ARCH      Force the use of an architecture\n'''\n\ndnf_operations = ['autoremove', 'check', 'check-update', 'clean', 'deplist',\n                  'distro-sync', 'downgrade', 'group', 'help', 'history',\n                  'info', 'install', 'list', 'makecache', 'mark', 'provides',\n                  'reinstall', 'remove', 'repolist', 'repoquery',\n                  'repository-packages', 'search', 'shell', 'swap', 'updateinfo',\n                  'upgrade', 'upgrade-minimal', 'builddep', 'config-manager',\n                  'copr', 'debug-dump', 'debug-restore', 'debuginfo-install',\n                  'download', 'needs-restarting', 'playground', 'repoclosure',\n                  'repograph', 'repomanage', 'reposync']\n\n\ndef invalid_command(command):\n    return \"\"\"No such command: %s. Please use /usr/bin/dnf --help\nIt could be a DNF plugin command, try: \"dnf install 'dnf-command(%s)'\"\n\"\"\" % (command, command)\n\n\n@pytest.mark.parametrize('output', [\n    (invalid_command('saerch')),\n    (invalid_command('isntall'))\n])\ndef test_match(output):\n    assert match(Command('dnf', output))\n\n\n@pytest.mark.parametrize('script, output', [\n    ('pip', invalid_command('isntall')),\n    ('vim', \"\")\n])\ndef test_not_match(script, output):\n    assert not match(Command(script, output))\n\n\n@pytest.fixture\ndef set_help(mocker):\n    mock = mocker.patch('subprocess.Popen')\n\n    def _set_text(text):\n        mock.return_value.stdout = BytesIO(text)\n\n    return _set_text\n\n\ndef test_get_operations(set_help):\n    set_help(help_text)\n    assert _get_operations() == dnf_operations\n\n\n@pytest.mark.parametrize('script, output, result', [\n    ('dnf isntall vim', invalid_command('isntall'),\n     'dnf install vim'),\n    ('dnf saerch vim', invalid_command('saerch'),\n     'dnf search vim'),\n])\ndef test_get_new_command(set_help, output, script, result):\n    set_help(help_text)\n    assert result in get_new_command(Command(script, output))\n"
  },
  {
    "path": "tests/rules/test_docker_image_being_used_by_container.py",
    "content": "from thefuck.rules.docker_image_being_used_by_container import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef test_match():\n    err_response = \"\"\"Error response from daemon: conflict: unable to delete cd809b04b6ff (cannot be forced) - image is being used by running container e5e2591040d1\"\"\"\n    assert match(Command('docker image rm -f cd809b04b6ff', err_response))\n\n\ndef test_not_match():\n    err_response = 'bash: docker: command not found'\n    assert not match(Command('docker image rm -f cd809b04b6ff', err_response))\n\n\ndef test_not_docker_command():\n    err_response = \"\"\"Error response from daemon: conflict: unable to delete cd809b04b6ff (cannot be forced) - image is being used by running container e5e2591040d1\"\"\"\n    assert not match(Command('git image rm -f cd809b04b6ff', err_response))\n\n\ndef test_get_new_command():\n    err_response = \"\"\"\n        Error response from daemon: conflict: unable to delete cd809b04b6ff (cannot be forced) - image\n        is being used by running container e5e2591040d1\n        \"\"\"\n    result = get_new_command(Command('docker image rm -f cd809b04b6ff', err_response))\n    expected = 'docker container rm -f e5e2591040d1 && docker image rm -f cd809b04b6ff'\n    assert result == expected\n"
  },
  {
    "path": "tests/rules/test_docker_login.py",
    "content": "from thefuck.rules.docker_login import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef test_match():\n    err_response1 = \"\"\"\n    Sending build context to Docker daemon  118.8kB\nStep 1/6 : FROM foo/bar:fdb7c6d\npull access denied for foo/bar, repository does not exist or may require 'docker login'\n\"\"\"\n    assert match(Command('docker build -t artifactory:9090/foo/bar:fdb7c6d .', err_response1))\n\n    err_response2 = \"\"\"\n    The push refers to repository [artifactory:9090/foo/bar]\npush access denied for foo/bar, repository does not exist or may require 'docker login'\n\"\"\"\n    assert match(Command('docker push artifactory:9090/foo/bar:fdb7c6d', err_response2))\n\n    err_response3 = \"\"\"\n    docker push artifactory:9090/foo/bar:fdb7c6d\nThe push refers to repository [artifactory:9090/foo/bar]\n9c29c7ad209d: Preparing\n71f3ad53dfe0: Preparing\nf58ee068224c: Preparing\naeddc924d0f7: Preparing\nc2040e5d6363: Preparing\n4d42df4f350f: Preparing\n35723dab26f9: Preparing\n71f3ad53dfe0: Pushed\ncb95fa0faeb1: Layer already exists\n\"\"\"\n    assert not match(Command('docker push artifactory:9090/foo/bar:fdb7c6d', err_response3))\n\n\ndef test_get_new_command():\n    assert get_new_command(Command('docker build -t artifactory:9090/foo/bar:fdb7c6d .', '')) == 'docker login && docker build -t artifactory:9090/foo/bar:fdb7c6d .'\n    assert get_new_command(Command('docker push artifactory:9090/foo/bar:fdb7c6d', '')) == 'docker login && docker push artifactory:9090/foo/bar:fdb7c6d'\n"
  },
  {
    "path": "tests/rules/test_docker_not_command.py",
    "content": "import pytest\nfrom io import BytesIO\nfrom thefuck.types import Command\nfrom thefuck.rules.docker_not_command import get_new_command, match\n\n\n_DOCKER_SWARM_OUTPUT = '''\nUsage:\tdocker swarm COMMAND\n\nManage Swarm\n\nCommands:\n  ca          Display and rotate the root CA\n  init        Initialize a swarm\n  join        Join a swarm as a node and/or manager\n  join-token  Manage join tokens\n  leave       Leave the swarm\n  unlock      Unlock swarm\n  unlock-key  Manage the unlock key\n  update      Update the swarm\n\nRun 'docker swarm COMMAND --help' for more information on a command.\n'''\n_DOCKER_IMAGE_OUTPUT = '''\nUsage:\tdocker image COMMAND\n\nManage images\n\nCommands:\n  build       Build an image from a Dockerfile\n  history     Show the history of an image\n  import      Import the contents from a tarball to create a filesystem image\n  inspect     Display detailed information on one or more images\n  load        Load an image from a tar archive or STDIN\n  ls          List images\n  prune       Remove unused images\n  pull        Pull an image or a repository from a registry\n  push        Push an image or a repository to a registry\n  rm          Remove one or more images\n  save        Save one or more images to a tar archive (streamed to STDOUT by default)\n  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE\n\nRun 'docker image COMMAND --help' for more information on a command.\n'''\n\n\n@pytest.fixture\ndef docker_help(mocker):\n    help = b'''Usage: docker [OPTIONS] COMMAND [arg...]\n\nA self-sufficient runtime for linux containers.\n\nOptions:\n\n  --api-cors-header=                   Set CORS headers in the remote API\n  -b, --bridge=                        Attach containers to a network bridge\n  --bip=                               Specify network bridge IP\n  -D, --debug=false                    Enable debug mode\n  -d, --daemon=false                   Enable daemon mode\n  --default-gateway=                   Container default gateway IPv4 address\n  --default-gateway-v6=                Container default gateway IPv6 address\n  --default-ulimit=[]                  Set default ulimits for containers\n  --dns=[]                             DNS server to use\n  --dns-search=[]                      DNS search domains to use\n  -e, --exec-driver=native             Exec driver to use\n  --exec-opt=[]                        Set exec driver options\n  --exec-root=/var/run/docker          Root of the Docker execdriver\n  --fixed-cidr=                        IPv4 subnet for fixed IPs\n  --fixed-cidr-v6=                     IPv6 subnet for fixed IPs\n  -G, --group=docker                   Group for the unix socket\n  -g, --graph=/var/lib/docker          Root of the Docker runtime\n  -H, --host=[]                        Daemon socket(s) to connect to\n  -h, --help=false                     Print usage\n  --icc=true                           Enable inter-container communication\n  --insecure-registry=[]               Enable insecure registry communication\n  --ip=0.0.0.0                         Default IP when binding container ports\n  --ip-forward=true                    Enable net.ipv4.ip_forward\n  --ip-masq=true                       Enable IP masquerading\n  --iptables=true                      Enable addition of iptables rules\n  --ipv6=false                         Enable IPv6 networking\n  -l, --log-level=info                 Set the logging level\n  --label=[]                           Set key=value labels to the daemon\n  --log-driver=json-file               Default driver for container logs\n  --log-opt=map[]                      Set log driver options\n  --mtu=0                              Set the containers network MTU\n  -p, --pidfile=/var/run/docker.pid    Path to use for daemon PID file\n  --registry-mirror=[]                 Preferred Docker registry mirror\n  -s, --storage-driver=                Storage driver to use\n  --selinux-enabled=false              Enable selinux support\n  --storage-opt=[]                     Set storage driver options\n  --tls=false                          Use TLS; implied by --tlsverify\n  --tlscacert=~/.docker/ca.pem         Trust certs signed only by this CA\n  --tlscert=~/.docker/cert.pem         Path to TLS certificate file\n  --tlskey=~/.docker/key.pem           Path to TLS key file\n  --tlsverify=false                    Use TLS and verify the remote\n  --userland-proxy=true                Use userland proxy for loopback traffic\n  -v, --version=false                  Print version information and quit\n\nCommands:\n    attach    Attach to a running container\n    build     Build an image from a Dockerfile\n    commit    Create a new image from a container's changes\n    cp        Copy files/folders from a container's filesystem to the host path\n    create    Create a new container\n    diff      Inspect changes on a container's filesystem\n    events    Get real time events from the server\n    exec      Run a command in a running container\n    export    Stream the contents of a container as a tar archive\n    history   Show the history of an image\n    images    List images\n    import    Create a new filesystem image from the contents of a tarball\n    info      Display system-wide information\n    inspect   Return low-level information on a container or image\n    kill      Kill a running container\n    load      Load an image from a tar archive\n    login     Register or log in to a Docker registry server\n    logout    Log out from a Docker registry server\n    logs      Fetch the logs of a container\n    pause     Pause all processes within a container\n    port      Lookup the public-facing port that is NAT-ed to PRIVATE_PORT\n    ps        List containers\n    pull      Pull an image or a repository from a Docker registry server\n    push      Push an image or a repository to a Docker registry server\n    rename    Rename an existing container\n    restart   Restart a running container\n    rm        Remove one or more containers\n    rmi       Remove one or more images\n    run       Run a command in a new container\n    save      Save an image to a tar archive\n    search    Search for an image on the Docker Hub\n    start     Start a stopped container\n    stats     Display a stream of a containers' resource usage statistics\n    stop      Stop a running container\n    tag       Tag an image into a repository\n    top       Lookup the running processes of a container\n    unpause   Unpause a paused container\n    version   Show the Docker version information\n    wait      Block until a container stops, then print its exit code\n\nRun 'docker COMMAND --help' for more information on a command.\n'''\n    mock = mocker.patch('subprocess.Popen')\n    mock.return_value.stdout = BytesIO(help)\n    return mock\n\n\n@pytest.fixture\ndef docker_help_new(mocker):\n    helptext_new = b'''\nUsage:\tdocker [OPTIONS] COMMAND\n\nA self-sufficient runtime for containers\n\nOptions:\n      --config string      Location of client config files (default \"/Users/ik1ne/.docker\")\n  -c, --context string     Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var\n                           and default context set with \"docker context use\")\n  -D, --debug              Enable debug mode\n  -H, --host list          Daemon socket(s) to connect to\n  -l, --log-level string   Set the logging level (\"debug\"|\"info\"|\"warn\"|\"error\"|\"fatal\") (default \"info\")\n      --tls                Use TLS; implied by --tlsverify\n      --tlscacert string   Trust certs signed only by this CA (default \"/Users/ik1ne/.docker/ca.pem\")\n      --tlscert string     Path to TLS certificate file (default \"/Users/ik1ne/.docker/cert.pem\")\n      --tlskey string      Path to TLS key file (default \"/Users/ik1ne/.docker/key.pem\")\n      --tlsverify          Use TLS and verify the remote\n  -v, --version            Print version information and quit\n\nManagement Commands:\n  builder     Manage builds\n  config      Manage Docker configs\n  container   Manage containers\n  context     Manage contexts\n  image       Manage images\n  network     Manage networks\n  node        Manage Swarm nodes\n  plugin      Manage plugins\n  secret      Manage Docker secrets\n  service     Manage services\n  stack       Manage Docker stacks\n  swarm       Manage Swarm\n  system      Manage Docker\n  trust       Manage trust on Docker images\n  volume      Manage volumes\n\nCommands:\n  attach      Attach local standard input, output, and error streams to a running container\n  build       Build an image from a Dockerfile\n  commit      Create a new image from a container's changes\n  cp          Copy files/folders between a container and the local filesystem\n  create      Create a new container\n  diff        Inspect changes to files or directories on a container's filesystem\n  events      Get real time events from the server\n  exec        Run a command in a running container\n  export      Export a container's filesystem as a tar archive\n  history     Show the history of an image\n  images      List images\n  import      Import the contents from a tarball to create a filesystem image\n  info        Display system-wide information\n  inspect     Return low-level information on Docker objects\n  kill        Kill one or more running containers\n  load        Load an image from a tar archive or STDIN\n  login       Log in to a Docker registry\n  logout      Log out from a Docker registry\n  logs        Fetch the logs of a container\n  pause       Pause all processes within one or more containers\n  port        List port mappings or a specific mapping for the container\n  ps          List containers\n  pull        Pull an image or a repository from a registry\n  push        Push an image or a repository to a registry\n  rename      Rename a container\n  restart     Restart one or more containers\n  rm          Remove one or more containers\n  rmi         Remove one or more images\n  run         Run a command in a new container\n  save        Save one or more images to a tar archive (streamed to STDOUT by default)\n  search      Search the Docker Hub for images\n  start       Start one or more stopped containers\n  stats       Display a live stream of container(s) resource usage statistics\n  stop        Stop one or more running containers\n  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE\n  top         Display the running processes of a container\n  unpause     Unpause all processes within one or more containers\n  update      Update configuration of one or more containers\n  version     Show the Docker version information\n  wait        Block until one or more containers stop, then print their exit codes\n\nRun 'docker COMMAND --help' for more information on a command.\n'''\n    mock = mocker.patch('subprocess.Popen')\n    mock.return_value.stdout = BytesIO(b'')\n    mock.return_value.stderr = BytesIO(helptext_new)\n    return mock\n\n\ndef output(cmd):\n    return \"docker: '{}' is not a docker command.\\n\" \\\n           \"See 'docker --help'.\".format(cmd)\n\n\ndef test_match():\n    assert match(Command('docker pes', output('pes')))\n\n\n# tests docker (management command)\n@pytest.mark.usefixtures('no_memoize')\n@pytest.mark.parametrize('script, output', [\n    ('docker swarn', output('swarn')),\n    ('docker imge', output('imge'))])\ndef test_match_management_cmd(script, output):\n    assert match(Command(script, output))\n\n\n# tests docker (management cmd) (management subcmd)\n@pytest.mark.usefixtures('no_memoize')\n@pytest.mark.parametrize('script, output', [\n    ('docker swarm int', _DOCKER_SWARM_OUTPUT),\n    ('docker image la', _DOCKER_IMAGE_OUTPUT)])\ndef test_match_management_subcmd(script, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output', [\n    ('docker ps', ''),\n    ('cat pes', output('pes'))])\ndef test_not_match(script, output):\n    assert not match(Command(script, output))\n\n\n@pytest.mark.usefixtures('no_memoize', 'docker_help')\n@pytest.mark.parametrize('wrong, fixed', [\n    ('pes', ['ps', 'push', 'pause']),\n    ('tags', ['tag', 'stats', 'images'])])\ndef test_get_new_command(wrong, fixed):\n    command = Command('docker {}'.format(wrong), output(wrong))\n    assert get_new_command(command) == ['docker {}'.format(x) for x in fixed]\n\n\n@pytest.mark.usefixtures('no_memoize', 'docker_help_new')\n@pytest.mark.parametrize('wrong, fixed', [\n    ('swarn', ['swarm', 'start', 'search']),\n    ('inage', ['image', 'images', 'rename'])])\ndef test_get_new_management_command(wrong, fixed):\n    command = Command('docker {}'.format(wrong), output(wrong))\n    assert get_new_command(command) == ['docker {}'.format(x) for x in fixed]\n\n\n@pytest.mark.usefixtures('no_memoize', 'docker_help_new')\n@pytest.mark.parametrize('wrong, fixed, output', [\n    ('swarm int', ['swarm init', 'swarm join', 'swarm join-token'], _DOCKER_SWARM_OUTPUT),\n    ('image la', ['image load', 'image ls', 'image tag'], _DOCKER_IMAGE_OUTPUT)])\ndef test_get_new_management_command_subcommand(wrong, fixed, output):\n    command = Command('docker {}'.format(wrong), output)\n    assert get_new_command(command) == ['docker {}'.format(x) for x in fixed]\n"
  },
  {
    "path": "tests/rules/test_dry.py",
    "content": "import pytest\nfrom thefuck.rules.dry import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('cd cd foo', ''),\n    Command('git git push origin/master', '')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('cd cd foo', ''), 'cd foo'),\n    (Command('git git push origin/master', ''), 'git push origin/master')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_fab_command_not_found.py",
    "content": "import pytest\nfrom thefuck.rules.fab_command_not_found import match, get_new_command\nfrom thefuck.types import Command\n\noutput = '''\nWarning: Command(s) not found:\n    extenson\n    deloyp\n\nAvailable commands:\n\n    update_config\n    prepare_extension\n    Template               A string class for supporting $-substitutions.\n    deploy\n    glob                   Return a list of paths matching a pathname pattern.\n    install_web\n    set_version\n'''\n\n\n@pytest.mark.parametrize('command', [\n    Command('fab extenson', output),\n    Command('fab deloyp', output),\n    Command('fab extenson deloyp', output)])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('gulp extenson', output),\n    Command('fab deloyp', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('script, result', [\n    ('fab extenson', 'fab prepare_extension'),\n    ('fab extenson:version=2016',\n     'fab prepare_extension:version=2016'),\n    ('fab extenson:version=2016 install_web set_version:val=0.5.0',\n     'fab prepare_extension:version=2016 install_web set_version:val=0.5.0'),\n    ('fab extenson:version=2016 deloyp:beta=true -H the.fuck',\n     'fab prepare_extension:version=2016 deploy:beta=true -H the.fuck'),\n])\ndef test_get_new_command(script, result):\n    command = Command(script, output)\n    assert get_new_command(command) == result\n"
  },
  {
    "path": "tests/rules/test_fix_alt_space.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom thefuck.rules.fix_alt_space import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef test_match():\n    \"\"\"The character before 'grep' is Alt+Space, which happens frequently\n    on the Mac when typing the pipe character (Alt+7), and holding the Alt\n    key pressed for longer than necessary.\n\n    \"\"\"\n    assert match(Command(u'ps -ef | grep foo',\n                         u'-bash:  grep: command not found'))\n    assert not match(Command('ps -ef | grep foo', ''))\n    assert not match(Command('', ''))\n\n\ndef test_get_new_command():\n    \"\"\" Replace the Alt+Space character by a simple space \"\"\"\n    assert (get_new_command(Command(u'ps -ef | grep foo', ''))\n            == 'ps -ef | grep foo')\n"
  },
  {
    "path": "tests/rules/test_fix_file.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport pytest\nimport os\nfrom collections import namedtuple\nfrom thefuck.rules.fix_file import match, get_new_command\nfrom thefuck.types import Command\n\nFixFileTest = namedtuple('FixFileTest', ['script', 'file', 'line', 'col', 'output'])\n\ntests = (\n    FixFileTest('gcc a.c', 'a.c', 3, 1, \"\"\"\na.c: In function 'main':\na.c:3:1: error: expected expression before '}' token\n }\n  ^\n\"\"\"),\n\n    FixFileTest('clang a.c', 'a.c', 3, 1, \"\"\"\na.c:3:1: error: expected expression\n}\n^\n\"\"\"),\n\n    FixFileTest('perl a.pl', 'a.pl', 3, None, \"\"\"\nsyntax error at a.pl line 3, at EOF\nExecution of a.pl aborted due to compilation errors.\n\"\"\"),\n\n    FixFileTest('perl a.pl', 'a.pl', 2, None, \"\"\"\nSearch pattern not terminated at a.pl line 2.\n\"\"\"),\n\n    FixFileTest('sh a.sh', 'a.sh', 2, None, \"\"\"\na.sh: line 2: foo: command not found\n\"\"\"),\n\n    FixFileTest('zsh a.sh', 'a.sh', 2, None, \"\"\"\na.sh:2: command not found: foo\n\"\"\"),\n\n    FixFileTest('bash a.sh', 'a.sh', 2, None, \"\"\"\na.sh: line 2: foo: command not found\n\"\"\"),\n\n    FixFileTest('rustc a.rs', 'a.rs', 2, 5, \"\"\"\na.rs:2:5: 2:6 error: unexpected token: `+`\na.rs:2     +\n           ^\n\"\"\"),\n\n    FixFileTest('cargo build', 'src/lib.rs', 3, 5, \"\"\"\n   Compiling test v0.1.0 (file:///tmp/fix-error/test)\n   src/lib.rs:3:5: 3:6 error: unexpected token: `+`\n   src/lib.rs:3     +\n                    ^\nCould not compile `test`.\n\nTo learn more, run the command again with --verbose.\n\"\"\"),\n\n    FixFileTest('python a.py', 'a.py', 2, None, \"\"\"\n  File \"a.py\", line 2\n      +\n          ^\nSyntaxError: invalid syntax\n\"\"\"),\n\n    FixFileTest('python a.py', 'a.py', 8, None, \"\"\"\nTraceback (most recent call last):\n  File \"a.py\", line 8, in <module>\n    match(\"foo\")\n  File \"a.py\", line 5, in match\n    m = re.search(None, command)\n  File \"/usr/lib/python3.4/re.py\", line 170, in search\n    return _compile(pattern, flags).search(string)\n  File \"/usr/lib/python3.4/re.py\", line 293, in _compile\n    raise TypeError(\"first argument must be string or compiled pattern\")\nTypeError: first argument must be string or compiled pattern\n\"\"\"),\n\n    FixFileTest(u'python café.py', u'café.py', 8, None, u\"\"\"\nTraceback (most recent call last):\n  File \"café.py\", line 8, in <module>\n    match(\"foo\")\n  File \"café.py\", line 5, in match\n    m = re.search(None, command)\n  File \"/usr/lib/python3.4/re.py\", line 170, in search\n    return _compile(pattern, flags).search(string)\n  File \"/usr/lib/python3.4/re.py\", line 293, in _compile\n    raise TypeError(\"first argument must be string or compiled pattern\")\nTypeError: first argument must be string or compiled pattern\n\"\"\"),\n\n    FixFileTest('ruby a.rb', 'a.rb', 3, None, \"\"\"\na.rb:3: syntax error, unexpected keyword_end\n\"\"\"),\n\n    FixFileTest('lua a.lua', 'a.lua', 2, None, \"\"\"\nlua: a.lua:2: unexpected symbol near '+'\n\"\"\"),\n\n    FixFileTest('fish a.sh', '/tmp/fix-error/a.sh', 2, None, \"\"\"\nfish: Unknown command 'foo'\n/tmp/fix-error/a.sh (line 2): foo\n                              ^\n\"\"\"),\n\n    FixFileTest('./a', './a', 2, None, \"\"\"\nawk: ./a:2: BEGIN { print \"Hello, world!\" + }\nawk: ./a:2:                                 ^ syntax error\n\"\"\"),\n\n    FixFileTest('llc a.ll', 'a.ll', 1, 2, \"\"\"\nllc: a.ll:1:2: error: expected top-level entity\n+\n^\n\"\"\"),\n\n    FixFileTest('go build a.go', 'a.go', 1, 2, \"\"\"\ncan't load package:\na.go:1:2: expected 'package', found '+'\n\"\"\"),\n\n    FixFileTest('make', 'Makefile', 2, None, \"\"\"\nbidule\nmake: bidule: Command not found\nMakefile:2: recipe for target 'target' failed\nmake: *** [target] Error 127\n\"\"\"),\n\n    FixFileTest('git st', '/home/martin/.config/git/config', 1, None, \"\"\"\nfatal: bad config file line 1 in /home/martin/.config/git/config\n\"\"\"),\n\n    FixFileTest('node fuck.js asdf qwer', '/Users/pablo/Workspace/barebones/fuck.js', '2', 5, \"\"\"\n/Users/pablo/Workspace/barebones/fuck.js:2\nconole.log(arg);  // this should read console.log(arg);\n^\nReferenceError: conole is not defined\n    at /Users/pablo/Workspace/barebones/fuck.js:2:5\n    at Array.forEach (native)\n    at Object.<anonymous> (/Users/pablo/Workspace/barebones/fuck.js:1:85)\n    at Module._compile (module.js:460:26)\n    at Object.Module._extensions..js (module.js:478:10)\n    at Module.load (module.js:355:32)\n    at Function.Module._load (module.js:310:12)\n    at Function.Module.runMain (module.js:501:10)\n    at startup (node.js:129:16)\n    at node.js:814:3\n\"\"\"),\n\n    FixFileTest('pep8', './tests/rules/test_systemctl.py', 17, 80, \"\"\"\n./tests/rules/test_systemctl.py:17:80: E501 line too long (93 > 79 characters)\n./tests/rules/test_systemctl.py:18:80: E501 line too long (103 > 79 characters)\n./tests/rules/test_whois.py:20:80: E501 line too long (89 > 79 characters)\n./tests/rules/test_whois.py:22:80: E501 line too long (83 > 79 characters)\n\"\"\"),\n\n    FixFileTest('pytest', '/home/thefuck/tests/rules/test_fix_file.py', 218, None, \"\"\"\nmonkeypatch = <_pytest.monkeypatch.monkeypatch object at 0x7fdb76a25b38>\ntest = ('fish a.sh', '/tmp/fix-error/a.sh', 2, None, '', \"\\\\nfish: Unknown command 'foo'\\\\n/tmp/fix-error/a.sh (line 2): foo\\\\n                              ^\\\\n\")\n\n    @pytest.mark.parametrize('test', tests)\n    @pytest.mark.usefixtures('no_memoize')\n    def test_get_new_command(monkeypatch, test):\n>       mocker.patch('os.path.isfile', return_value=True)\nE       NameError: name 'mocker' is not defined\n\n/home/thefuck/tests/rules/test_fix_file.py:218: NameError\n\"\"\"),\n)\n\n\n@pytest.mark.parametrize('test', tests)\n@pytest.mark.usefixtures('no_memoize')\ndef test_match(mocker, monkeypatch, test):\n    mocker.patch('os.path.isfile', return_value=True)\n    monkeypatch.setenv('EDITOR', 'dummy_editor')\n    assert match(Command('', test.output))\n\n\n@pytest.mark.parametrize('test', tests)\n@pytest.mark.usefixtures('no_memoize')\ndef test_no_editor(mocker, monkeypatch, test):\n    mocker.patch('os.path.isfile', return_value=True)\n    if 'EDITOR' in os.environ:\n        monkeypatch.delenv('EDITOR')\n\n    assert not match(Command('', test.output))\n\n\n@pytest.mark.parametrize('test', tests)\n@pytest.mark.usefixtures('no_memoize')\ndef test_not_file(mocker, monkeypatch, test):\n    mocker.patch('os.path.isfile', return_value=False)\n    monkeypatch.setenv('EDITOR', 'dummy_editor')\n\n    assert not match(Command('', test.output))\n\n\n@pytest.mark.parametrize('test', tests)\n@pytest.mark.usefixtures('no_memoize')\ndef test_get_new_command(mocker, monkeypatch, test):\n    mocker.patch('os.path.isfile', return_value=True)\n    monkeypatch.setenv('EDITOR', 'dummy_editor')\n\n\n@pytest.mark.parametrize('test', tests)\n@pytest.mark.usefixtures('no_memoize')\ndef test_get_new_command_with_settings(mocker, monkeypatch, test, settings):\n    mocker.patch('os.path.isfile', return_value=True)\n    monkeypatch.setenv('EDITOR', 'dummy_editor')\n\n    cmd = Command(test.script, test.output)\n    settings.fixcolcmd = '{editor} {file} +{line}:{col}'\n\n    if test.col:\n        assert (get_new_command(cmd) ==\n                u'dummy_editor {} +{}:{} && {}'.format(test.file, test.line, test.col, test.script))\n    else:\n        assert (get_new_command(cmd) ==\n                u'dummy_editor {} +{} && {}'.format(test.file, test.line, test.script))\n"
  },
  {
    "path": "tests/rules/test_gem_unknown_command.py",
    "content": "import pytest\nfrom six import BytesIO\nfrom thefuck.rules.gem_unknown_command import match, get_new_command\nfrom thefuck.types import Command\n\noutput = '''\nERROR:  While executing gem ... (Gem::CommandLineError)\n    Unknown command {}\n'''\n\ngem_help_commands_stdout = b'''\nGEM commands are:\n\n    build             Build a gem from a gemspec\n    cert              Manage RubyGems certificates and signing settings\n    check             Check a gem repository for added or missing files\n    cleanup           Clean up old versions of installed gems\n    contents          Display the contents of the installed gems\n    dependency        Show the dependencies of an installed gem\n    environment       Display information about the RubyGems environment\n    fetch             Download a gem and place it in the current directory\n    generate_index    Generates the index files for a gem server directory\n    help              Provide help on the 'gem' command\n    install           Install a gem into the local repository\n    list              Display local gems whose name matches REGEXP\n    lock              Generate a lockdown list of gems\n    mirror            Mirror all gem files (requires rubygems-mirror)\n    open              Open gem sources in editor\n    outdated          Display all gems that need updates\n    owner             Manage gem owners of a gem on the push server\n    pristine          Restores installed gems to pristine condition from files\n                      located in the gem cache\n    push              Push a gem up to the gem server\n    query             Query gem information in local or remote repositories\n    rdoc              Generates RDoc for pre-installed gems\n    search            Display remote gems whose name matches REGEXP\n    server            Documentation and gem repository HTTP server\n    sources           Manage the sources and cache file RubyGems uses to search\n                      for gems\n    specification     Display gem specification (in yaml)\n    stale             List gems along with access times\n    uninstall         Uninstall gems from the local repository\n    unpack            Unpack an installed gem to the current directory\n    update            Update installed gems to the latest version\n    which             Find the location of a library file you can require\n    yank              Remove a pushed gem from the index\n\nFor help on a particular command, use 'gem help COMMAND'.\n\nCommands may be abbreviated, so long as they are unambiguous.\ne.g. 'gem i rake' is short for 'gem install rake'.\n\n'''\n\n\n@pytest.fixture(autouse=True)\ndef gem_help_commands(mocker):\n    patch = mocker.patch('subprocess.Popen')\n    patch.return_value.stdout = BytesIO(gem_help_commands_stdout)\n    return patch\n\n\n@pytest.mark.parametrize('script, command', [\n    ('gem isntall jekyll', 'isntall'),\n    ('gem last --local', 'last')])\ndef test_match(script, command):\n    assert match(Command(script, output.format(command)))\n\n\n@pytest.mark.parametrize('script, output', [\n    ('gem install jekyll', ''),\n    ('git log', output.format('log'))])\ndef test_not_match(script, output):\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output, result', [\n    ('gem isntall jekyll', output.format('isntall'), 'gem install jekyll'),\n    ('gem last --local', output.format('last'), 'gem list --local')])\ndef test_get_new_command(script, output, result):\n    new_command = get_new_command(Command(script, output))\n    assert new_command[0] == result\n"
  },
  {
    "path": "tests/rules/test_git_add.py",
    "content": "import pytest\nfrom thefuck.rules.git_add import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture(autouse=True)\ndef path_exists(mocker):\n    return mocker.patch('thefuck.rules.git_add.Path.exists',\n                        return_value=True)\n\n\n@pytest.fixture\ndef output(target):\n    return (\"error: pathspec '{}' did not match any \"\n            'file(s) known to git.'.format(target))\n\n\n@pytest.mark.parametrize('script, target', [\n    ('git submodule update unknown', 'unknown'),\n    ('git commit unknown', 'unknown')])\ndef test_match(output, script, target):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, target, exists', [\n    ('git submodule update known', '', True),\n    ('git commit known', '', True),\n    ('git submodule update known', output, False)])\ndef test_not_match(path_exists, output, script, target, exists):\n    path_exists.return_value = exists\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, target, new_command', [\n    ('git submodule update unknown', 'unknown',\n     'git add -- unknown && git submodule update unknown'),\n    ('git commit unknown', 'unknown',\n     'git add -- unknown && git commit unknown')])\ndef test_get_new_command(output, script, target, new_command):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_add_force.py",
    "content": "import pytest\nfrom thefuck.rules.git_add_force import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output():\n    return ('The following paths are ignored by one of your .gitignore files:\\n'\n            'dist/app.js\\n'\n            'dist/background.js\\n'\n            'dist/options.js\\n'\n            'Use -f if you really want to add them.\\n')\n\n\ndef test_match(output):\n    assert match(Command('git add dist/*.js', output))\n    assert not match(Command('git add dist/*.js', ''))\n\n\ndef test_get_new_command(output):\n    assert (get_new_command(Command('git add dist/*.js', output))\n            == \"git add --force dist/*.js\")\n"
  },
  {
    "path": "tests/rules/test_git_bisect_usage.py",
    "content": "import pytest\nfrom thefuck.types import Command\nfrom thefuck.rules.git_bisect_usage import match, get_new_command\n\n\n@pytest.fixture\ndef output():\n    return (\"usage: git bisect [help|start|bad|good|new|old\"\n            \"|terms|skip|next|reset|visualize|replay|log|run]\")\n\n\n@pytest.mark.parametrize('script', [\n    'git bisect strt', 'git bisect rset', 'git bisect goood'])\ndef test_match(output, script):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script', [\n    'git bisect', 'git bisect start', 'git bisect good'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script, new_cmd, ', [\n    ('git bisect goood', ['good', 'old', 'log']),\n    ('git bisect strt', ['start', 'terms', 'reset']),\n    ('git bisect rset', ['reset', 'next', 'start'])])\ndef test_get_new_command(output, script, new_cmd):\n    new_cmd = ['git bisect %s' % cmd for cmd in new_cmd]\n    assert get_new_command(Command(script, output)) == new_cmd\n"
  },
  {
    "path": "tests/rules/test_git_branch_0flag.py",
    "content": "import pytest\n\nfrom thefuck.rules.git_branch_0flag import get_new_command, match\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output_branch_exists():\n    return \"fatal: A branch named 'bar' already exists.\"\n\n\n@pytest.mark.parametrize(\n    \"script\",\n    [\n        \"git branch 0a\",\n        \"git branch 0d\",\n        \"git branch 0f\",\n        \"git branch 0r\",\n        \"git branch 0v\",\n        \"git branch 0d foo\",\n        \"git branch 0D foo\",\n    ],\n)\ndef test_match(script, output_branch_exists):\n    assert match(Command(script, output_branch_exists))\n\n\n@pytest.mark.parametrize(\n    \"script\",\n    [\n        \"git branch -a\",\n        \"git branch -r\",\n        \"git branch -v\",\n        \"git branch -d foo\",\n        \"git branch -D foo\",\n    ],\n)\ndef test_not_match(script, output_branch_exists):\n    assert not match(Command(script, \"\"))\n\n\n@pytest.mark.parametrize(\n    \"script, new_command\",\n    [\n        (\"git branch 0a\", \"git branch -D 0a && git branch -a\"),\n        (\"git branch 0v\", \"git branch -D 0v && git branch -v\"),\n        (\"git branch 0d foo\", \"git branch -D 0d && git branch -d foo\"),\n        (\"git branch 0D foo\", \"git branch -D 0D && git branch -D foo\"),\n        (\"git branch 0l 'maint-*'\", \"git branch -D 0l && git branch -l 'maint-*'\"),\n        (\"git branch 0u upstream\", \"git branch -D 0u && git branch -u upstream\"),\n    ],\n)\ndef test_get_new_command_branch_exists(script, output_branch_exists, new_command):\n    assert get_new_command(Command(script, output_branch_exists)) == new_command\n\n\n@pytest.fixture\ndef output_not_valid_object():\n    return \"fatal: Not a valid object name: 'bar'.\"\n\n\n@pytest.mark.parametrize(\n    \"script, new_command\",\n    [\n        (\"git branch 0l 'maint-*'\", \"git branch -l 'maint-*'\"),\n        (\"git branch 0u upstream\", \"git branch -u upstream\"),\n    ],\n)\ndef test_get_new_command_not_valid_object(script, output_not_valid_object, new_command):\n    assert get_new_command(Command(script, output_not_valid_object)) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_branch_delete.py",
    "content": "import pytest\nfrom thefuck.rules.git_branch_delete import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output():\n    return '''error: The branch 'branch' is not fully merged.\nIf you are sure you want to delete it, run 'git branch -D branch'.\n\n'''\n\n\ndef test_match(output):\n    assert match(Command('git branch -d branch', output))\n    assert not match(Command('git branch -d branch', ''))\n    assert not match(Command('ls', output))\n\n\ndef test_get_new_command(output):\n    assert get_new_command(Command('git branch -d branch', output))\\\n        == \"git branch -D branch\"\n"
  },
  {
    "path": "tests/rules/test_git_branch_delete_checked_out.py",
    "content": "import pytest\nfrom thefuck.rules.git_branch_delete_checked_out import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output():\n    return \"error: Cannot delete branch 'foo' checked out at '/bar/foo'\"\n\n\n@pytest.mark.parametrize(\"script\", [\"git branch -d foo\", \"git branch -D foo\"])\ndef test_match(script, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize(\"script\", [\"git branch -d foo\", \"git branch -D foo\"])\ndef test_not_match(script):\n    assert not match(Command(script, \"Deleted branch foo (was a1b2c3d).\"))\n\n\n@pytest.mark.parametrize(\n    \"script, new_command\",\n    [\n        (\"git branch -d foo\", \"git checkout master && git branch -D foo\"),\n        (\"git branch -D foo\", \"git checkout master && git branch -D foo\"),\n    ],\n)\ndef test_get_new_command(script, new_command, output):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_branch_exists.py",
    "content": "import pytest\nfrom thefuck.rules.git_branch_exists import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output(src_branch_name):\n    return \"fatal: A branch named '{}' already exists.\".format(src_branch_name)\n\n\n@pytest.fixture\ndef new_command(branch_name):\n    return [cmd.format(branch_name) for cmd in [\n        'git branch -d {0} && git branch {0}',\n        'git branch -d {0} && git checkout -b {0}',\n        'git branch -D {0} && git branch {0}',\n        'git branch -D {0} && git checkout -b {0}', 'git checkout {0}']]\n\n\n@pytest.mark.parametrize('script, src_branch_name, branch_name', [\n    ('git branch foo', 'foo', 'foo'),\n    ('git checkout bar', 'bar', 'bar'),\n    ('git checkout -b \"let\\'s-push-this\"', '\"let\\'s-push-this\"', '\"let\\'s-push-this\"')])\ndef test_match(output, script, branch_name):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script', [\n    'git branch foo',\n    'git checkout bar',\n    'git checkout -b \"let\\'s-push-this\"'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script, src_branch_name, branch_name', [\n    ('git branch foo', 'foo', 'foo'),\n    ('git checkout bar', 'bar', 'bar'),\n    ('git checkout -b \"let\\'s-push-this\"', \"let's-push-this\", \"let\\\\'s-push-this\")])\ndef test_get_new_command(output, new_command, script, src_branch_name, branch_name):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_branch_list.py",
    "content": "from thefuck.rules.git_branch_list import match, get_new_command\nfrom thefuck.shells import shell\nfrom thefuck.types import Command\n\n\ndef test_match():\n    assert match(Command('git branch list', ''))\n\n\ndef test_not_match():\n    assert not match(Command('', ''))\n    assert not match(Command('git commit', ''))\n    assert not match(Command('git branch', ''))\n    assert not match(Command('git stash list', ''))\n\n\ndef test_get_new_command():\n    assert (get_new_command(Command('git branch list', '')) ==\n            shell.and_('git branch --delete list', 'git branch'))\n"
  },
  {
    "path": "tests/rules/test_git_checkout.py",
    "content": "import pytest\nfrom io import BytesIO\nfrom thefuck.rules.git_checkout import match, get_branches, get_new_command\nfrom thefuck.types import Command\n\n\ndef did_not_match(target, did_you_forget=False):\n    error = (\"error: pathspec '{}' did not match any \"\n             \"file(s) known to git.\".format(target))\n    if did_you_forget:\n        error = (\"{}\\nDid you forget to 'git add'?'\".format(error))\n    return error\n\n\n@pytest.fixture\ndef git_branch(mocker, branches):\n    mock = mocker.patch('subprocess.Popen')\n    mock.return_value.stdout = BytesIO(branches)\n    return mock\n\n\n@pytest.mark.parametrize('command', [\n    Command('git checkout unknown', did_not_match('unknown')),\n    Command('git commit unknown', did_not_match('unknown'))])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('git submodule update unknown',\n            did_not_match('unknown', True)),\n    Command('git checkout known', ''),\n    Command('git commit known', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('branches, branch_list', [\n    (b'', []),\n    (b'* master', ['master']),\n    (b'  remotes/origin/master', ['master']),\n    (b'  remotes/origin/test/1', ['test/1']),\n    (b'  remotes/origin/test/1/2/3', ['test/1/2/3']),\n    (b'  test/1', ['test/1']),\n    (b'  test/1/2/3', ['test/1/2/3']),\n    (b'  remotes/origin/HEAD -> origin/master', []),\n    (b'  just-another-branch', ['just-another-branch']),\n    (b'* master\\n  just-another-branch', ['master', 'just-another-branch']),\n    (b'* master\\n  remotes/origin/master\\n  just-another-branch',\n     ['master', 'master', 'just-another-branch'])])\ndef test_get_branches(branches, branch_list, git_branch):\n    git_branch(branches)\n    assert list(get_branches()) == branch_list\n\n\n@pytest.mark.parametrize('branches, command, new_command', [\n    (b'',\n     Command('git checkout unknown', did_not_match('unknown')),\n     ['git checkout -b unknown']),\n    (b'',\n     Command('git commit unknown', did_not_match('unknown')),\n     ['git branch unknown && git commit unknown']),\n    (b'  test-random-branch-123',\n     Command('git checkout tst-rdm-brnch-123',\n             did_not_match('tst-rdm-brnch-123')),\n     ['git checkout test-random-branch-123', 'git checkout -b tst-rdm-brnch-123']),\n    (b'  test-random-branch-123',\n     Command('git commit tst-rdm-brnch-123',\n             did_not_match('tst-rdm-brnch-123')),\n     ['git commit test-random-branch-123'])])\ndef test_get_new_command(branches, command, new_command, git_branch):\n    git_branch(branches)\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_clone_git_clone.py",
    "content": "from thefuck.rules.git_clone_git_clone import match, get_new_command\nfrom thefuck.types import Command\n\n\noutput_clean = \"\"\"\nfatal: Too many arguments.\n\nusage: git clone [<options>] [--] <repo> [<dir>]\n\"\"\"\n\n\ndef test_match():\n    assert match(Command('git clone git clone foo', output_clean))\n\n\ndef test_not_match():\n    assert not match(Command('', ''))\n    assert not match(Command('git branch', ''))\n    assert not match(Command('git clone foo', ''))\n    assert not match(Command('git clone foo bar baz', output_clean))\n\n\ndef test_get_new_command():\n    assert get_new_command(Command('git clone git clone foo', output_clean)) == 'git clone foo'\n"
  },
  {
    "path": "tests/rules/test_git_clone_missing.py",
    "content": "import pytest\nfrom thefuck.rules.git_clone_missing import match, get_new_command\nfrom thefuck.types import Command\n\nvalid_urls = [\n    'https://github.com/nvbn/thefuck.git',\n    'https://github.com/nvbn/thefuck',\n    'http://github.com/nvbn/thefuck.git',\n    'git@github.com:nvbn/thefuck.git',\n    'git@github.com:nvbn/thefuck',\n    'ssh://git@github.com:nvbn/thefuck.git',\n]\ninvalid_urls = [\n    '',  # No command\n    'notacommand',  # Command not found\n    'ssh git@github.com:nvbn/thefrick.git',  # ssh command, not a git clone\n    'git clone foo',  # Valid clone\n    'git clone https://github.com/nvbn/thefuck.git',  # Full command\n    'github.com/nvbn/thefuck.git',  # Missing protocol\n    'github.com:nvbn/thefuck.git',  # SSH missing username\n    'git clone git clone ssh://git@github.com:nvbn/thefrick.git',  # 2x clone\n    'https:/github.com/nvbn/thefuck.git'  # Bad protocol\n]\noutputs = [\n    'No such file or directory',\n    'not found',\n    'is not recognised as',\n]\n\n\n@pytest.mark.parametrize('cmd', valid_urls)\n@pytest.mark.parametrize('output', outputs)\ndef test_match(cmd, output):\n    c = Command(cmd, output)\n    assert match(c)\n\n\n@pytest.mark.parametrize('cmd', invalid_urls)\n@pytest.mark.parametrize('output', outputs + [\"some other output\"])\ndef test_not_match(cmd, output):\n    c = Command(cmd, output)\n    assert not match(c)\n\n\n@pytest.mark.parametrize('script', valid_urls)\n@pytest.mark.parametrize('output', outputs)\ndef test_get_new_command(script, output):\n    command = Command(script, output)\n    new_command = 'git clone ' + script\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_commit_add.py",
    "content": "import pytest\nfrom thefuck.rules.git_commit_add import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize(\n    \"script, output\",\n    [\n        ('git commit -m \"test\"', \"no changes added to commit\"),\n        (\"git commit\", \"no changes added to commit\"),\n    ],\n)\ndef test_match(output, script):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize(\n    \"script, output\",\n    [\n        ('git commit -m \"test\"', \" 1 file changed, 15 insertions(+), 14 deletions(-)\"),\n        (\"git branch foo\", \"\"),\n        (\"git checkout feature/test_commit\", \"\"),\n        (\"git push\", \"\"),\n    ],\n)\ndef test_not_match(output, script):\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize(\n    \"script, new_command\",\n    [\n        (\"git commit\", [\"git commit -a\", \"git commit -p\"]),\n        ('git commit -m \"foo\"', ['git commit -a -m \"foo\"', 'git commit -p -m \"foo\"']),\n    ],\n)\ndef test_get_new_command(script, new_command):\n    assert get_new_command(Command(script, \"\")) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_commit_amend.py",
    "content": "import pytest\nfrom thefuck.rules.git_commit_amend import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('script, output', [\n    ('git commit -m \"test\"', 'test output'),\n    ('git commit', '')])\ndef test_match(output, script):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script', [\n    'git branch foo',\n    'git checkout feature/test_commit',\n    'git push'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script', [\n    ('git commit -m \"test commit\"'),\n    ('git commit')])\ndef test_get_new_command(script):\n    assert get_new_command(Command(script, '')) == 'git commit --amend'\n"
  },
  {
    "path": "tests/rules/test_git_commit_reset.py",
    "content": "import pytest\nfrom thefuck.rules.git_commit_reset import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('script, output', [\n    ('git commit -m \"test\"', 'test output'),\n    ('git commit', '')])\ndef test_match(output, script):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script', [\n    'git branch foo',\n    'git checkout feature/test_commit',\n    'git push'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script', [\n    ('git commit -m \"test commit\"'),\n    ('git commit')])\ndef test_get_new_command(script):\n    assert get_new_command(Command(script, '')) == 'git reset HEAD~'\n"
  },
  {
    "path": "tests/rules/test_git_diff_no_index.py",
    "content": "import pytest\nfrom thefuck.rules.git_diff_no_index import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('git diff foo bar', '')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('git diff --no-index foo bar', ''),\n    Command('git diff foo', ''),\n    Command('git diff foo bar baz', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('git diff foo bar', ''), 'git diff --no-index foo bar')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_diff_staged.py",
    "content": "import pytest\nfrom thefuck.rules.git_diff_staged import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('git diff foo', ''),\n    Command('git diff', '')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('git diff --staged', ''),\n    Command('git tag', ''),\n    Command('git branch', ''),\n    Command('git log', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('git diff', ''), 'git diff --staged'),\n    (Command('git diff foo', ''), 'git diff --staged foo')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_fix_stash.py",
    "content": "import pytest\nfrom thefuck.rules.git_fix_stash import match, get_new_command\nfrom thefuck.types import Command\n\n\ngit_stash_err = '''\nusage: git stash list [<options>]\n   or: git stash show [<stash>]\n   or: git stash drop [-q|--quiet] [<stash>]\n   or: git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]\n   or: git stash branch <branchname> [<stash>]\n   or: git stash [save [--patch] [-k|--[no-]keep-index] [-q|--quiet]\n\\t\\t       [-u|--include-untracked] [-a|--all] [<message>]]\n   or: git stash clear\n'''\n\n\n@pytest.mark.parametrize('wrong', [\n    'git stash opp',\n    'git stash Some message',\n    'git stash saev Some message'])\ndef test_match(wrong):\n    assert match(Command(wrong, git_stash_err))\n\n\ndef test_not_match():\n    assert not match(Command(\"git\", git_stash_err))\n\n\n@pytest.mark.parametrize('wrong,fixed', [\n    ('git stash opp', 'git stash pop'),\n    ('git stash Some message', 'git stash save Some message'),\n    ('git stash saev Some message', 'git stash save Some message')])\ndef test_get_new_command(wrong, fixed):\n    assert get_new_command(Command(wrong, git_stash_err)) == fixed\n"
  },
  {
    "path": "tests/rules/test_git_flag_after_filename.py",
    "content": "import pytest\nfrom thefuck.rules.git_flag_after_filename import match, get_new_command\nfrom thefuck.types import Command\n\ncommand1 = Command('git log README.md -p',\n                   \"fatal: bad flag '-p' used after filename\")\ncommand2 = Command('git log README.md -p CONTRIBUTING.md',\n                   \"fatal: bad flag '-p' used after filename\")\ncommand3 = Command('git log -p README.md --name-only',\n                   \"fatal: bad flag '--name-only' used after filename\")\ncommand4 = Command('git log README.md -p',\n                   \"fatal: option '-p' must come before non-option arguments\")\ncommand5 = Command('git log README.md -p CONTRIBUTING.md',\n                   \"fatal: option '-p' must come before non-option arguments\")\ncommand6 = Command('git log -p README.md --name-only',\n                   \"fatal: option '--name-only' must come before non-option arguments\")\n\n\n@pytest.mark.parametrize('command', [\n    command1, command2, command3, command4, command5, command6])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('git log README.md', ''),\n    Command('git log -p README.md', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, result', [\n    (command1, \"git log -p README.md\"),\n    (command2, \"git log -p README.md CONTRIBUTING.md\"),\n    (command3, \"git log -p --name-only README.md\"),\n    (command4, \"git log -p README.md\"),\n    (command5, \"git log -p README.md CONTRIBUTING.md\"),\n    (command6, \"git log -p --name-only README.md\")])\ndef test_get_new_command(command, result):\n    assert get_new_command(command) == result\n"
  },
  {
    "path": "tests/rules/test_git_help_aliased.py",
    "content": "import pytest\nfrom thefuck.rules.git_help_aliased import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('script, output', [\n    ('git help st', \"`git st' is aliased to `status'\"),\n    ('git help ds', \"`git ds' is aliased to `diff --staged'\")])\ndef test_match(script, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output', [\n    ('git help status', \"GIT-STATUS(1)...Git Manual...GIT-STATUS(1)\"),\n    ('git help diff', \"GIT-DIFF(1)...Git Manual...GIT-DIFF(1)\")])\ndef test_not_match(script, output):\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output, new_command', [\n    ('git help st', \"`git st' is aliased to `status'\", 'git help status'),\n    ('git help ds', \"`git ds' is aliased to `diff --staged'\", 'git help diff')])\ndef test_get_new_command(script, output, new_command):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_hook_bypass.py",
    "content": "import pytest\nfrom thefuck.rules.git_hook_bypass import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize(\n    \"command\",\n    [\n        Command(\"git am\", \"\"),\n        Command(\"git commit\", \"\"),\n        Command(\"git commit -m 'foo bar'\", \"\"),\n        Command(\"git push\", \"\"),\n        Command(\"git push -u foo bar\", \"\"),\n    ],\n)\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize(\n    \"command\",\n    [\n        Command(\"git add foo\", \"\"),\n        Command(\"git status\", \"\"),\n        Command(\"git diff foo bar\", \"\"),\n    ],\n)\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize(\n    \"command, new_command\",\n    [\n        (Command(\"git am\", \"\"), \"git am --no-verify\"),\n        (Command(\"git commit\", \"\"), \"git commit --no-verify\"),\n        (Command(\"git commit -m 'foo bar'\", \"\"), \"git commit --no-verify -m 'foo bar'\"),\n        (Command(\"git push\", \"\"), \"git push --no-verify\"),\n        (Command(\"git push -p\", \"\"), \"git push --no-verify -p\"),\n    ],\n)\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_lfs_mistype.py",
    "content": "import pytest\n\nfrom thefuck.rules.git_lfs_mistype import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef mistype_response():\n    return \"\"\"\nError: unknown command \"evn\" for \"git-lfs\"\n\nDid you mean this?\n        env\n        ext\n\nRun 'git-lfs --help' for usage.\n    \"\"\"\n\n\ndef test_match(mistype_response):\n    assert match(Command('git lfs evn', mistype_response))\n    err_response = 'bash: git: command not found'\n    assert not match(Command('git lfs env', err_response))\n    assert not match(Command('docker lfs env', mistype_response))\n\n\ndef test_get_new_command(mistype_response):\n    assert (get_new_command(Command('git lfs evn', mistype_response))\n            == ['git lfs env', 'git lfs ext'])\n"
  },
  {
    "path": "tests/rules/test_git_main_master.py",
    "content": "import pytest\nfrom thefuck.rules.git_main_master import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output(branch_name):\n    if not branch_name:\n        return \"\"\n    output_str = u\"error: pathspec '{}' did not match any file(s) known to git\"\n    return output_str.format(branch_name)\n\n\n@pytest.mark.parametrize(\n    \"script, branch_name\",\n    [\n        (\"git checkout main\", \"main\"),\n        (\"git checkout master\", \"master\"),\n        (\"git show main\", \"main\"),\n    ],\n)\ndef test_match(script, branch_name, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize(\n    \"script, branch_name\",\n    [\n        (\"git checkout master\", \"\"),\n        (\"git checkout main\", \"\"),\n        (\"git checkout wibble\", \"wibble\"),\n    ],\n)\ndef test_not_match(script, branch_name, output):\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize(\n    \"script, branch_name, new_command\",\n    [\n        (\"git checkout main\", \"main\", \"git checkout master\"),\n        (\"git checkout master\", \"master\", \"git checkout main\"),\n        (\"git checkout wibble\", \"wibble\", \"git checkout wibble\"),\n    ],\n)\ndef test_get_new_command(script, branch_name, new_command, output):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_merge.py",
    "content": "import pytest\nfrom thefuck.rules.git_merge import match, get_new_command\nfrom thefuck.types import Command\n\n\noutput = 'merge: local - not something we can merge\\n\\n' \\\n         'Did you mean this?\\n\\tremote/local'\n\n\ndef test_match():\n    assert match(Command('git merge test', output))\n    assert not match(Command('git merge master', ''))\n    assert not match(Command('ls', output))\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('git merge local', output),\n     'git merge remote/local'),\n    (Command('git merge -m \"test\" local', output),\n     'git merge -m \"test\" remote/local'),\n    (Command('git merge -m \"test local\" local', output),\n     'git merge -m \"test local\" remote/local')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_merge_unrelated.py",
    "content": "import pytest\nfrom thefuck.rules.git_merge_unrelated import match, get_new_command\nfrom thefuck.types import Command\n\n\noutput = 'fatal: refusing to merge unrelated histories'\n\n\ndef test_match():\n    assert match(Command('git merge test', output))\n    assert not match(Command('git merge master', ''))\n    assert not match(Command('ls', output))\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('git merge local', output),\n     'git merge local --allow-unrelated-histories'),\n    (Command('git merge -m \"test\" local', output),\n     'git merge -m \"test\" local --allow-unrelated-histories'),\n    (Command('git merge -m \"test local\" local', output),\n     'git merge -m \"test local\" local --allow-unrelated-histories')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_not_command.py",
    "content": "import pytest\nfrom thefuck.rules.git_not_command import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef git_not_command():\n    return \"\"\"git: 'brnch' is not a git command. See 'git --help'.\n\nThe most similar command is\nbranch\n\"\"\"\n\n\n@pytest.fixture\ndef git_not_command_one_of_this():\n    return \"\"\"git: 'st' is not a git command. See 'git --help'.\n\nThe most similar commands are\nstatus\nreset\nstage\nstash\nstats\n\"\"\"\n\n\n@pytest.fixture\ndef git_not_command_closest():\n    return '''git: 'tags' is not a git command. See 'git --help'.\n\nThe most similar commands are\n\\tstage\n\\ttag\n'''\n\n\n@pytest.fixture\ndef git_command():\n    return \"* master\"\n\n\ndef test_match(git_not_command, git_command, git_not_command_one_of_this):\n    assert match(Command('git brnch', git_not_command))\n    assert match(Command('git st', git_not_command_one_of_this))\n    assert not match(Command('ls brnch', git_not_command))\n    assert not match(Command('git branch', git_command))\n\n\ndef test_get_new_command(git_not_command, git_not_command_one_of_this,\n                         git_not_command_closest):\n    assert (get_new_command(Command('git brnch', git_not_command))\n            == ['git branch'])\n    assert (get_new_command(Command('git st', git_not_command_one_of_this))\n            == ['git stats', 'git stash', 'git stage'])\n    assert (get_new_command(Command('git tags', git_not_command_closest))\n            == ['git tag', 'git stage'])\n"
  },
  {
    "path": "tests/rules/test_git_pull.py",
    "content": "import pytest\nfrom thefuck.rules.git_pull import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output():\n    return '''There is no tracking information for the current branch.\nPlease specify which branch you want to merge with.\nSee git-pull(1) for details\n\n    git pull <remote> <branch>\n\nIf you wish to set tracking information for this branch you can do so with:\n\n    git branch --set-upstream-to=<remote>/<branch> master\n\n'''\n\n\ndef test_match(output):\n    assert match(Command('git pull', output))\n    assert not match(Command('git pull', ''))\n    assert not match(Command('ls', output))\n\n\ndef test_get_new_command(output):\n    assert (get_new_command(Command('git pull', output))\n            == \"git branch --set-upstream-to=origin/master master && git pull\")\n"
  },
  {
    "path": "tests/rules/test_git_pull_clone.py",
    "content": "import pytest\nfrom thefuck.rules.git_pull_clone import match, get_new_command\nfrom thefuck.types import Command\n\n\ngit_err = '''\nfatal: Not a git repository (or any parent up to mount point /home)\nStopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\n'''\n\n\n@pytest.mark.parametrize('command', [\n    Command('git pull git@github.com:mcarton/thefuck.git', git_err)])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command, output', [\n    (Command('git pull git@github.com:mcarton/thefuck.git', git_err), 'git clone git@github.com:mcarton/thefuck.git')])\ndef test_get_new_command(command, output):\n    assert get_new_command(command) == output\n"
  },
  {
    "path": "tests/rules/test_git_pull_uncommitted_changes.py",
    "content": "import pytest\nfrom thefuck.rules.git_pull_uncommitted_changes import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output():\n    return '''error: Cannot pull with rebase: You have unstaged changes.'''\n\n\ndef test_match(output):\n    assert match(Command('git pull', output))\n    assert not match(Command('git pull', ''))\n    assert not match(Command('ls', output))\n\n\ndef test_get_new_command(output):\n    assert (get_new_command(Command('git pull', output))\n            == \"git stash && git pull && git stash pop\")\n"
  },
  {
    "path": "tests/rules/test_git_pull_unstaged_changes.py",
    "content": "import pytest\nfrom thefuck.rules.git_pull_uncommitted_changes import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output():\n    return '''error: Cannot pull with rebase: Your index contains uncommitted changes.'''\n\n\ndef test_match(output):\n    assert match(Command('git pull', output))\n    assert not match(Command('git pull', ''))\n    assert not match(Command('ls', output))\n\n\ndef test_get_new_command(output):\n    assert (get_new_command(Command('git pull', output))\n            == \"git stash && git pull && git stash pop\")\n"
  },
  {
    "path": "tests/rules/test_git_push.py",
    "content": "import pytest\nfrom thefuck.rules.git_push import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output(branch_name):\n    if not branch_name:\n        return ''\n    return '''fatal: The current branch {} has no upstream branch.\nTo push the current branch and set the remote as upstream, use\n\n    git push --set-upstream origin {}\n\n'''.format(branch_name, branch_name)\n\n\n@pytest.fixture\ndef output_bitbucket():\n    return '''Total 0 (delta 0), reused 0 (delta 0)\nremote:\nremote: Create pull request for feature/set-upstream:\nremote:   https://bitbucket.org/set-upstream\nremote:\nTo git@bitbucket.org:test.git\n   e5e7fbb..700d998  feature/set-upstream -> feature/set-upstream\nBranch feature/set-upstream set up to track remote branch feature/set-upstream from origin.\n'''\n\n\n@pytest.mark.parametrize('script, branch_name', [\n    ('git push', 'master'),\n    ('git push origin', 'master')])\ndef test_match(output, script, branch_name):\n    assert match(Command(script, output))\n\n\ndef test_match_bitbucket(output_bitbucket):\n    assert not match(Command('git push origin', output_bitbucket))\n\n\n@pytest.mark.parametrize('script, branch_name', [\n    ('git push master', None),\n    ('ls', 'master')])\ndef test_not_match(output, script, branch_name):\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, branch_name, new_command', [\n    ('git push', 'master',\n     'git push --set-upstream origin master'),\n    ('git push master', 'master',\n     'git push --set-upstream origin master'),\n    ('git push -u', 'master',\n     'git push --set-upstream origin master'),\n    ('git push -u origin', 'master',\n     'git push --set-upstream origin master'),\n    ('git push origin', 'master',\n     'git push --set-upstream origin master'),\n    ('git push --set-upstream origin', 'master',\n     'git push --set-upstream origin master'),\n    ('git push --quiet', 'master',\n     'git push --set-upstream origin master --quiet'),\n    ('git push --quiet origin', 'master',\n     'git push --set-upstream origin master --quiet'),\n    ('git -c test=test push --quiet origin', 'master',\n     'git -c test=test push --set-upstream origin master --quiet'),\n    ('git push', \"test's\",\n     \"git push --set-upstream origin test\\\\'s\"),\n    ('git push --force', 'master',\n     'git push --set-upstream origin master --force'),\n    ('git push --force-with-lease', 'master',\n     'git push --set-upstream origin master --force-with-lease')])\ndef test_get_new_command(output, script, branch_name, new_command):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_push_different_branch_names.py",
    "content": "import pytest\nfrom thefuck.rules.git_push_different_branch_names import get_new_command, match\nfrom thefuck.types import Command\n\n\noutput = \"\"\"fatal: The upstream branch of your current branch does not match\nthe name of your current branch.  To push to the upstream branch\non the remote, use\n\n    git push origin HEAD:%s\n\nTo push to the branch of the same name on the remote, use\n\n    git push origin %s\n\nTo choose either option permanently, see push.default in 'git help config'.\n\"\"\"\n\n\ndef error_msg(localbranch, remotebranch):\n    return output % (remotebranch, localbranch)\n\n\ndef test_match():\n    assert match(Command('git push', error_msg('foo', 'bar')))\n\n\n@pytest.mark.parametrize('command', [\n    Command('vim', ''),\n    Command('git status', error_msg('foo', 'bar')),\n    Command('git push', '')\n])\ndef test_not_match(command):\n    assert not match(command)\n\n\ndef test_get_new_command():\n    new_command = get_new_command(Command('git push', error_msg('foo', 'bar')))\n    assert new_command == 'git push origin HEAD:bar'\n"
  },
  {
    "path": "tests/rules/test_git_push_force.py",
    "content": "import pytest\nfrom thefuck.rules.git_push_force import match, get_new_command\nfrom thefuck.types import Command\n\n\ngit_err = '''\nTo /tmp/foo\n ! [rejected]        master -> master (non-fast-forward)\n error: failed to push some refs to '/tmp/bar'\n hint: Updates were rejected because the tip of your current branch is behind\n hint: its remote counterpart. Integrate the remote changes (e.g.\n hint: 'git pull ...') before pushing again.\n hint: See the 'Note about fast-forwards' in 'git push --help' for details.\n'''\n\ngit_uptodate = 'Everything up-to-date'\ngit_ok = '''\nCounting objects: 3, done.\nDelta compression using up to 4 threads.\nCompressing objects: 100% (2/2), done.\nWriting objects: 100% (3/3), 282 bytes | 0 bytes/s, done.\nTotal 3 (delta 0), reused 0 (delta 0)\nTo /tmp/bar\n   514eed3..f269c79  master -> master\n'''\n\n\n@pytest.mark.parametrize('command', [\n    Command('git push', git_err),\n    Command('git push nvbn', git_err),\n    Command('git push nvbn master', git_err)])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('git push', git_ok),\n    Command('git push', git_uptodate),\n    Command('git push nvbn', git_ok),\n    Command('git push nvbn master', git_uptodate),\n    Command('git push nvbn', git_ok),\n    Command('git push nvbn master', git_uptodate)])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, output', [\n    (Command('git push', git_err), 'git push --force-with-lease'),\n    (Command('git push nvbn', git_err), 'git push --force-with-lease nvbn'),\n    (Command('git push nvbn master', git_err), 'git push --force-with-lease nvbn master')])\ndef test_get_new_command(command, output):\n    assert get_new_command(command) == output\n"
  },
  {
    "path": "tests/rules/test_git_push_pull.py",
    "content": "import pytest\nfrom thefuck.rules.git_push_pull import match, get_new_command\nfrom thefuck.types import Command\n\n\ngit_err = '''\nTo /tmp/foo\n ! [rejected]        master -> master (non-fast-forward)\n error: failed to push some refs to '/tmp/bar'\n hint: Updates were rejected because the tip of your current branch is behind\n hint: its remote counterpart. Integrate the remote changes (e.g.\n hint: 'git pull ...') before pushing again.\n hint: See the 'Note about fast-forwards' in 'git push --help' for details.\n'''\n\ngit_err2 = '''\nTo /tmp/foo\n ! [rejected]        master -> master (non-fast-forward)\n error: failed to push some refs to '/tmp/bar'\nhint: Updates were rejected because the remote contains work that you do\nhint: not have locally. This is usually caused by another repository pushing\nhint: to the same ref. You may want to first integrate the remote changes\nhint: (e.g., 'git pull ...') before pushing again.\nhint: See the 'Note about fast-forwards' in 'git push --help' for details.\n'''\n\ngit_uptodate = 'Everything up-to-date'\ngit_ok = '''\nCounting objects: 3, done.\nDelta compression using up to 4 threads.\nCompressing objects: 100% (2/2), done.\nWriting objects: 100% (3/3), 282 bytes | 0 bytes/s, done.\nTotal 3 (delta 0), reused 0 (delta 0)\nTo /tmp/bar\n   514eed3..f269c79  master -> master\n'''\n\n\n@pytest.mark.parametrize('command', [\n    Command('git push', git_err),\n    Command('git push nvbn', git_err),\n    Command('git push nvbn master', git_err),\n    Command('git push', git_err2),\n    Command('git push nvbn', git_err2),\n    Command('git push nvbn master', git_err2)])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('git push', git_ok),\n    Command('git push', git_uptodate),\n    Command('git push nvbn', git_ok),\n    Command('git push nvbn master', git_uptodate),\n    Command('git push nvbn', git_ok),\n    Command('git push nvbn master', git_uptodate)])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, output', [\n    (Command('git push', git_err), 'git pull && git push'),\n    (Command('git push nvbn', git_err),\n     'git pull nvbn && git push nvbn'),\n    (Command('git push nvbn master', git_err),\n     'git pull nvbn master && git push nvbn master'),\n    (Command('git push', git_err2), 'git pull && git push'),\n    (Command('git push nvbn', git_err2),\n     'git pull nvbn && git push nvbn'),\n    (Command('git push nvbn master', git_err2),\n     'git pull nvbn master && git push nvbn master')])\ndef test_get_new_command(command, output):\n    assert get_new_command(command) == output\n"
  },
  {
    "path": "tests/rules/test_git_push_without_commits.py",
    "content": "from thefuck.types import Command\nfrom thefuck.rules.git_push_without_commits import get_new_command, match\n\n\ndef test_match():\n    script = \"git push -u origin master\"\n    output = \"error: src refspec master does not match any\\nerror: failed to...\"\n    assert match(Command(script, output))\n\n\ndef test_not_match():\n    script = \"git push -u origin master\"\n    assert not match(Command(script, \"Everything up-to-date\"))\n\n\ndef test_get_new_command():\n    script = \"git push -u origin master\"\n    output = \"error: src refspec master does not match any\\nerror: failed to...\"\n    new_command = 'git commit -m \"Initial commit\" && git push -u origin master'\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_rebase_merge_dir.py",
    "content": "import pytest\nfrom thefuck.rules.git_rebase_merge_dir import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output():\n    return ('\\n\\nIt seems that there is already a rebase-merge directory, and\\n'\n            'I wonder if you are in the middle of another rebase.  If that is the\\n'\n            'case, please try\\n'\n            '\\tgit rebase (--continue | --abort | --skip)\\n'\n            'If that is not the case, please\\n'\n            '\\trm -fr \"/foo/bar/baz/egg/.git/rebase-merge\"\\n'\n            'and run me again.  I am stopping in case you still have something\\n'\n            'valuable there.\\n')\n\n\n@pytest.mark.parametrize('script', [\n    'git rebase master',\n    'git rebase -skip',\n    'git rebase'])\ndef test_match(output, script):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script', ['git rebase master', 'git rebase -abort'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script, result', [\n    ('git rebase master', [\n        'git rebase --abort', 'git rebase --skip', 'git rebase --continue',\n        'rm -fr \"/foo/bar/baz/egg/.git/rebase-merge\"']),\n    ('git rebase -skip', [\n        'git rebase --skip', 'git rebase --abort', 'git rebase --continue',\n        'rm -fr \"/foo/bar/baz/egg/.git/rebase-merge\"']),\n    ('git rebase', [\n        'git rebase --skip', 'git rebase --abort', 'git rebase --continue',\n        'rm -fr \"/foo/bar/baz/egg/.git/rebase-merge\"'])])\ndef test_get_new_command(output, script, result):\n    assert get_new_command(Command(script, output)) == result\n"
  },
  {
    "path": "tests/rules/test_git_rebase_no_changes.py",
    "content": "import pytest\nfrom thefuck.rules.git_rebase_no_changes import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output():\n    return '''Applying: Test commit\nNo changes - did you forget to use 'git add'?\nIf there is nothing left to stage, chances are that something else\nalready introduced the same changes; you might want to skip this patch.\n\nWhen you have resolved this problem, run \"git rebase --continue\".\nIf you prefer to skip this patch, run \"git rebase --skip\" instead.\nTo check out the original branch and stop rebasing, run \"git rebase --abort\".\n\n'''\n\n\ndef test_match(output):\n    assert match(Command('git rebase --continue', output))\n    assert not match(Command('git rebase --continue', ''))\n    assert not match(Command('git rebase --skip', ''))\n\n\ndef test_get_new_command(output):\n    assert (get_new_command(Command('git rebase --continue', output)) ==\n            'git rebase --skip')\n"
  },
  {
    "path": "tests/rules/test_git_remote_delete.py",
    "content": "import pytest\nfrom thefuck.rules.git_remote_delete import get_new_command, match\nfrom thefuck.types import Command\n\n\ndef test_match():\n    assert match(Command('git remote delete foo', ''))\n\n\n@pytest.mark.parametrize('command', [\n    Command('git remote remove foo', ''),\n    Command('git remote add foo', ''),\n    Command('git commit', '')\n])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('git remote delete foo', ''), 'git remote remove foo'),\n    (Command('git remote delete delete', ''), 'git remote remove delete'),\n])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_remote_seturl_add.py",
    "content": "import pytest\nfrom thefuck.rules.git_remote_seturl_add import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('git remote set-url origin url', \"fatal: No such remote\")])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('git remote set-url origin url', \"\"),\n    Command('git remote add origin url', ''),\n    Command('git remote remove origin', ''),\n    Command('git remote prune origin', ''),\n    Command('git remote set-branches origin branch', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('git remote set-url origin git@github.com:nvbn/thefuck.git', ''),\n     'git remote add origin git@github.com:nvbn/thefuck.git')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_rm_local_modifications.py",
    "content": "import pytest\nfrom thefuck.rules.git_rm_local_modifications import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output(target):\n    return ('error: the following file has local modifications:\\n    {}\\n(use '\n            '--cached to keep the file, or -f to force removal)').format(target)\n\n\n@pytest.mark.parametrize('script, target', [\n    ('git rm foo', 'foo'),\n    ('git rm foo bar', 'bar')])\ndef test_match(output, script, target):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script', ['git rm foo', 'git rm foo bar', 'git rm'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script, target, new_command', [\n    ('git rm foo', 'foo', ['git rm --cached foo', 'git rm -f foo']),\n    ('git rm foo bar', 'bar', ['git rm --cached foo bar', 'git rm -f foo bar'])])\ndef test_get_new_command(output, script, target, new_command):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_rm_recursive.py",
    "content": "import pytest\nfrom thefuck.rules.git_rm_recursive import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output(target):\n    return \"fatal: not removing '{}' recursively without -r\".format(target)\n\n\n@pytest.mark.parametrize('script, target', [\n    ('git rm foo', 'foo'),\n    ('git rm foo bar', 'foo bar')])\ndef test_match(output, script, target):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script', ['git rm foo', 'git rm foo bar'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script, target, new_command', [\n    ('git rm foo', 'foo', 'git rm -r foo'),\n    ('git rm foo bar', 'foo bar', 'git rm -r foo bar')])\ndef test_get_new_command(output, script, target, new_command):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_rm_staged.py",
    "content": "import pytest\nfrom thefuck.rules.git_rm_staged import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output(target):\n    return ('error: the following file has changes staged in the index:\\n    {}\\n(use '\n            '--cached to keep the file, or -f to force removal)').format(target)\n\n\n@pytest.mark.parametrize('script, target', [\n    ('git rm foo', 'foo'),\n    ('git rm foo bar', 'bar')])\ndef test_match(output, script, target):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script', ['git rm foo', 'git rm foo bar', 'git rm'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script, target, new_command', [\n    ('git rm foo', 'foo', ['git rm --cached foo', 'git rm -f foo']),\n    ('git rm foo bar', 'bar', ['git rm --cached foo bar', 'git rm -f foo bar'])])\ndef test_get_new_command(output, script, target, new_command):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_stash.py",
    "content": "import pytest\nfrom thefuck.rules.git_stash import match, get_new_command\nfrom thefuck.types import Command\n\n\ncherry_pick_error = (\n    'error: Your local changes would be overwritten by cherry-pick.\\n'\n    'hint: Commit your changes or stash them to proceed.\\n'\n    'fatal: cherry-pick failed')\n\n\nrebase_error = (\n    'Cannot rebase: Your index contains uncommitted changes.\\n'\n    'Please commit or stash them.')\n\n\n@pytest.mark.parametrize('command', [\n    Command('git cherry-pick a1b2c3d', cherry_pick_error),\n    Command('git rebase -i HEAD~7', rebase_error)])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('git cherry-pick a1b2c3d', ''),\n    Command('git rebase -i HEAD~7', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('git cherry-pick a1b2c3d', cherry_pick_error),\n     'git stash && git cherry-pick a1b2c3d'),\n    (Command('git rebase -i HEAD~7', rebase_error),\n     'git stash && git rebase -i HEAD~7')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_git_stash_pop.py",
    "content": "import pytest\nfrom thefuck.rules.git_stash_pop import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output():\n    return '''error: Your local changes to the following files would be overwritten by merge:'''\n\n\ndef test_match(output):\n    assert match(Command('git stash pop', output))\n    assert not match(Command('git stash', ''))\n\n\ndef test_get_new_command(output):\n    assert (get_new_command(Command('git stash pop', output))\n            == \"git add --update && git stash pop && git reset .\")\n"
  },
  {
    "path": "tests/rules/test_git_tag_force.py",
    "content": "import pytest\nfrom thefuck.rules.git_tag_force import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output():\n    return '''fatal: tag 'alert' already exists'''\n\n\ndef test_match(output):\n    assert match(Command('git tag alert', output))\n    assert not match(Command('git tag alert', ''))\n\n\ndef test_get_new_command(output):\n    assert (get_new_command(Command('git tag alert', output))\n            == \"git tag --force alert\")\n"
  },
  {
    "path": "tests/rules/test_git_two_dashes.py",
    "content": "import pytest\nfrom thefuck.rules.git_two_dashes import match, get_new_command\nfrom thefuck.types import Command\n\n\noutput = 'error: did you mean `{}` (with two dashes ?)'.format\n\n\n@pytest.mark.parametrize('command', [\n    Command('git add -patch', output('--patch')),\n    Command('git checkout -patch', output('--patch')),\n    Command('git commit -amend', output('--amend')),\n    Command('git push -tags', output('--tags')),\n    Command('git rebase -continue', output('--continue'))])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('git add --patch', ''),\n    Command('git checkout --patch', ''),\n    Command('git commit --amend', ''),\n    Command('git push --tags', ''),\n    Command('git rebase --continue', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, output', [\n    (Command('git add -patch', output('--patch')),\n        'git add --patch'),\n    (Command('git checkout -patch', output('--patch')),\n        'git checkout --patch'),\n    (Command('git checkout -patch', output('--patch')),\n        'git checkout --patch'),\n    (Command('git init -bare', output('--bare')),\n        'git init --bare'),\n    (Command('git commit -amend', output('--amend')),\n        'git commit --amend'),\n    (Command('git push -tags', output('--tags')),\n        'git push --tags'),\n    (Command('git rebase -continue', output('--continue')),\n        'git rebase --continue')])\ndef test_get_new_command(command, output):\n    assert get_new_command(command) == output\n"
  },
  {
    "path": "tests/rules/test_go_run.py",
    "content": "import pytest\nfrom thefuck.rules.go_run import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('go run foo', ''),\n    Command('go run bar', '')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('go run foo', ''), 'go run foo.go'),\n    (Command('go run bar', ''), 'go run bar.go')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_go_unknown_command.py",
    "content": "import pytest\nfrom io import BytesIO\nfrom thefuck.rules.go_unknown_command import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef build_misspelled_output():\n    return '''go bulid: unknown command\nRun 'go help' for usage.'''\n\n\n@pytest.fixture\ndef go_stderr(mocker):\n    stderr = b'''Go is a tool for managing Go source code.\n\nUsage:\n\n\\tgo <command> [arguments]\n\nThe commands are:\n\n\\tbug         start a bug report\n\\tbuild       compile packages and dependencies\n\\tclean       remove object files and cached files\n\\tdoc         show documentation for package or symbol\n\\tenv         print Go environment information\n\\tfix         update packages to use new APIs\n\\tfmt         gofmt (reformat) package sources\n\\tgenerate    generate Go files by processing source\n\\tget         add dependencies to current module and install them\n\\tinstall     compile and install packages and dependencies\n\\tlist        list packages or modules\n\\tmod         module maintenance\n\\trun         compile and run Go program\n\\ttest        test packages\n\\ttool        run specified go tool\n\\tversion     print Go version\n\\tvet         report likely mistakes in packages\n\nUse \"go help <command>\" for more information about a command.\n\nAdditional help topics:\n\n\\tbuildconstraint build constraints\n\\tbuildmode       build modes\n\\tc               calling between Go and C\n\\tcache           build and test caching\n\\tenvironment     environment variables\n\\tfiletype        file types\n\\tgo.mod          the go.mod file\n\\tgopath          GOPATH environment variable\n\\tgopath-get      legacy GOPATH go get\n\\tgoproxy         module proxy protocol\n\\timportpath      import path syntax\n\\tmodules         modules, module versions, and more\n\\tmodule-get      module-aware go get\n\\tmodule-auth     module authentication using go.sum\n\\tmodule-private  module configuration for non-public modules\n\\tpackages        package lists and patterns\n\\ttestflag        testing flags\n\\ttestfunc        testing functions\n\nUse \"go help <topic>\" for more information about that topic.\n\n'''\n    mock = mocker.patch('subprocess.Popen')\n    mock.return_value.stderr = BytesIO(stderr)\n    return mock\n\n\ndef test_match(build_misspelled_output):\n    assert match(Command('go bulid', build_misspelled_output))\n\n\ndef test_not_match():\n    assert not match(Command('go run', 'go run: no go files listed'))\n\n\n@pytest.mark.usefixtures('no_memoize', 'go_stderr')\ndef test_get_new_command(build_misspelled_output):\n    assert get_new_command(Command('go bulid', build_misspelled_output)) == 'go build'\n"
  },
  {
    "path": "tests/rules/test_gradle_not_task.py",
    "content": "import pytest\nfrom io import BytesIO\nfrom thefuck.rules.gradle_no_task import match, get_new_command\nfrom thefuck.types import Command\n\ngradle_tasks = b'''\n:tasks\n\n------------------------------------------------------------\nAll tasks runnable from root project\n------------------------------------------------------------\n\nAndroid tasks\n-------------\nandroidDependencies - Displays the Android dependencies of the project.\nsigningReport - Displays the signing info for each variant.\nsourceSets - Prints out all the source sets defined in this project.\n\nBuild tasks\n-----------\nassemble - Assembles all variants of all applications and secondary packages.\nassembleAndroidTest - Assembles all the Test applications.\nassembleDebug - Assembles all Debug builds.\nassembleRelease - Assembles all Release builds.\nbuild - Assembles and tests this project.\nbuildDependents - Assembles and tests this project and all projects that depend on it.\nbuildNeeded - Assembles and tests this project and all projects it depends on.\ncompileDebugAndroidTestSources\ncompileDebugSources\ncompileDebugUnitTestSources\ncompileReleaseSources\ncompileReleaseUnitTestSources\nextractDebugAnnotations - Extracts Android annotations for the debug variant into the archive file\nextractReleaseAnnotations - Extracts Android annotations for the release variant into the archive file\nmockableAndroidJar - Creates a version of android.jar that's suitable for unit tests.\n\nBuild Setup tasks\n-----------------\ninit - Initializes a new Gradle build. [incubating]\nwrapper - Generates Gradle wrapper files. [incubating]\n\nHelp tasks\n----------\ncomponents - Displays the components produced by root project 'org.rerenderer_example.snake'. [incubating]\ndependencies - Displays all dependencies declared in root project 'org.rerenderer_example.snake'.\ndependencyInsight - Displays the insight into a specific dependency in root project 'org.rerenderer_example.snake'.\nhelp - Displays a help message.\nmodel - Displays the configuration model of root project 'org.rerenderer_example.snake'. [incubating]\nprojects - Displays the sub-projects of root project 'org.rerenderer_example.snake'.\nproperties - Displays the properties of root project 'org.rerenderer_example.snake'.\ntasks - Displays the tasks runnable from root project 'org.rerenderer_example.snake' (some of the displayed tasks may belong to subprojects).\n\nInstall tasks\n-------------\ninstallDebug - Installs the Debug build.\ninstallDebugAndroidTest - Installs the android (on device) tests for the Debug build.\ninstallRelease - Installs the Release build.\nuninstallAll - Uninstall all applications.\nuninstallDebug - Uninstalls the Debug build.\nuninstallDebugAndroidTest - Uninstalls the android (on device) tests for the Debug build.\nuninstallRelease - Uninstalls the Release build.\n\nReact tasks\n-----------\nbundleDebugJsAndAssets - bundle JS and assets for Debug.\nbundleReleaseJsAndAssets - bundle JS and assets for Release.\n\nVerification tasks\n------------------\ncheck - Runs all checks.\nclean - Deletes the build directory.\nconnectedAndroidTest - Installs and runs instrumentation tests for all flavors on connected devices.\nconnectedCheck - Runs all device checks on currently connected devices.\nconnectedDebugAndroidTest - Installs and runs the tests for debug on connected devices.\ndeviceAndroidTest - Installs and runs instrumentation tests using all Device Providers.\ndeviceCheck - Runs all device checks using Device Providers and Test Servers.\nlint - Runs lint on all variants.\nlintDebug - Runs lint on the Debug build.\nlintRelease - Runs lint on the Release build.\ntest - Run unit tests for all variants.\ntestDebugUnitTest - Run unit tests for the debug build.\ntestReleaseUnitTest - Run unit tests for the release build.\n\nOther tasks\n-----------\nassembleDefault\ncopyDownloadableDepsToLibs\njarDebugClasses\njarReleaseClasses\n\nTo see all tasks and more detail, run gradlew tasks --all\n\nTo see more detail about a task, run gradlew help --task <task>\n\nBUILD SUCCESSFUL\n\nTotal time: 1.936 secs\n'''\n\noutput_not_found = '''\n\nFAILURE: Build failed with an exception.\n\n* What went wrong:\nTask '{}' not found in root project 'org.rerenderer_example.snake'.\n\n* Try:\nRun gradlew tasks to get a list of available tasks. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.\n'''.format\n\noutput_ambiguous = '''\n\nFAILURE: Build failed with an exception.\n\n* What went wrong:\nTask '{}' is ambiguous in root project 'org.rerenderer_example.snake'. Candidates are: 'assembleRelease', 'assembleReleaseUnitTest'.\n\n* Try:\nRun gradlew tasks to get a list of available tasks. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.\n'''.format\n\n\n@pytest.fixture(autouse=True)\ndef tasks(mocker):\n    patch = mocker.patch('thefuck.rules.gradle_no_task.Popen')\n    patch.return_value.stdout = BytesIO(gradle_tasks)\n    return patch\n\n\n@pytest.mark.parametrize('command', [\n    Command('./gradlew assembler', output_ambiguous('assembler')),\n    Command('./gradlew instar', output_not_found('instar')),\n    Command('gradle assembler', output_ambiguous('assembler')),\n    Command('gradle instar', output_not_found('instar'))])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('./gradlew assemble', ''),\n    Command('gradle assemble', ''),\n    Command('npm assembler', output_ambiguous('assembler')),\n    Command('npm instar', output_not_found('instar'))])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, result', [\n    (Command('./gradlew assembler', output_ambiguous('assembler')),\n     './gradlew assemble'),\n    (Command('./gradlew instardebug', output_not_found('instardebug')),\n     './gradlew installDebug'),\n    (Command('gradle assembler', output_ambiguous('assembler')),\n     'gradle assemble'),\n    (Command('gradle instardebug', output_not_found('instardebug')),\n     'gradle installDebug')])\ndef test_get_new_command(command, result):\n    assert get_new_command(command)[0] == result\n"
  },
  {
    "path": "tests/rules/test_gradle_wrapper.py",
    "content": "import pytest\nfrom thefuck.rules.gradle_wrapper import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture(autouse=True)\ndef exists(mocker):\n    return mocker.patch('thefuck.rules.gradle_wrapper.os.path.isfile',\n                        return_value=True)\n\n\n@pytest.mark.parametrize('command', [\n    Command('gradle tasks', 'gradle: not found'),\n    Command('gradle build', 'gradle: not found')])\ndef test_match(mocker, command):\n    mocker.patch('thefuck.rules.gradle_wrapper.which', return_value=None)\n\n    assert match(command)\n\n\n@pytest.mark.parametrize('command, gradlew, which', [\n    (Command('gradle tasks', 'gradle: not found'), False, None),\n    (Command('gradle tasks', 'command not found'), True, '/usr/bin/gradle'),\n    (Command('npm tasks', 'npm: not found'), True, None)])\ndef test_not_match(mocker, exists, command, gradlew, which):\n    mocker.patch('thefuck.rules.gradle_wrapper.which', return_value=which)\n    exists.return_value = gradlew\n\n    assert not match(command)\n\n\n@pytest.mark.parametrize('script, result', [\n    ('gradle assemble', './gradlew assemble'),\n    ('gradle --help', './gradlew --help'),\n    ('gradle build -c', './gradlew build -c')])\ndef test_get_new_command(script, result):\n    command = Command(script, '')\n    assert get_new_command(command) == result\n"
  },
  {
    "path": "tests/rules/test_grep_arguments_order.py",
    "content": "import pytest\nfrom thefuck.rules.grep_arguments_order import get_new_command, match\nfrom thefuck.types import Command\n\noutput = 'grep: {}: No such file or directory'.format\n\n\n@pytest.fixture(autouse=True)\ndef os_path(monkeypatch):\n    monkeypatch.setattr('os.path.isfile', lambda x: not x.startswith('-'))\n\n\n@pytest.mark.parametrize('script, file', [\n    ('grep test.py test', 'test'),\n    ('grep -lir . test', 'test'),\n    ('egrep test.py test', 'test'),\n    ('egrep -lir . test', 'test')])\ndef test_match(script, file):\n    assert match(Command(script, output(file)))\n\n\n@pytest.mark.parametrize('script, output', [\n    ('cat test.py', output('test')),\n    ('grep test test.py', ''),\n    ('grep -lir test .', ''),\n    ('egrep test test.py', ''),\n    ('egrep -lir test .', '')])\ndef test_not_match(script, output):\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output, result', [\n    ('grep test.py test', output('test'), 'grep test test.py'),\n    ('grep -lir . test', output('test'), 'grep -lir test .'),\n    ('grep . test -lir', output('test'), 'grep test -lir .'),\n    ('egrep test.py test', output('test'), 'egrep test test.py'),\n    ('egrep -lir . test', output('test'), 'egrep -lir test .'),\n    ('egrep . test -lir', output('test'), 'egrep test -lir .')])\ndef test_get_new_command(script, output, result):\n    assert get_new_command(Command(script, output)) == result\n"
  },
  {
    "path": "tests/rules/test_grep_recursive.py",
    "content": "# -*- coding: utf-8 -*-\n\nfrom thefuck.rules.grep_recursive import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef test_match():\n    assert match(Command('grep blah .', 'grep: .: Is a directory'))\n    assert match(Command(u'grep café .', 'grep: .: Is a directory'))\n    assert not match(Command('', ''))\n\n\ndef test_get_new_command():\n    assert get_new_command(Command('grep blah .', '')) == 'grep -r blah .'\n    assert get_new_command(Command(u'grep café .', '')) == u'grep -r café .'\n"
  },
  {
    "path": "tests/rules/test_grunt_task_not_found.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom io import BytesIO\nimport pytest\nfrom thefuck.types import Command\nfrom thefuck.rules.grunt_task_not_found import match, get_new_command\n\noutput = '''\nWarning: Task \"{}\" not found. Use --force to continue.\n\nAborted due to warnings.\n\n\nExecution Time (2016-08-13 21:01:40 UTC+3)\nloading tasks  11ms  ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 92%\nTotal 12ms\n\n'''.format\n\ngrunt_help_stdout = b'''\nGrunt: The JavaScript Task Runner (v0.4.5)\n\nUsage\n grunt [options] [task [task ...]]\n\nOptions\n    --help, -h  Display this help text.\n        --base  Specify an alternate base path. By default, all file paths are\n                relative to the Gruntfile. (grunt.file.setBase) *\n    --no-color  Disable colored output.\n   --gruntfile  Specify an alternate Gruntfile. By default, grunt looks in the\n                current or parent directories for the nearest Gruntfile.js or\n                Gruntfile.coffee file.\n   --debug, -d  Enable debugging mode for tasks that support it.\n       --stack  Print a stack trace when exiting with a warning or fatal error.\n   --force, -f  A way to force your way past warnings. Want a suggestion? Don't\n                use this option, fix your code.\n       --tasks  Additional directory paths to scan for task and \"extra\" files.\n                (grunt.loadTasks) *\n         --npm  Npm-installed grunt plugins to scan for task and \"extra\" files.\n                (grunt.loadNpmTasks) *\n    --no-write  Disable writing files (dry run).\n --verbose, -v  Verbose mode. A lot more information output.\n --version, -V  Print the grunt version. Combine with --verbose for more info.\n  --completion  Output shell auto-completion rules. See the grunt-cli\n                documentation for more information.\n\nOptions marked with * have methods exposed via the grunt API and should instead\nbe specified inside the Gruntfile wherever possible.\n\nAvailable tasks\n  autoprefixer  Prefix CSS files. *\n    concurrent  Run grunt tasks concurrently *\n         clean  Clean files and folders. *\n       compass  Compile Sass to CSS using Compass *\n        concat  Concatenate files. *\n       connect  Start a connect web server. *\n          copy  Copy files. *\n        cssmin  Minify CSS *\n       htmlmin  Minify HTML *\n      imagemin  Minify PNG, JPEG, GIF and SVG images *\n        jshint  Validate files with JSHint. *\n        uglify  Minify files with UglifyJS. *\n         watch  Run predefined tasks whenever watched files change.\n       filerev  File revisioning based on content hashing *\n        cdnify  Replace scripts with refs to the Google CDN *\n         karma  run karma. *\n         newer  Run a task with only those source files that have been modified\n                since the last successful run.\n     any-newer  DEPRECATED TASK.  Use the \"newer\" task instead\n newer-postrun  Internal task.\n   newer-clean  Remove cached timestamps.\n    ngAnnotate  Add, remove and rebuild AngularJS dependency injection\n                annotations *\n    ngconstant  Dynamic angular constant generator task. *\n        svgmin  Minify SVG *\n        usemin  Replaces references to non-minified scripts / stylesheets *\n useminPrepare  Using HTML markup as the primary source of information *\n       wiredep  Inject Bower components into your source code. *\n         serve  Compile then start a connect web server\n        server  DEPRECATED TASK. Use the \"serve\" task instead\n          test  Alias for \"clean:server\", \"ngconstant:test\", \"wiredep\",\n                \"concurrent:test\", \"autoprefixer\", \"connect:test\", \"karma\"\n                tasks.\n         build  Alias for \"ngconstant:production\", \"clean:dist\", \"wiredep\",\n                \"useminPrepare\", \"concurrent:dist\", \"autoprefixer\", \"concat\",\n                \"ngAnnotate\", \"copy:dist\", \"cdnify\", \"cssmin\", \"uglify\",\n                \"filerev\", \"usemin\", \"htmlmin\" tasks.\n       default  Alias for \"newer:jshint\", \"test\", \"build\" tasks.\n\nTasks run in the order specified. Arguments may be passed to tasks that accept\nthem by using colons, like \"lint:files\". Tasks marked with * are \"multi tasks\"\nand will iterate over all sub-targets if no argument is specified.\n\nThe list of available tasks may change based on tasks directories or grunt\nplugins specified in the Gruntfile or via command-line options.\n\nFor more information, see http://gruntjs.com/\n'''\n\n\n@pytest.fixture(autouse=True)\ndef grunt_help(mocker):\n    patch = mocker.patch('thefuck.rules.grunt_task_not_found.Popen')\n    patch.return_value.stdout = BytesIO(grunt_help_stdout)\n    return patch\n\n\n@pytest.mark.parametrize('command', [\n    Command('grunt defualt', output('defualt')),\n    Command('grunt buld:css', output('buld:css'))])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('npm nuild', output('nuild')),\n    Command('grunt rm', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, result', [\n    (Command('grunt defualt', output('defualt')), 'grunt default'),\n    (Command('grunt cmpass:all', output('cmpass:all')), 'grunt compass:all'),\n    (Command('grunt cmpass:all --color', output('cmpass:all')),\n     'grunt compass:all --color')])\ndef test_get_new_command(command, result):\n    assert get_new_command(command) == result\n"
  },
  {
    "path": "tests/rules/test_gulp_not_task.py",
    "content": "import pytest\nfrom io import BytesIO\nfrom thefuck.types import Command\nfrom thefuck.rules.gulp_not_task import match, get_new_command\n\n\ndef output(task):\n    return '''[00:41:11] Using gulpfile gulpfile.js\n[00:41:11] Task '{}' is not in your gulpfile\n[00:41:11] Please check the documentation for proper gulpfile formatting\n'''.format(task)\n\n\ndef test_match():\n    assert match(Command('gulp srve', output('srve')))\n\n\n@pytest.mark.parametrize('script, stdout', [\n    ('gulp serve', ''),\n    ('cat srve', output('srve'))])\ndef test_not_march(script, stdout):\n    assert not match(Command(script, stdout))\n\n\ndef test_get_new_command(mocker):\n    mock = mocker.patch('subprocess.Popen')\n    mock.return_value.stdout = BytesIO(b'serve \\nbuild \\ndefault \\n')\n    command = Command('gulp srve', output('srve'))\n    assert get_new_command(command) == ['gulp serve', 'gulp default']\n"
  },
  {
    "path": "tests/rules/test_has_exists_script.py",
    "content": "from mock import patch\nfrom thefuck.rules.has_exists_script import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef test_match():\n    with patch('os.path.exists', return_value=True):\n        assert match(Command('main', 'main: command not found'))\n        assert match(Command('main --help',\n                             'main: command not found'))\n        assert not match(Command('main', ''))\n\n    with patch('os.path.exists', return_value=False):\n        assert not match(Command('main', 'main: command not found'))\n\n\ndef test_get_new_command():\n    assert get_new_command(Command('main --help', '')) == './main --help'\n"
  },
  {
    "path": "tests/rules/test_heroku_multiple_apps.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport pytest\nfrom thefuck.types import Command\nfrom thefuck.rules.heroku_multiple_apps import match, get_new_command\n\n\nsuggest_output = '''\n ▸    Multiple apps in git remotes\n ▸    Usage: --remote heroku-dev\n ▸    or: --app myapp-dev\n ▸    Your local git repository has more than 1 app referenced in git remotes.\n ▸    Because of this, we can't determine which app you want to run this command against.\n ▸    Specify the app you want with --app or --remote.\n ▸    Heroku remotes in repo:\n ▸    myapp (heroku)\n ▸    myapp-dev (heroku-dev)\n ▸\n ▸    https://devcenter.heroku.com/articles/multiple-environments\n'''\n\nnot_match_output = '''\n=== HEROKU_POSTGRESQL_TEAL_URL, DATABASE_URL\nPlan:                  Hobby-basic\nStatus:                Available\nConnections:           20/20\nPG Version:            9.6.4\nCreated:               2017-01-01 00:00 UTC\nData Size:             99.9 MB\nTables:                99\nRows:                  12345/10000000 (In compliance)\nFork/Follow:           Unsupported\nRollback:              Unsupported\nContinuous Protection: Off\nAdd-on:                postgresql-round-12345\n'''\n\n\n@pytest.mark.parametrize('cmd', ['pg'])\ndef test_match(cmd):\n    assert match(\n        Command('heroku {}'.format(cmd), suggest_output))\n\n\n@pytest.mark.parametrize('script, output', [\n    ('heroku pg', not_match_output)])\ndef test_not_match(script, output):\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize('cmd, result', [\n    ('pg', ['heroku pg --app myapp', 'heroku pg --app myapp-dev'])])\ndef test_get_new_command(cmd, result):\n    command = Command('heroku {}'.format(cmd), suggest_output)\n    assert get_new_command(command) == result\n"
  },
  {
    "path": "tests/rules/test_heroku_not_command.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport pytest\nfrom thefuck.types import Command\nfrom thefuck.rules.heroku_not_command import match, get_new_command\n\n\nsuggest_output = '''\n ▸    log is not a heroku command.\n ▸    Perhaps you meant logs?\n ▸    Run heroku _ to run heroku logs.\n ▸    Run heroku help for a list of available commands.'''\n\n\n@pytest.mark.parametrize('cmd', ['log'])\ndef test_match(cmd):\n    assert match(\n        Command('heroku {}'.format(cmd), suggest_output))\n\n\n@pytest.mark.parametrize('script, output', [\n    ('cat log', suggest_output)])\ndef test_not_match(script, output):\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize('cmd, result', [\n    ('log', 'heroku logs')])\ndef test_get_new_command(cmd, result):\n    command = Command('heroku {}'.format(cmd), suggest_output)\n    assert get_new_command(command) == result\n"
  },
  {
    "path": "tests/rules/test_history.py",
    "content": "import pytest\nfrom thefuck.rules.history import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture(autouse=True)\ndef history_without_current(mocker):\n    return mocker.patch(\n        'thefuck.rules.history.get_valid_history_without_current',\n        return_value=['ls cat', 'diff x'])\n\n\n@pytest.mark.parametrize('script', ['ls cet', 'daff x'])\ndef test_match(script):\n    assert match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script', ['apt-get', 'nocommand y'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script, result', [\n    ('ls cet', 'ls cat'),\n    ('daff x', 'diff x')])\ndef test_get_new_command(script, result):\n    assert get_new_command(Command(script, '')) == result\n"
  },
  {
    "path": "tests/rules/test_hostscli.py",
    "content": "import pytest\nfrom thefuck.rules.hostscli import no_website, get_new_command, match\nfrom thefuck.types import Command\n\nno_website_long = '''\n{}:\n\nNo Domain list found for website: a_website_that_does_not_exist\n\nPlease raise a Issue here: https://github.com/dhilipsiva/hostscli/issues/new\nif you think we should add domains for this website.\n\ntype `hostscli websites` to see a list of websites that you can block/unblock\n'''.format(no_website)\n\n\n@pytest.mark.parametrize('command', [\n    Command('hostscli block a_website_that_does_not_exist', no_website_long)])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command, result', [(\n    Command('hostscli block a_website_that_does_not_exist', no_website_long),\n    ['hostscli websites'])])\ndef test_get_new_command(command, result):\n    assert get_new_command(command) == result\n"
  },
  {
    "path": "tests/rules/test_ifconfig_device_not_found.py",
    "content": "import pytest\nfrom six import BytesIO\nfrom thefuck.rules.ifconfig_device_not_found import match, get_new_command\nfrom thefuck.types import Command\n\n\noutput = '{}: error fetching interface information: Device not found'\n\nstdout = b'''\nwlp2s0    Link encap:Ethernet  HWaddr 5c:51:4f:7c:58:5d\n          inet addr:192.168.0.103  Bcast:192.168.0.255  Mask:255.255.255.0\n          inet6 addr: fe80::be23:69b9:96d2:6d39/64 Scope:Link\n          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1\n          RX packets:23581604 errors:0 dropped:0 overruns:0 frame:0\n          TX packets:17017655 errors:0 dropped:0 overruns:0 carrier:0\n          collisions:0 txqueuelen:1000\n          RX bytes:16148429061 (16.1 GB)  TX bytes:7067533695 (7.0 GB)\n'''\n\n\n@pytest.fixture(autouse=True)\ndef ifconfig(mocker):\n    mock = mocker.patch(\n        'thefuck.rules.ifconfig_device_not_found.subprocess.Popen')\n    mock.return_value.stdout = BytesIO(stdout)\n    return mock\n\n\n@pytest.mark.parametrize('script, output', [\n    ('ifconfig wlan0', output.format('wlan0')),\n    ('ifconfig -s eth0', output.format('eth0')),\n])\ndef test_match(script, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output', [\n    ('config wlan0',\n     'wlan0: error fetching interface information: Device not found'),\n    ('ifconfig eth0', ''),\n])\ndef test_not_match(script, output):\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, result', [\n    ('ifconfig wlan0', ['ifconfig wlp2s0']),\n    ('ifconfig -s wlan0', ['ifconfig -s wlp2s0']),\n])\ndef test_get_new_comman(script, result):\n    new_command = get_new_command(\n        Command(script, output.format('wlan0')))\n    assert new_command == result\n"
  },
  {
    "path": "tests/rules/test_java.py",
    "content": "import pytest\nfrom thefuck.rules.java import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('java foo.java', ''),\n    Command('java bar.java', '')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('java foo.java', ''), 'java foo'),\n    (Command('java bar.java', ''), 'java bar')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_javac.py",
    "content": "import pytest\nfrom thefuck.rules.javac import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('javac foo', ''),\n    Command('javac bar', '')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('javac foo', ''), 'javac foo.java'),\n    (Command('javac bar', ''), 'javac bar.java')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_lein_not_task.py",
    "content": "import pytest\nfrom thefuck.rules.lein_not_task import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef is_not_task():\n    return ''''rpl' is not a task. See 'lein help'.\n\nDid you mean this?\n         repl\n         jar\n'''\n\n\ndef test_match(is_not_task):\n    assert match(Command('lein rpl', is_not_task))\n    assert not match(Command('ls', is_not_task))\n\n\ndef test_get_new_command(is_not_task):\n    assert (get_new_command(Command('lein rpl --help', is_not_task))\n            == ['lein repl --help', 'lein jar --help'])\n"
  },
  {
    "path": "tests/rules/test_ln_no_hard_link.py",
    "content": "# -*- coding: utf-8 -*-\nimport pytest\nfrom thefuck.rules.ln_no_hard_link import match, get_new_command\nfrom thefuck.types import Command\n\nerror = \"hard link not allowed for directory\"\n\n\n@pytest.mark.parametrize('script, output', [\n    (\"ln barDir barLink\", \"ln: ‘barDir’: {}\"),\n    (\"sudo ln a b\", \"ln: ‘a’: {}\"),\n    (\"sudo ln -nbi a b\", \"ln: ‘a’: {}\")])\ndef test_match(script, output):\n    command = Command(script, output.format(error))\n    assert match(command)\n\n\n@pytest.mark.parametrize('script, output', [\n    ('', ''),\n    (\"ln a b\", \"... hard link\"),\n    (\"sudo ln a b\", \"... hard link\"),\n    (\"a b\", error)])\ndef test_not_match(script, output):\n    command = Command(script, output)\n    assert not match(command)\n\n\n@pytest.mark.parametrize('script, result', [\n    (\"ln barDir barLink\", \"ln -s barDir barLink\"),\n    (\"sudo ln barDir barLink\", \"sudo ln -s barDir barLink\"),\n    (\"sudo ln -nbi a b\", \"sudo ln -s -nbi a b\"),\n    (\"ln -nbi a b && ls\", \"ln -s -nbi a b && ls\"),\n    (\"ln a ln\", \"ln -s a ln\"),\n    (\"sudo ln a ln\", \"sudo ln -s a ln\")])\ndef test_get_new_command(script, result):\n    command = Command(script, '')\n    assert get_new_command(command) == result\n"
  },
  {
    "path": "tests/rules/test_ln_s_order.py",
    "content": "import pytest\nfrom thefuck.rules.ln_s_order import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef file_exists(mocker):\n    return mocker.patch('os.path.exists', return_value=True)\n\n\nget_output = \"ln: failed to create symbolic link '{}': File exists\".format\n\n\n@pytest.mark.parametrize('script, output, exists', [\n    ('ln dest source', get_output('source'), True),\n    ('ls -s dest source', get_output('source'), True),\n    ('ln -s dest source', '', True),\n    ('ln -s dest source', get_output('source'), False)])\ndef test_not_match(file_exists, script, output, exists):\n    file_exists.return_value = exists\n    assert not match(Command(script, output))\n\n\n@pytest.mark.usefixtures('file_exists')\n@pytest.mark.parametrize('script, result', [\n    ('ln -s dest source', 'ln -s source dest'),\n    ('ln dest -s source', 'ln -s source dest'),\n    ('ln dest source -s', 'ln source -s dest')])\ndef test_match(script, result):\n    output = get_output('source')\n    assert match(Command(script, output))\n    assert get_new_command(Command(script, output)) == result\n"
  },
  {
    "path": "tests/rules/test_long_form_help.py",
    "content": "import pytest\nfrom thefuck.rules.long_form_help import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('output', [\n    'Try \\'grep --help\\' for more information.'])\ndef test_match(output):\n    assert match(Command('grep -h', output))\n\n\ndef test_not_match():\n    assert not match(Command('', ''))\n\n\n@pytest.mark.parametrize('before, after', [\n    ('grep -h', 'grep --help'),\n    ('tar -h', 'tar --help'),\n    ('docker run -h', 'docker run --help'),\n    ('cut -h', 'cut --help')])\ndef test_get_new_command(before, after):\n    assert get_new_command(Command(before, '')) == after\n"
  },
  {
    "path": "tests/rules/test_ls_all.py",
    "content": "from thefuck.rules.ls_all import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef test_match():\n    assert match(Command('ls', ''))\n    assert not match(Command('ls', 'file.py\\n'))\n\n\ndef test_get_new_command():\n    assert get_new_command(Command('ls empty_dir', '')) == 'ls -A empty_dir'\n    assert get_new_command(Command('ls', '')) == 'ls -A'\n"
  },
  {
    "path": "tests/rules/test_ls_lah.py",
    "content": "from thefuck.rules.ls_lah import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef test_match():\n    assert match(Command('ls', ''))\n    assert match(Command('ls file.py', ''))\n    assert match(Command('ls /opt', ''))\n    assert not match(Command('ls -lah /opt', ''))\n    assert not match(Command('pacman -S binutils', ''))\n    assert not match(Command('lsof', ''))\n\n\ndef test_get_new_command():\n    assert get_new_command(Command('ls file.py', '')) == 'ls -lah file.py'\n    assert get_new_command(Command('ls', '')) == 'ls -lah'\n"
  },
  {
    "path": "tests/rules/test_man.py",
    "content": "import pytest\nfrom thefuck.rules.man import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('man read', ''),\n    Command('man 2 read', ''),\n    Command('man 3 read', ''),\n    Command('man -s2 read', ''),\n    Command('man -s3 read', ''),\n    Command('man -s 2 read', ''),\n    Command('man -s 3 read', '')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('man', ''),\n    Command('man ', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('man read', ''), ['man 3 read', 'man 2 read', 'read --help']),\n    (Command('man missing', \"No manual entry for missing\\n\"), ['missing --help']),\n    (Command('man 2 read', ''), 'man 3 read'),\n    (Command('man 3 read', ''), 'man 2 read'),\n    (Command('man -s2 read', ''), 'man -s3 read'),\n    (Command('man -s3 read', ''), 'man -s2 read'),\n    (Command('man -s 2 read', ''), 'man -s 3 read'),\n    (Command('man -s 3 read', ''), 'man -s 2 read')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_man_no_space.py",
    "content": "from thefuck.rules.man_no_space import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef test_match():\n    assert match(Command('mandiff', 'mandiff: command not found'))\n    assert not match(Command('', ''))\n\n\ndef test_get_new_command():\n    assert get_new_command(Command('mandiff', '')) == 'man diff'\n"
  },
  {
    "path": "tests/rules/test_mercurial.py",
    "content": "import pytest\n\nfrom thefuck.types import Command\nfrom thefuck.rules.mercurial import (\n    extract_possibilities, match, get_new_command\n)\n\n\n@pytest.mark.parametrize('command', [\n    Command('hg base', (\n        \"hg: unknown command 'base'\"\n        '\\n(did you mean one of blame, phase, rebase?)'\n    )),\n    Command('hg branchch', (\n        \"hg: unknown command 'branchch'\"\n        '\\n(did you mean one of branch, branches?)'\n    )),\n    Command('hg vert', (\n        \"hg: unknown command 'vert'\"\n        '\\n(did you mean one of revert?)'\n    )),\n    Command('hg lgo -r tip', (\n        \"hg: command 're' is ambiguous:\"\n        '\\n(did you mean one of log?)'\n    )),\n    Command('hg rerere', (\n        \"hg: unknown command 'rerere'\"\n        '\\n(did you mean one of revert?)'\n    )),\n    Command('hg re', (\n        \"hg: command 're' is ambiguous:\"\n        '\\n    rebase recover remove rename resolve revert'\n    )),\n    Command('hg re re', (\n        \"hg: command 're' is ambiguous:\"\n        '\\n    rebase recover remove rename resolve revert'\n    )),\n])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('hg', (\n        '\\nMercurial Distributed SCM\\n\\nbasic commands:'\n    )),\n    Command('hg asdf', (\n        \"hg: unknown command 'asdf'\"\n        '\\nMercurial Distributed SCM\\n\\nbasic commands:'\n    )),\n    Command('hg qwer', (\n        \"hg: unknown command 'qwer'\"\n        '\\nMercurial Distributed SCM\\n\\nbasic commands:'\n    )),\n    Command('hg me', (\n        \"\\nabort: no repository found in './thefuck' (.hg not found)!\"\n    )),\n    Command('hg reb', (\n        \"\\nabort: no repository found in './thefuck' (.hg not found)!\"\n    )),\n    Command('hg co', (\n        \"\\nabort: no repository found in './thefuck' (.hg not found)!\"\n    )),\n])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, possibilities', [\n    (Command('hg base', (\n        \"hg: unknown command 'base'\"\n        '\\n(did you mean one of blame, phase, rebase?)'\n    )), ['blame', 'phase', 'rebase']),\n    (Command('hg branchch', (\n        \"hg: unknown command 'branchch'\"\n        '\\n(did you mean one of branch, branches?)'\n    )), ['branch', 'branches']),\n    (Command('hg vert', (\n        \"hg: unknown command 'vert'\"\n        '\\n(did you mean one of revert?)'\n    )), ['revert']),\n    (Command('hg lgo -r tip', (\n        \"hg: command 're' is ambiguous:\"\n        '\\n(did you mean one of log?)'\n    )), ['log']),\n    (Command('hg rerere', (\n        \"hg: unknown command 'rerere'\"\n        '\\n(did you mean one of revert?)'\n    )), ['revert']),\n    (Command('hg re', (\n        \"hg: command 're' is ambiguous:\"\n        '\\n    rebase recover remove rename resolve revert'\n    )), ['rebase', 'recover', 'remove', 'rename', 'resolve', 'revert']),\n    (Command('hg re re', (\n        \"hg: command 're' is ambiguous:\"\n        '\\n    rebase recover remove rename resolve revert'\n    )), ['rebase', 'recover', 'remove', 'rename', 'resolve', 'revert']),\n])\ndef test_extract_possibilities(command, possibilities):\n    assert extract_possibilities(command) == possibilities\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('hg base', (\n        \"hg: unknown command 'base'\"\n        '\\n(did you mean one of blame, phase, rebase?)'\n    )), 'hg rebase'),\n    (Command('hg branchch', (\n        \"hg: unknown command 'branchch'\"\n        '\\n(did you mean one of branch, branches?)'\n    )), 'hg branch'),\n    (Command('hg vert', (\n        \"hg: unknown command 'vert'\"\n        '\\n(did you mean one of revert?)'\n    )), 'hg revert'),\n    (Command('hg lgo -r tip', (\n        \"hg: command 're' is ambiguous:\"\n        '\\n(did you mean one of log?)'\n    )), 'hg log -r tip'),\n    (Command('hg rerere', (\n        \"hg: unknown command 'rerere'\"\n        '\\n(did you mean one of revert?)'\n    )), 'hg revert'),\n    (Command('hg re', (\n        \"hg: command 're' is ambiguous:\"\n        '\\n    rebase recover remove rename resolve revert'\n    )), 'hg rebase'),\n    (Command('hg re re', (\n        \"hg: command 're' is ambiguous:\"\n        '\\n    rebase recover remove rename resolve revert'\n    )), 'hg rebase re'),\n])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_missing_space_before_subcommand.py",
    "content": "import pytest\nfrom thefuck.rules.missing_space_before_subcommand import (\n    match, get_new_command)\nfrom thefuck.types import Command\n\n\n@pytest.fixture(autouse=True)\ndef all_executables(mocker):\n    return mocker.patch(\n        'thefuck.rules.missing_space_before_subcommand.get_all_executables',\n        return_value=['git', 'ls', 'npm', 'w', 'watch'])\n\n\n@pytest.mark.parametrize('script', [\n    'gitbranch', 'ls-la', 'npminstall', 'watchls'])\ndef test_match(script):\n    assert match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script', ['git branch', 'vimfile'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script, result', [\n    ('gitbranch', 'git branch'),\n    ('ls-la', 'ls -la'),\n    ('npminstall webpack', 'npm install webpack'),\n    ('watchls', 'watch ls')])\ndef test_get_new_command(script, result):\n    assert get_new_command(Command(script, '')) == result\n"
  },
  {
    "path": "tests/rules/test_mkdir_p.py",
    "content": "import pytest\nfrom thefuck.rules.mkdir_p import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('mkdir foo/bar/baz', 'mkdir: foo/bar: No such file or directory'),\n    Command('./bin/hdfs dfs -mkdir foo/bar/baz', 'mkdir: `foo/bar/baz\\': No such file or directory'),\n    Command('hdfs dfs -mkdir foo/bar/baz', 'mkdir: `foo/bar/baz\\': No such file or directory')\n])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('mkdir foo/bar/baz', ''),\n    Command('mkdir foo/bar/baz', 'foo bar baz'),\n    Command('hdfs dfs -mkdir foo/bar/baz', ''),\n    Command('./bin/hdfs dfs -mkdir foo/bar/baz', ''),\n    Command('', ''),\n])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('mkdir foo/bar/baz', ''), 'mkdir -p foo/bar/baz'),\n    (Command('hdfs dfs -mkdir foo/bar/baz', ''), 'hdfs dfs -mkdir -p foo/bar/baz'),\n    (Command('./bin/hdfs dfs -mkdir foo/bar/baz', ''), './bin/hdfs dfs -mkdir -p foo/bar/baz'),\n])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_mvn_no_command.py",
    "content": "import pytest\nfrom thefuck.rules.mvn_no_command import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('mvn', '[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('mvn clean', \"\"\"\n[INFO] Scanning for projects...[INFO]                                                                         \n[INFO] ------------------------------------------------------------------------\n[INFO] Building test 0.2\n[INFO] ------------------------------------------------------------------------\n[INFO] \n[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ test ---\n[INFO] Deleting /home/mlk/code/test/target\n[INFO] ------------------------------------------------------------------------\n[INFO] BUILD SUCCESS\n[INFO] ------------------------------------------------------------------------\n[INFO] Total time: 0.477s\n[INFO] Finished at: Wed Aug 26 13:05:47 BST 2015\n[INFO] Final Memory: 6M/240M\n[INFO] ------------------------------------------------------------------------\n\"\"\"),  # noqa\n    Command('mvn --help', ''),\n    Command('mvn -v', '')\n])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('mvn', '[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn clean package', 'mvn clean install']),\n    (Command('mvn -N', '[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn -N clean package', 'mvn -N clean install'])])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_mvn_unknown_lifecycle_phase.py",
    "content": "import pytest\nfrom thefuck.rules.mvn_unknown_lifecycle_phase import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('mvn cle', '[ERROR] Unknown lifecycle phase \"cle\". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('mvn clean', \"\"\"\n[INFO] Scanning for projects...[INFO]                                                                         \n[INFO] ------------------------------------------------------------------------\n[INFO] Building test 0.2\n[INFO] ------------------------------------------------------------------------\n[INFO] \n[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ test ---\n[INFO] Deleting /home/mlk/code/test/target\n[INFO] ------------------------------------------------------------------------\n[INFO] BUILD SUCCESS\n[INFO] ------------------------------------------------------------------------\n[INFO] Total time: 0.477s\n[INFO] Finished at: Wed Aug 26 13:05:47 BST 2015\n[INFO] Final Memory: 6M/240M\n[INFO] ------------------------------------------------------------------------\n\"\"\"),  # noqa\n    Command('mvn --help', ''),\n    Command('mvn -v', '')\n])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('mvn cle', '[ERROR] Unknown lifecycle phase \"cle\". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn clean', 'mvn compile']),\n    (Command('mvn claen package', '[ERROR] Unknown lifecycle phase \"claen\". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-clean, clean, post-clean, pre-site, site, post-site, site-deploy. -> [Help 1]'), ['mvn clean package'])])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_nixos_cmd_not_found.py",
    "content": "import pytest\nfrom thefuck.rules.nixos_cmd_not_found import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('vim', 'nix-env -iA nixos.vim')])\ndef test_match(mocker, command):\n    mocker.patch('thefuck.rules.nixos_cmd_not_found', return_value=None)\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('vim', ''),\n    Command('', '')])\ndef test_not_match(mocker, command):\n    mocker.patch('thefuck.rules.nixos_cmd_not_found', return_value=None)\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('vim', 'nix-env -iA nixos.vim'), 'nix-env -iA nixos.vim && vim'),\n    (Command('pacman', 'nix-env -iA nixos.pacman'), 'nix-env -iA nixos.pacman && pacman')])\ndef test_get_new_command(mocker, command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_no_command.py",
    "content": "import pytest\nfrom thefuck.rules.no_command import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture(autouse=True)\ndef get_all_executables(mocker):\n    mocker.patch('thefuck.rules.no_command.get_all_executables',\n                 return_value=['vim', 'fsck', 'git', 'go', 'python'])\n\n\n@pytest.fixture(autouse=True)\ndef history_without_current(mocker):\n    return mocker.patch(\n        'thefuck.rules.no_command.get_valid_history_without_current',\n        return_value=['git commit'])\n\n\n@pytest.mark.usefixtures('no_memoize')\n@pytest.mark.parametrize('script, output', [\n    ('vom file.py', 'vom: not found'),\n    ('fucck', 'fucck: not found'),\n    ('puthon', \"'puthon' is not recognized as an internal or external command\"),\n    ('got commit', 'got: command not found'),\n    ('gti commit -m \"new commit\"', 'gti: command not found')])\ndef test_match(mocker, script, output):\n    mocker.patch('thefuck.rules.no_command.which', return_value=None)\n\n    assert match(Command(script, output))\n\n\n@pytest.mark.usefixtures('no_memoize')\n@pytest.mark.parametrize('script, output, which', [\n    ('qweqwe', 'qweqwe: not found', None),\n    ('vom file.py', 'some text', None),\n    ('vim file.py', 'vim: not found', 'vim')])\ndef test_not_match(mocker, script, output, which):\n    mocker.patch('thefuck.rules.no_command.which', return_value=which)\n\n    assert not match(Command(script, output))\n\n\n@pytest.mark.usefixtures('no_memoize')\n@pytest.mark.parametrize('script, result', [\n    ('vom file.py', ['vim file.py']),\n    ('fucck', ['fsck']),\n    ('got commit', ['git commit', 'go commit']),\n    ('gti commit -m \"new commit\"', ['git commit -m \"new commit\"'])])\ndef test_get_new_command(script, result):\n    assert get_new_command(Command(script, '')) == result\n"
  },
  {
    "path": "tests/rules/test_no_such_file.py",
    "content": "import pytest\nfrom thefuck.rules.no_such_file import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('mv foo bar/foo', \"mv: cannot move 'foo' to 'bar/foo': No such file or directory\"),\n    Command('mv foo bar/', \"mv: cannot move 'foo' to 'bar/': No such file or directory\"),\n])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('mv foo bar/', \"\"),\n    Command('mv foo bar/foo', \"mv: permission denied\"),\n])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('mv foo bar/foo', \"mv: cannot move 'foo' to 'bar/foo': No such file or directory\"), 'mkdir -p bar && mv foo bar/foo'),\n    (Command('mv foo bar/', \"mv: cannot move 'foo' to 'bar/': No such file or directory\"), 'mkdir -p bar && mv foo bar/'),\n])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_npm_missing_script.py",
    "content": "import pytest\nfrom io import BytesIO\nfrom thefuck.types import Command\nfrom thefuck.rules.npm_missing_script import match, get_new_command\n\noutput = '''\nnpm ERR! Linux 4.4.0-31-generic\nnpm ERR! argv \"/opt/node/bin/node\" \"/opt/node/bin/npm\" \"run\" \"dvelop\"\nnpm ERR! node v4.4.7\nnpm ERR! npm  v2.15.8\n\nnpm ERR! missing script: {}\nnpm ERR!\nnpm ERR! If you need help, you may report this error at:\nnpm ERR!     <https://github.com/npm/npm/issues>\n\nnpm ERR! Please include the following file with any support request:\nnpm ERR!     /home/nvbn/exp/code_view/client_web/npm-debug.log\n'''.format\n\nrun_script_stdout = b'''\nLifecycle scripts included in code-view-web:\n  test\n    jest\n\navailable via `npm run-script`:\n  build\n    cp node_modules/ace-builds/src-min/ -a resources/ace/ && webpack --progress --colors -p --config ./webpack.production.config.js\n  develop\n    cp node_modules/ace-builds/src/ -a resources/ace/ && webpack-dev-server --progress --colors\n  watch-test\n    jest --verbose --watch\n\n'''\n\n\n@pytest.fixture(autouse=True)\ndef run_script(mocker):\n    patch = mocker.patch('thefuck.specific.npm.Popen')\n    patch.return_value.stdout = BytesIO(run_script_stdout)\n    return patch.return_value\n\n\n@pytest.mark.parametrize('command', [\n    Command('npm ru wach', output('wach')),\n    Command('npm run live-tes', output('live-tes')),\n    Command('npm run-script sahare', output('sahare'))])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('npm wach', output('wach')),\n    Command('vim live-tes', output('live-tes')),\n    Command('npm run-script sahare', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('script, output, result', [\n    ('npm ru wach-tests', output('wach-tests'), 'npm ru watch-test'),\n    ('npm -i run-script dvelop', output('dvelop'),\n     'npm -i run-script develop'),\n    ('npm -i run-script buld -X POST', output('buld'),\n     'npm -i run-script build -X POST')])\ndef test_get_new_command(script, output, result):\n    command = Command(script, output)\n\n    assert get_new_command(command)[0] == result\n"
  },
  {
    "path": "tests/rules/test_npm_run_script.py",
    "content": "import pytest\nfrom io import BytesIO\nfrom thefuck.rules.npm_run_script import match, get_new_command\nfrom thefuck.types import Command\n\noutput = '''\nUsage: npm <command>\n\nwhere <command> is one of:\n    access, add-user, adduser, apihelp, author, bin, bugs, c,\n    cache, completion, config, ddp, dedupe, deprecate, dist-tag,\n    dist-tags, docs, edit, explore, faq, find, find-dupes, get,\n    help, help-search, home, i, info, init, install, issues, la,\n    link, list, ll, ln, login, logout, ls, outdated, owner,\n    pack, ping, prefix, prune, publish, r, rb, rebuild, remove,\n    repo, restart, rm, root, run-script, s, se, search, set,\n    show, shrinkwrap, star, stars, start, stop, t, tag, team,\n    test, tst, un, uninstall, unlink, unpublish, unstar, up,\n    update, upgrade, v, version, view, whoami\n\nnpm <cmd> -h     quick help on <cmd>\nnpm -l           display full usage info\nnpm faq          commonly asked questions\nnpm help <term>  search for help on <term>\nnpm help npm     involved overview\n\nSpecify configs in the ini-formatted file:\n    /home/nvbn/.npmrc\nor on the command line via: npm <command> --key value\nConfig info can be viewed via: npm help config\n\n'''\n\nrun_script_stdout = b'''\nLifecycle scripts included in code-view-web:\n  test\n    jest\n\navailable via `npm run-script`:\n  build\n    cp node_modules/ace-builds/src-min/ -a resources/ace/ && webpack --progress --colors -p --config ./webpack.production.config.js\n  develop\n    cp node_modules/ace-builds/src/ -a resources/ace/ && webpack-dev-server --progress --colors\n  watch-test\n    jest --verbose --watch\n\n'''\n\n\n@pytest.fixture(autouse=True)\ndef run_script(mocker):\n    patch = mocker.patch('thefuck.specific.npm.Popen')\n    patch.return_value.stdout = BytesIO(run_script_stdout)\n    return patch.return_value\n\n\n@pytest.mark.usefixtures('no_memoize')\n@pytest.mark.parametrize('script', [\n    'npm watch-test', 'npm develop'])\ndef test_match(script):\n    command = Command(script, output)\n    assert match(command)\n\n\n@pytest.mark.usefixtures('no_memoize')\n@pytest.mark.parametrize('command, run_script_out', [\n    (Command('npm test', 'TEST FAIL'), run_script_stdout),\n    (Command('npm watch-test', 'TEST FAIL'), run_script_stdout),\n    (Command('npm test', output), run_script_stdout),\n    (Command('vim watch-test', output), run_script_stdout)])\ndef test_not_match(run_script, command, run_script_out):\n    run_script.stdout = BytesIO(run_script_out)\n    assert not match(command)\n\n\n@pytest.mark.usefixtures('no_memoize')\n@pytest.mark.parametrize('script, result', [\n    ('npm watch-test', 'npm run-script watch-test'),\n    ('npm -i develop', 'npm run-script -i develop'),\n    ('npm -i watch-script --path ..',\n     'npm run-script -i watch-script --path ..')])\ndef test_get_new_command(script, result):\n    command = Command(script, output)\n    assert get_new_command(command) == result\n"
  },
  {
    "path": "tests/rules/test_npm_wrong_command.py",
    "content": "import pytest\nfrom thefuck.rules.npm_wrong_command import match, get_new_command\nfrom thefuck.types import Command\n\noutput = '''\nUsage: npm <command>\n\nwhere <command> is one of:\n    access, add-user, adduser, apihelp, author, bin, bugs, c,\n    cache, completion, config, ddp, dedupe, deprecate, dist-tag,\n    dist-tags, docs, edit, explore, faq, find, find-dupes, get,\n    help, help-search, home, i, info, init, install, issues, la,\n    link, list, ll, ln, login, logout, ls, outdated, owner,\n    pack, ping, prefix, prune, publish, r, rb, rebuild, remove,\n    repo, restart, rm, root, run-script, s, se, search, set,\n    show, shrinkwrap, star, stars, start, stop, t, tag, team,\n    test, tst, un, uninstall, unlink, unpublish, unstar, up,\n    update, upgrade, v, verison, version, view, whoami\n\nnpm <cmd> -h     quick help on <cmd>\nnpm -l           display full usage info\nnpm faq          commonly asked questions\nnpm help <term>  search for help on <term>\nnpm help npm     involved overview\n\nSpecify configs in the ini-formatted file:\n    /home/nvbn/.npmrc\nor on the command line via: npm <command> --key value\nConfig info can be viewed via: npm help config\n\nnpm@2.14.7 /opt/node/lib/node_modules/npm\n'''\n\n\n@pytest.mark.parametrize('script', [\n    'npm urgrdae',\n    'npm urgrade -g',\n    'npm -f urgrade -g',\n    'npm urg'])\ndef test_match(script):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output', [\n    ('npm urgrade', ''),\n    ('npm', output),\n    ('test urgrade', output),\n    ('npm -e', output)])\ndef test_not_match(script, output):\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, result', [\n    ('npm urgrade', 'npm upgrade'),\n    ('npm -g isntall gulp', 'npm -g install gulp'),\n    ('npm isntall -g gulp', 'npm install -g gulp')])\ndef test_get_new_command(script, result):\n    assert get_new_command(Command(script, output)) == result\n"
  },
  {
    "path": "tests/rules/test_omnienv_no_such_command.py",
    "content": "import pytest\n\nfrom thefuck.rules.omnienv_no_such_command import get_new_command, match\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output(pyenv_cmd):\n    return \"pyenv: no such command `{}'\".format(pyenv_cmd)\n\n\n@pytest.fixture(autouse=True)\ndef Popen(mocker):\n    mock = mocker.patch('thefuck.rules.omnienv_no_such_command.Popen')\n    mock.return_value.stdout.readlines.return_value = (\n        b'--version\\nactivate\\ncommands\\ncompletions\\ndeactivate\\nexec_\\n'\n        b'global\\nhelp\\nhooks\\ninit\\ninstall\\nlocal\\nprefix_\\n'\n        b'realpath.dylib\\nrehash\\nroot\\nshell\\nshims\\nuninstall\\nversion_\\n'\n        b'version-file\\nversion-file-read\\nversion-file-write\\nversion-name_\\n'\n        b'version-origin\\nversions\\nvirtualenv\\nvirtualenv-delete_\\n'\n        b'virtualenv-init\\nvirtualenv-prefix\\nvirtualenvs_\\n'\n        b'virtualenvwrapper\\nvirtualenvwrapper_lazy\\nwhence\\nwhich_\\n'\n    ).split()\n    return mock\n\n\n@pytest.mark.parametrize('script, pyenv_cmd', [\n    ('pyenv globe', 'globe'),\n    ('pyenv intall 3.8.0', 'intall'),\n    ('pyenv list', 'list'),\n])\ndef test_match(script, pyenv_cmd, output):\n    assert match(Command(script, output=output))\n\n\ndef test_match_goenv_output_quote():\n    \"\"\"test goenv's specific output with quotes (')\"\"\"\n    assert match(Command('goenv list', output=\"goenv: no such command 'list'\"))\n\n\n@pytest.mark.parametrize('script, output', [\n    ('pyenv global', 'system'),\n    ('pyenv versions', '  3.7.0\\n  3.7.1\\n* 3.7.2\\n'),\n    ('pyenv install --list', '  3.7.0\\n  3.7.1\\n  3.7.2\\n'),\n])\ndef test_not_match(script, output):\n    assert not match(Command(script, output=output))\n\n\n@pytest.mark.parametrize('script, pyenv_cmd, result', [\n    ('pyenv globe', 'globe', 'pyenv global'),\n    ('pyenv intall 3.8.0', 'intall', 'pyenv install 3.8.0'),\n    ('pyenv list', 'list', 'pyenv install --list'),\n    ('pyenv remove 3.8.0', 'remove', 'pyenv uninstall 3.8.0'),\n])\ndef test_get_new_command(script, pyenv_cmd, output, result):\n    assert result in get_new_command(Command(script, output))\n"
  },
  {
    "path": "tests/rules/test_open.py",
    "content": "import pytest\nfrom thefuck.rules.open import is_arg_url, match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output(script):\n    return 'The file {} does not exist.\\n'.format(script.split(' ', 1)[1])\n\n\n@pytest.mark.parametrize('script', [\n    'open foo.com',\n    'open foo.edu',\n    'open foo.info',\n    'open foo.io',\n    'open foo.ly',\n    'open foo.me',\n    'open foo.net',\n    'open foo.org',\n    'open foo.se',\n    'open www.foo.ru'])\ndef test_is_arg_url(script):\n    assert is_arg_url(Command(script, ''))\n\n\n@pytest.mark.parametrize('script', ['open foo', 'open bar.txt', 'open egg.doc'])\ndef test_not_is_arg_url(script):\n    assert not is_arg_url(Command(script, ''))\n\n\n@pytest.mark.parametrize('script', [\n    'open foo.com',\n    'xdg-open foo.com',\n    'gnome-open foo.com',\n    'kde-open foo.com',\n    'open nonest'])\ndef test_match(script, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, new_command', [\n    ('open foo.io', ['open http://foo.io']),\n    ('xdg-open foo.io', ['xdg-open http://foo.io']),\n    ('gnome-open foo.io', ['gnome-open http://foo.io']),\n    ('kde-open foo.io', ['kde-open http://foo.io']),\n    ('open nonest', ['touch nonest && open nonest',\n                     'mkdir nonest && open nonest'])])\ndef test_get_new_command(script, new_command, output):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_pacman.py",
    "content": "import pytest\nfrom mock import patch\nfrom thefuck.rules import pacman\nfrom thefuck.rules.pacman import match, get_new_command\nfrom thefuck.types import Command\n\n\npacman_cmd = getattr(pacman, 'pacman', 'pacman')\n\nPKGFILE_OUTPUT_SUDO = 'core/sudo 1.8.13-13/usr/bin/sudo'\nPKGFILE_OUTPUT_CONVERT = 'extra/imagemagick 6.9.1.0-1\\t/usr/bin/convert'\n\nPKGFILE_OUTPUT_VIM = '''extra/gvim 7.4.712-1        \\t/usr/bin/vim\nextra/gvim-python3 7.4.712-1\\t/usr/bin/vim\nextra/vim 7.4.712-1         \\t/usr/bin/vim\nextra/vim-minimal 7.4.712-1 \\t/usr/bin/vim\nextra/vim-python3 7.4.712-1 \\t/usr/bin/vim'''\n\n\n@pytest.mark.skipif(not getattr(pacman, 'enabled_by_default', True),\n                    reason='Skip if pacman is not available')\n@pytest.mark.parametrize('command', [\n    Command('vim', 'vim: command not found'),\n    Command('sudo vim', 'sudo: vim: command not found')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command, return_value', [\n    (Command('vim', 'vim: command not found'), PKGFILE_OUTPUT_VIM),\n    (Command('sudo vim', 'sudo: vim: command not found'), PKGFILE_OUTPUT_VIM)])\n@patch('thefuck.specific.archlinux.subprocess')\n@patch.multiple(pacman, create=True, pacman=pacman_cmd)\ndef test_match_mocked(subp_mock, command, return_value):\n    subp_mock.check_output.return_value = return_value\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('vim', ''), Command('', ''),\n    Command('sudo vim', ''), Command('', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\nsudo_vim_possibilities = ['{} -S extra/gvim && sudo vim',\n                          '{} -S extra/gvim-python3 && sudo vim',\n                          '{} -S extra/vim && sudo vim',\n                          '{} -S extra/vim-minimal && sudo vim',\n                          '{} -S extra/vim-python3 && sudo vim']\nsudo_vim_possibilities = [s.format(pacman_cmd) for s in sudo_vim_possibilities]\n\nvim_possibilities = ['{} -S extra/gvim && vim',\n                     '{} -S extra/gvim-python3 && vim',\n                     '{} -S extra/vim && vim',\n                     '{} -S extra/vim-minimal && vim',\n                     '{} -S extra/vim-python3 && vim']\nvim_possibilities = [s.format(pacman_cmd) for s in vim_possibilities]\n\n\n@pytest.mark.skipif(not getattr(pacman, 'enabled_by_default', True),\n                    reason='Skip if pacman is not available')\n@pytest.mark.parametrize('command, new_command', [\n    (Command('vim', ''), vim_possibilities),\n    (Command('sudo vim', ''), sudo_vim_possibilities),\n    (Command('convert', ''), ['{} -S extra/imagemagick && convert'.format(pacman_cmd)]),\n    (Command('sudo convert', ''), ['{} -S extra/imagemagick && sudo convert'.format(pacman_cmd)])])\ndef test_get_new_command(command, new_command, mocker):\n    assert get_new_command(command) == new_command\n\n\n@pytest.mark.parametrize('command, new_command, return_value', [\n    (Command('vim', ''), vim_possibilities, PKGFILE_OUTPUT_VIM),\n    (Command('sudo vim', ''), sudo_vim_possibilities, PKGFILE_OUTPUT_VIM),\n    (Command('convert', ''), ['{} -S extra/imagemagick && convert'.format(pacman_cmd)], PKGFILE_OUTPUT_CONVERT),\n    (Command('sudo', ''), ['{} -S core/sudo && sudo'.format(pacman_cmd)], PKGFILE_OUTPUT_SUDO),\n    (Command('sudo convert', ''), ['{} -S extra/imagemagick && sudo convert'.format(pacman_cmd)], PKGFILE_OUTPUT_CONVERT)])\n@patch('thefuck.specific.archlinux.subprocess')\n@patch.multiple(pacman, create=True, pacman=pacman_cmd)\ndef test_get_new_command_mocked(subp_mock, command, new_command, return_value):\n    subp_mock.check_output.return_value = return_value\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_pacman_invalid_option.py",
    "content": "import pytest\nfrom thefuck.rules.pacman_invalid_option import get_new_command, match\nfrom thefuck.types import Command\n\ngood_output = \"\"\"community/shared_meataxe 1.0-3\n    A set of programs for working with matrix representations over finite fields\n\"\"\"\n\nbad_output = \"error: invalid option '-\"\n\n\n@pytest.mark.parametrize(\"option\", \"SURQFDVT\")\ndef test_not_match_good_output(option):\n    assert not match(Command(\"pacman -{}s meat\".format(option), good_output))\n\n\n@pytest.mark.parametrize(\"option\", \"azxcbnm\")\ndef test_not_match_bad_output(option):\n    assert not match(Command(\"pacman -{}v meat\".format(option), bad_output))\n\n\n@pytest.mark.parametrize(\"option\", \"surqfdvt\")\ndef test_match(option):\n    assert match(Command(\"pacman -{}v meat\".format(option), bad_output))\n\n\n@pytest.mark.parametrize(\"option\", \"surqfdvt\")\ndef test_get_new_command(option):\n    new_command = get_new_command(Command(\"pacman -{}v meat\".format(option), \"\"))\n    assert new_command == \"pacman -{}v meat\".format(option.upper())\n"
  },
  {
    "path": "tests/rules/test_pacman_not_found.py",
    "content": "import pytest\nfrom mock import patch\nfrom thefuck.rules import pacman_not_found\nfrom thefuck.rules.pacman_not_found import match, get_new_command\nfrom thefuck.types import Command\n\nPKGFILE_OUTPUT_LLC = '''extra/llvm 3.6.0-5      /usr/bin/llc\nextra/llvm35 3.5.2-13/usr/bin/llc'''\n\n\n@pytest.mark.skipif(not getattr(pacman_not_found, 'enabled_by_default', True),\n                    reason='Skip if pacman is not available')\n@pytest.mark.parametrize('command', [\n    Command('yay -S llc', 'error: target not found: llc'),\n    Command('pikaur -S llc', 'error: target not found: llc'),\n    Command('yaourt -S llc', 'error: target not found: llc'),\n    Command('pacman llc', 'error: target not found: llc'),\n    Command('sudo pacman llc', 'error: target not found: llc')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('yay -S llc', 'error: target not found: llc'),\n    Command('pikaur -S llc', 'error: target not found: llc'),\n    Command('yaourt -S llc', 'error: target not found: llc'),\n    Command('pacman llc', 'error: target not found: llc'),\n    Command('sudo pacman llc', 'error: target not found: llc')])\n@patch('thefuck.specific.archlinux.subprocess')\ndef test_match_mocked(subp_mock, command):\n    subp_mock.check_output.return_value = PKGFILE_OUTPUT_LLC\n    assert match(command)\n\n\n@pytest.mark.skipif(not getattr(pacman_not_found, 'enabled_by_default', True),\n                    reason='Skip if pacman is not available')\n@pytest.mark.parametrize('command, fixed', [\n    (Command('yay -S llc', 'error: target not found: llc'), ['yay -S extra/llvm', 'yay -S extra/llvm35']),\n    (Command('pikaur -S llc', 'error: target not found: llc'), ['pikaur -S extra/llvm', 'pikaur -S extra/llvm35']),\n    (Command('yaourt -S llc', 'error: target not found: llc'), ['yaourt -S extra/llvm', 'yaourt -S extra/llvm35']),\n    (Command('pacman -S llc', 'error: target not found: llc'), ['pacman -S extra/llvm', 'pacman -S extra/llvm35']),\n    (Command('sudo pacman -S llc', 'error: target not found: llc'), ['sudo pacman -S extra/llvm', 'sudo pacman -S extra/llvm35'])])\ndef test_get_new_command(command, fixed):\n    assert get_new_command(command) == fixed\n\n\n@pytest.mark.parametrize('command, fixed', [\n    (Command('yay -S llc', 'error: target not found: llc'), ['yay -S extra/llvm', 'yay -S extra/llvm35']),\n    (Command('pikaur -S llc', 'error: target not found: llc'), ['pikaur -S extra/llvm', 'pikaur -S extra/llvm35']),\n    (Command('yaourt -S llc', 'error: target not found: llc'), ['yaourt -S extra/llvm', 'yaourt -S extra/llvm35']),\n    (Command('pacman -S llc', 'error: target not found: llc'), ['pacman -S extra/llvm', 'pacman -S extra/llvm35']),\n    (Command('sudo pacman -S llc', 'error: target not found: llc'), ['sudo pacman -S extra/llvm', 'sudo pacman -S extra/llvm35'])])\n@patch('thefuck.specific.archlinux.subprocess')\ndef test_get_new_command_mocked(subp_mock, command, fixed):\n    subp_mock.check_output.return_value = PKGFILE_OUTPUT_LLC\n    assert get_new_command(command) == fixed\n"
  },
  {
    "path": "tests/rules/test_path_from_history.py",
    "content": "import pytest\nfrom thefuck.rules.path_from_history import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture(autouse=True)\ndef history(mocker):\n    return mocker.patch(\n        'thefuck.rules.path_from_history.get_valid_history_without_current',\n        return_value=['cd /opt/java', 'ls ~/work/project/'])\n\n\n@pytest.fixture(autouse=True)\ndef path_exists(mocker):\n    path_mock = mocker.patch('thefuck.rules.path_from_history.Path')\n    exists_mock = path_mock.return_value.expanduser.return_value.exists\n    exists_mock.return_value = True\n    return exists_mock\n\n\n@pytest.mark.parametrize('script, output', [\n    ('ls project', 'no such file or directory: project'),\n    ('cd project', \"can't cd to project\"),\n])\ndef test_match(script, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output', [\n    ('myapp cats', 'no such file or directory: project'),\n    ('cd project', \"\"),\n])\ndef test_not_match(script, output):\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output, result', [\n    ('ls project', 'no such file or directory: project', 'ls ~/work/project'),\n    ('cd java', \"can't cd to java\", 'cd /opt/java'),\n])\ndef test_get_new_command(script, output, result):\n    new_command = get_new_command(Command(script, output))\n    assert new_command[0] == result\n"
  },
  {
    "path": "tests/rules/test_php_s.py",
    "content": "import pytest\nfrom thefuck.rules.php_s import get_new_command, match\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('php -s localhost:8000', ''),\n    Command('php -t pub -s 0.0.0.0:8080', '')\n])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('php -S localhost:8000', ''),\n    Command('vim php -s', '')\n])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('php -s localhost:8000', ''), 'php -S localhost:8000'),\n    (Command('php -t pub -s 0.0.0.0:8080', ''), 'php -t pub -S 0.0.0.0:8080')\n])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_pip_install.py",
    "content": "# -*- coding: UTF-8 -*-\nfrom thefuck.rules.pip_install import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef test_match():\n    response1 = \"\"\"\n    Could not install packages due to an EnvironmentError: [Errno 13] Permission denied: '/Library/Python/2.7/site-packages/entrypoints.pyc'\nConsider using the `--user` option or check the permissions.\n\"\"\"\n    assert match(Command('pip install -r requirements.txt', response1))\n\n    response2 = \"\"\"\nCollecting bacon\n  Downloading https://files.pythonhosted.org/packages/b2/81/19fb79139ee71c8bc4e5a444546f318e2b87253b8939ec8a7e10d63b7341/bacon-0.3.1.zip (11.0MB)\n    100% |████████████████████████████████| 11.0MB 3.0MB/s\nInstalling collected packages: bacon\n  Running setup.py install for bacon ... done\nSuccessfully installed bacon-0.3.1\n\"\"\"\n    assert not match(Command('pip install bacon', response2))\n\n\ndef test_get_new_command():\n    assert get_new_command(Command('pip install -r requirements.txt', '')) == 'pip install --user -r requirements.txt'\n    assert get_new_command(Command('pip install bacon', '')) == 'pip install --user bacon'\n    assert get_new_command(Command('pip install --user -r requirements.txt', '')) == 'sudo pip install -r requirements.txt'\n"
  },
  {
    "path": "tests/rules/test_pip_unknown_command.py",
    "content": "import pytest\nfrom thefuck.rules.pip_unknown_command import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef pip_unknown_cmd_without_recommend():\n    return '''ERROR: unknown command \"i\"'''\n\n\n@pytest.fixture\ndef broken():\n    return 'instatl'\n\n\n@pytest.fixture\ndef suggested():\n    return 'install'\n\n\n@pytest.fixture\ndef pip_unknown_cmd(broken, suggested):\n    return 'ERROR: unknown command \"{}\" - maybe you meant \"{}\"'.format(broken, suggested)\n\n\ndef test_match(pip_unknown_cmd, pip_unknown_cmd_without_recommend):\n    assert match(Command('pip instatl', pip_unknown_cmd))\n    assert not match(Command('pip i',\n                             pip_unknown_cmd_without_recommend))\n\n\n@pytest.mark.parametrize('script, broken, suggested, new_cmd', [\n    ('pip un+install thefuck', 'un+install', 'uninstall', 'pip uninstall thefuck'),\n    ('pip instatl', 'instatl', 'install', 'pip install')])\ndef test_get_new_command(script, new_cmd, pip_unknown_cmd):\n    assert get_new_command(Command(script,\n                                   pip_unknown_cmd)) == new_cmd\n"
  },
  {
    "path": "tests/rules/test_port_already_in_use.py",
    "content": "from io import BytesIO\n\nimport pytest\nfrom thefuck.rules.port_already_in_use import match, get_new_command\nfrom thefuck.types import Command\n\noutputs = [\n    '''\n\nDE 70% 1/1 build modulesevents.js:141\n      throw er; // Unhandled 'error' event\n      ^\n\nError: listen EADDRINUSE 127.0.0.1:8080\n    at Object.exports._errnoException (util.js:873:11)\n    at exports._exceptionWithHostPort (util.js:896:20)\n    at Server._listen2 (net.js:1250:14)\n    at listen (net.js:1286:10)\n    at net.js:1395:9\n    at GetAddrInfoReqWrap.asyncCallback [as callback] (dns.js:64:16)\n    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:83:10)\n\n    ''',\n    '''\n[6:40:01 AM] <START> Building Dependency Graph\n[6:40:01 AM] <START> Crawling File System\n ERROR  Packager can't listen on port 8080\nMost likely another process is already using this port\nRun the following command to find out which process:\n\n   lsof -n -i4TCP:8080\n\nYou can either shut down the other process:\n\n   kill -9 <PID>\n\nor run packager on different port.\n\n    ''',\n    '''\nTraceback (most recent call last):\n  File \"/usr/lib/python3.5/runpy.py\", line 184, in _run_module_as_main\n    \"__main__\", mod_spec)\n  File \"/usr/lib/python3.5/runpy.py\", line 85, in _run_code\n    exec(code, run_globals)\n  File \"/home/nvbn/exp/code_view/server/code_view/main.py\", line 14, in <module>\n    web.run_app(app)\n  File \"/home/nvbn/.virtualenvs/code_view/lib/python3.5/site-packages/aiohttp/web.py\", line 310, in run_app\n    backlog=backlog))\n  File \"/usr/lib/python3.5/asyncio/base_events.py\", line 373, in run_until_complete\n    return future.result()\n  File \"/usr/lib/python3.5/asyncio/futures.py\", line 274, in result\n    raise self._exception\n  File \"/usr/lib/python3.5/asyncio/tasks.py\", line 240, in _step\n    result = coro.send(None)\n  File \"/usr/lib/python3.5/asyncio/base_events.py\", line 953, in create_server\n    % (sa, err.strerror.lower()))\nOSError: [Errno 98] error while attempting to bind on address ('0.0.0.0', 8080): address already in use\nTask was destroyed but it is pending!\ntask: <Task pending coro=<RedisProtocol._reader_coroutine() running at /home/nvbn/.virtualenvs/code_view/lib/python3.5/site-packages/asyncio_redis/protocol.py:921> wait_for=<Future pending cb=[Task._wakeup()]>>\n    '''\n]\n\nlsof_stdout = b'''COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME\nnode    18233 nvbn   16u  IPv4 557134      0t0  TCP localhost:http-alt (LISTEN)\n'''\n\n\n@pytest.fixture(autouse=True)\ndef lsof(mocker):\n    patch = mocker.patch('thefuck.rules.port_already_in_use.Popen')\n    patch.return_value.stdout = BytesIO(lsof_stdout)\n    return patch\n\n\n@pytest.mark.usefixtures('no_memoize')\n@pytest.mark.parametrize(\n    'command',\n    [Command('./app', output) for output in outputs]\n    + [Command('./app', output) for output in outputs])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.usefixtures('no_memoize')\n@pytest.mark.parametrize('command, lsof_output', [\n    (Command('./app', ''), lsof_stdout),\n    (Command('./app', outputs[1]), b''),\n    (Command('./app', outputs[2]), b'')])\ndef test_not_match(lsof, command, lsof_output):\n    lsof.return_value.stdout = BytesIO(lsof_output)\n\n    assert not match(command)\n\n\n@pytest.mark.parametrize(\n    'command',\n    [Command('./app', output) for output in outputs]\n    + [Command('./app', output) for output in outputs])\ndef test_get_new_command(command):\n    assert get_new_command(command) == 'kill 18233 && ./app'\n"
  },
  {
    "path": "tests/rules/test_prove_recursively.py",
    "content": "import pytest\nfrom thefuck.rules.prove_recursively import match, get_new_command\nfrom thefuck.types import Command\n\n\noutput = '''Files=0, Tests=0,  0 wallclock secs ( 0.00 usr +  0.00 sys =  0.00 CPU)\nResult: NOTESTS'''\n\n\n@pytest.fixture\ndef isdir(mocker):\n    return mocker.patch('thefuck.rules.prove_recursively'\n                        '.os.path.isdir')\n\n\n@pytest.mark.parametrize('script, output', [\n    ('prove -lv t', output),\n    ('prove app/t', output)])\ndef test_match(isdir, script, output):\n    isdir.return_value = True\n    command = Command(script, output)\n    assert match(command)\n\n\n@pytest.mark.parametrize('script, output, isdir_result', [\n    ('prove -lv t', output, False),\n    ('prove -r t', output, True),\n    ('prove --recurse t', output, True)])\ndef test_not_match(isdir, script, output, isdir_result):\n    isdir.return_value = isdir_result\n    command = Command(script, output)\n    assert not match(command)\n\n\n@pytest.mark.parametrize('before, after', [\n    ('prove -lv t', 'prove -r -lv t'),\n    ('prove t', 'prove -r t')])\ndef test_get_new_command(before, after):\n    command = Command(before, output)\n    assert get_new_command(command) == after\n"
  },
  {
    "path": "tests/rules/test_python_command.py",
    "content": "from thefuck.rules.python_command import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef test_match():\n    assert match(Command('temp.py', 'Permission denied'))\n    assert not match(Command('', ''))\n\n\ndef test_get_new_command():\n    assert (get_new_command(Command('./test_sudo.py', ''))\n            == 'python ./test_sudo.py')\n"
  },
  {
    "path": "tests/rules/test_python_execute.py",
    "content": "import pytest\nfrom thefuck.rules.python_execute import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('python foo', ''),\n    Command('python bar', '')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('python foo', ''), 'python foo.py'),\n    (Command('python bar', ''), 'python bar.py')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_python_module_error.py",
    "content": "import pytest\n\nfrom thefuck.rules.python_module_error import get_new_command, match\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef module_error_output(filename, module_name):\n    return \"\"\"Traceback (most recent call last):\n  File \"{0}\", line 1, in <module>\n    import {1}\nModuleNotFoundError: No module named '{1}'\"\"\".format(\n        filename, module_name\n    )\n\n\n@pytest.mark.parametrize(\n    \"test\",\n    [\n        Command(\"python hello_world.py\", \"Hello World\"),\n        Command(\n            \"./hello_world.py\",\n            \"\"\"Traceback (most recent call last):\n  File \"hello_world.py\", line 1, in <module>\n    pritn(\"Hello World\")\nNameError: name 'pritn' is not defined\"\"\",\n        ),\n    ],\n)\ndef test_not_match(test):\n    assert not match(test)\n\n\npositive_tests = [\n    (\n        \"python some_script.py\",\n        \"some_script.py\",\n        \"more_itertools\",\n        \"pip install more_itertools && python some_script.py\",\n    ),\n    (\n        \"./some_other_script.py\",\n        \"some_other_script.py\",\n        \"a_module\",\n        \"pip install a_module && ./some_other_script.py\",\n    ),\n]\n\n\n@pytest.mark.parametrize(\n    \"script, filename, module_name, corrected_script\", positive_tests\n)\ndef test_match(script, filename, module_name, corrected_script, module_error_output):\n    assert match(Command(script, module_error_output))\n\n\n@pytest.mark.parametrize(\n    \"script, filename, module_name, corrected_script\", positive_tests\n)\ndef test_get_new_command(\n    script, filename, module_name, corrected_script, module_error_output\n):\n    assert get_new_command(Command(script, module_error_output)) == corrected_script\n"
  },
  {
    "path": "tests/rules/test_quotation_marks.py",
    "content": "import pytest\nfrom thefuck.rules.quotation_marks import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command(\"git commit -m \\'My Message\\\"\", ''),\n    Command(\"git commit -am \\\"Mismatched Quotation Marks\\'\", ''),\n    Command(\"echo \\\"hello\\'\", '')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command(\"git commit -m \\'My Message\\\"\", ''), \"git commit -m \\\"My Message\\\"\"),\n    (Command(\"git commit -am \\\"Mismatched Quotation Marks\\'\", ''), \"git commit -am \\\"Mismatched Quotation Marks\\\"\"),\n    (Command(\"echo \\\"hello\\'\", ''), \"echo \\\"hello\\\"\")])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_rails_migrations_pending.py",
    "content": "import pytest\nfrom thefuck.rules.rails_migrations_pending import match, get_new_command\nfrom thefuck.types import Command\n\noutput_env_development = '''\nMigrations are pending. To resolve this issue, run:\n\n        rails db:migrate RAILS_ENV=development\n'''\noutput_env_test = '''\nMigrations are pending. To resolve this issue, run:\n\n        bin/rails db:migrate RAILS_ENV=test\n'''\n\n\n@pytest.mark.parametrize(\n    \"command\",\n    [\n        Command(\"\", output_env_development),\n        Command(\"\", output_env_test),\n    ],\n)\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize(\n    \"command\",\n    [\n        Command(\"Environment data not found in the schema. To resolve this issue, run: \\n\\n\", \"\"),\n    ],\n)\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize(\n    \"command, new_command\",\n    [\n        (Command(\"bin/rspec\", output_env_development), \"rails db:migrate RAILS_ENV=development && bin/rspec\"),\n        (Command(\"bin/rspec\", output_env_test), \"bin/rails db:migrate RAILS_ENV=test && bin/rspec\"),\n    ],\n)\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_react_native_command_unrecognized.py",
    "content": "import pytest\nfrom io import BytesIO\nfrom thefuck.rules.react_native_command_unrecognized import match, \\\n    get_new_command\nfrom thefuck.types import Command\n\noutput = \"Unrecognized command '{}'\".format\n\nstdout = b'''\nScanning 615 folders for symlinks in /home/nvbn/work/zcho/BookkaWebView/node_modules (6ms)\n\n  Usage: react-native [options] [command]\n\n\n  Options:\n\n    -V, --version  output the version number\n    -h, --help     output usage information\n\n\n  Commands:\n\n    start [options]                    starts the webserver\n    run-ios [options]                  builds your app and starts it on iOS simulator\n    run-android [options]              builds your app and starts it on a connected Android emulator or device\n    new-library [options]              generates a native library bridge\n    bundle [options]                   builds the javascript bundle for offline use\n    unbundle [options]                 builds javascript as \"unbundle\" for offline use\n    eject [options]                    Re-create the iOS and Android folders and native code\n    link [options] [packageName]       links all native dependencies (updates native build files)\n    unlink [options] <packageName>     unlink native dependency\n    install [options] <packageName>    install and link native dependencies\n    uninstall [options] <packageName>  uninstall and unlink native dependencies\n    upgrade [options]                  upgrade your app's template files to the latest version; run this after updating the react-native version in your package.json and running npm install\n    log-android [options]              starts adb logcat\n    log-ios [options]                  starts iOS device syslog tail\n'''\n\n\n@pytest.mark.parametrize('command', [\n    Command('react-native star', output('star')),\n    Command('react-native android-logs', output('android-logs'))])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('gradle star', output('star')),\n    Command('react-native start', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, result', [\n    (Command('react-native star', output('star')),\n     'react-native start'),\n    (Command('react-native logsandroid -f', output('logsandroid')),\n     'react-native log-android -f')])\ndef test_get_new_command(mocker, command, result):\n    patch = mocker.patch(\n        'thefuck.rules.react_native_command_unrecognized.Popen')\n    patch.return_value.stdout = BytesIO(stdout)\n    assert get_new_command(command)[0] == result\n"
  },
  {
    "path": "tests/rules/test_remove_shell_prompt_literal.py",
    "content": "import pytest\nfrom thefuck.rules.remove_shell_prompt_literal import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef output():\n    return \"$: command not found\"\n\n\n@pytest.mark.parametrize(\n    \"script\",\n    [\n        \"$ cd newdir\",\n        \" $ cd newdir\",\n        \"$ $ cd newdir\",\n        \" $ $ cd newdir\",\n    ],\n)\ndef test_match(script, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize(\n    \"command\",\n    [\n        Command(\"$\", \"$: command not found\"),\n        Command(\" $\", \"$: command not found\"),\n        Command(\"$?\", \"127: command not found\"),\n        Command(\" $?\", \"127: command not found\"),\n        Command(\"\", \"\"),\n    ],\n)\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize(\n    \"script, new_command\",\n    [\n        (\"$ cd newdir\", \"cd newdir\"),\n        (\"$ $ cd newdir\", \"cd newdir\"),\n        (\"$ python3 -m virtualenv env\", \"python3 -m virtualenv env\"),\n        (\" $ $ $ python3 -m virtualenv env\", \"python3 -m virtualenv env\"),\n    ],\n)\ndef test_get_new_command(script, new_command, output):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_remove_trailing_cedilla.py",
    "content": "import pytest\nfrom thefuck.rules.remove_trailing_cedilla import match, get_new_command, CEDILLA\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('wrong' + CEDILLA, ''),\n    Command('wrong with args' + CEDILLA, '')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('wrong' + CEDILLA, ''), 'wrong'),\n    (Command('wrong with args' + CEDILLA, ''), 'wrong with args')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_rm_dir.py",
    "content": "import pytest\nfrom thefuck.rules.rm_dir import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('rm foo', 'rm: foo: is a directory'),\n    Command('rm foo', 'rm: foo: Is a directory'),\n    Command('hdfs dfs -rm foo', 'rm: `foo`: Is a directory'),\n    Command('./bin/hdfs dfs -rm foo', 'rm: `foo`: Is a directory'),\n])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('rm foo', ''),\n    Command('hdfs dfs -rm foo', ''),\n    Command('./bin/hdfs dfs -rm foo', ''),\n    Command('', ''),\n])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('rm foo', ''), 'rm -rf foo'),\n    (Command('hdfs dfs -rm foo', ''), 'hdfs dfs -rm -r foo'),\n])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_rm_root.py",
    "content": "import pytest\nfrom thefuck.rules.rm_root import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef test_match():\n    assert match(Command('rm -rf /', 'add --no-preserve-root'))\n\n\n@pytest.mark.parametrize('command', [\n    Command('ls', 'add --no-preserve-root'),\n    Command('rm --no-preserve-root /', 'add --no-preserve-root'),\n    Command('rm -rf /', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\ndef test_get_new_command():\n    assert (get_new_command(Command('rm -rf /', ''))\n            == 'rm -rf / --no-preserve-root')\n"
  },
  {
    "path": "tests/rules/test_scm_correction.py",
    "content": "import pytest\nfrom thefuck.rules.scm_correction import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef get_actual_scm_mock(mocker):\n    return mocker.patch('thefuck.rules.scm_correction._get_actual_scm',\n                        return_value=None)\n\n\n@pytest.mark.parametrize('script, output, actual_scm', [\n    ('git log', 'fatal: Not a git repository '\n                '(or any of the parent directories): .git',\n     'hg'),\n    ('hg log', \"abort: no repository found in '/home/nvbn/exp/thefuck' \"\n               \"(.hg not found)!\",\n     'git')])\ndef test_match(get_actual_scm_mock, script, output, actual_scm):\n    get_actual_scm_mock.return_value = actual_scm\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output, actual_scm', [\n    ('git log', '', 'hg'),\n    ('git log', 'fatal: Not a git repository '\n                '(or any of the parent directories): .git',\n     None),\n    ('hg log', \"abort: no repository found in '/home/nvbn/exp/thefuck' \"\n               \"(.hg not found)!\",\n     None),\n    ('not-scm log', \"abort: no repository found in '/home/nvbn/exp/thefuck' \"\n                    \"(.hg not found)!\",\n     'git')])\ndef test_not_match(get_actual_scm_mock, script, output, actual_scm):\n    get_actual_scm_mock.return_value = actual_scm\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, actual_scm, result', [\n    ('git log', 'hg', 'hg log'),\n    ('hg log', 'git', 'git log')])\ndef test_get_new_command(get_actual_scm_mock, script, actual_scm, result):\n    get_actual_scm_mock.return_value = actual_scm\n    new_command = get_new_command(Command(script, ''))\n    assert new_command == result\n"
  },
  {
    "path": "tests/rules/test_sed_unterminated_s.py",
    "content": "import pytest\nfrom thefuck.rules.sed_unterminated_s import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef sed_unterminated_s():\n    return \"sed: -e expression #1, char 9: unterminated `s' command\"\n\n\ndef test_match(sed_unterminated_s):\n    assert match(Command('sed -e s/foo/bar', sed_unterminated_s))\n    assert match(Command('sed -es/foo/bar', sed_unterminated_s))\n    assert match(Command('sed -e s/foo/bar -e s/baz/quz', sed_unterminated_s))\n    assert not match(Command('sed -e s/foo/bar', ''))\n    assert not match(Command('sed -es/foo/bar', ''))\n    assert not match(Command('sed -e s/foo/bar -e s/baz/quz', ''))\n\n\ndef test_get_new_command(sed_unterminated_s):\n    assert (get_new_command(Command('sed -e s/foo/bar', sed_unterminated_s))\n            == 'sed -e s/foo/bar/')\n    assert (get_new_command(Command('sed -es/foo/bar', sed_unterminated_s))\n            == 'sed -es/foo/bar/')\n    assert (get_new_command(Command(r\"sed -e 's/\\/foo/bar'\", sed_unterminated_s))\n            == r\"sed -e 's/\\/foo/bar/'\")\n    assert (get_new_command(Command(r\"sed -e s/foo/bar -es/baz/quz\", sed_unterminated_s))\n            == r\"sed -e s/foo/bar/ -es/baz/quz/\")\n"
  },
  {
    "path": "tests/rules/test_sl_ls.py",
    "content": "\nfrom thefuck.rules.sl_ls import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef test_match():\n    assert match(Command('sl', ''))\n    assert not match(Command('ls', ''))\n\n\ndef test_get_new_command():\n    assert get_new_command(Command('sl', '')) == 'ls'\n"
  },
  {
    "path": "tests/rules/test_ssh_known_host.py",
    "content": "import os\nimport pytest\nfrom thefuck.rules.ssh_known_hosts import match, get_new_command, \\\n    side_effect\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef ssh_error(tmpdir):\n    path = os.path.join(str(tmpdir), 'known_hosts')\n\n    def reset(path):\n        with open(path, 'w') as fh:\n            lines = [\n                '123.234.567.890 asdjkasjdakjsd\\n'\n                '98.765.432.321 ejioweojwejrosj\\n'\n                '111.222.333.444 qwepoiwqepoiss\\n'\n            ]\n            fh.writelines(lines)\n\n    def known_hosts(path):\n        with open(path, 'r') as fh:\n            return fh.readlines()\n\n    reset(path)\n\n    errormsg = u\"\"\"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\nIT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\nSomeone could be eavesdropping on you right now (man-in-the-middle attack)!\nIt is also possible that a host key has just been changed.\nThe fingerprint for the RSA key sent by the remote host is\nb6:cb:07:34:c0:a0:94:d3:0d:69:83:31:f4:c5:20:9b.\nPlease contact your system administrator.\nAdd correct host key in {0} to get rid of this message.\nOffending RSA key in {0}:2\nRSA host key for {1} has changed and you have requested strict checking.\nHost key verification failed.\"\"\".format(path, '98.765.432.321')\n\n    return errormsg, path, reset, known_hosts\n\n\ndef test_match(ssh_error):\n    errormsg, _, _, _ = ssh_error\n    assert match(Command('ssh', errormsg))\n    assert match(Command('ssh', errormsg))\n    assert match(Command('scp something something', errormsg))\n    assert match(Command('scp something something', errormsg))\n    assert not match(Command(errormsg, ''))\n    assert not match(Command('notssh', errormsg))\n    assert not match(Command('ssh', ''))\n\n\n@pytest.mark.skipif(os.name == 'nt', reason='Skip if testing on Windows')\ndef test_side_effect(ssh_error):\n    errormsg, path, reset, known_hosts = ssh_error\n    command = Command('ssh user@host', errormsg)\n    side_effect(command, None)\n    expected = ['123.234.567.890 asdjkasjdakjsd\\n', '111.222.333.444 qwepoiwqepoiss\\n']\n    assert known_hosts(path) == expected\n\n\ndef test_get_new_command(ssh_error, monkeypatch):\n    errormsg, _, _, _ = ssh_error\n    assert get_new_command(Command('ssh user@host', errormsg)) == 'ssh user@host'\n"
  },
  {
    "path": "tests/rules/test_sudo.py",
    "content": "import pytest\nfrom thefuck.rules.sudo import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('output', [\n    'Permission denied',\n    'permission denied',\n    \"npm ERR! Error: EACCES, unlink\",\n    'requested operation requires superuser privilege',\n    'need to be root',\n    'need root',\n    'shutdown: NOT super-user',\n    'Error: This command has to be run with superuser privileges (under the root user on most systems).',\n    'updatedb: can not open a temporary file for `/var/lib/mlocate/mlocate.db',\n    'must be root',\n    'You don\\'t have access to the history DB.',\n    \"error: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/ipaddr.py'\"])\ndef test_match(output):\n    assert match(Command('', output))\n\n\ndef test_not_match():\n    assert not match(Command('', ''))\n    assert not match(Command('sudo ls', 'Permission denied'))\n\n\n@pytest.mark.parametrize('before, after', [\n    ('ls', 'sudo ls'),\n    ('echo a > b', 'sudo sh -c \"echo a > b\"'),\n    ('echo \"a\" >> b', 'sudo sh -c \"echo \\\\\"a\\\\\" >> b\"'),\n    ('mkdir && touch a', 'sudo sh -c \"mkdir && touch a\"')])\ndef test_get_new_command(before, after):\n    assert get_new_command(Command(before, '')) == after\n"
  },
  {
    "path": "tests/rules/test_sudo_command_from_user_path.py",
    "content": "import pytest\nfrom thefuck.rules.sudo_command_from_user_path import match, get_new_command\nfrom thefuck.types import Command\n\n\noutput = 'sudo: {}: command not found'\n\n\n@pytest.fixture(autouse=True)\ndef which(mocker):\n    return mocker.patch('thefuck.rules.sudo_command_from_user_path.which',\n                        return_value='/usr/bin/app')\n\n\n@pytest.mark.parametrize('script, output', [\n    ('sudo npm install -g react-native-cli', output.format('npm')),\n    ('sudo -u app appcfg update .', output.format('appcfg'))])\ndef test_match(script, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output, which_result', [\n    ('npm --version', output.format('npm'), '/usr/bin/npm'),\n    ('sudo npm --version', '', '/usr/bin/npm'),\n    ('sudo npm --version', output.format('npm'), None)])\ndef test_not_match(which, script, output, which_result):\n    which.return_value = which_result\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output, result', [\n    ('sudo npm install -g react-native-cli',\n     output.format('npm'),\n     'sudo env \"PATH=$PATH\" npm install -g react-native-cli'),\n    ('sudo -u app appcfg update .',\n     output.format('appcfg'),\n     'sudo -u app env \"PATH=$PATH\" appcfg update .')])\ndef test_get_new_command(script, output, result):\n    assert get_new_command(Command(script, output)) == result\n"
  },
  {
    "path": "tests/rules/test_switch_lang.py",
    "content": "# -*- encoding: utf-8 -*-\n\nimport pytest\n\nfrom thefuck.rules import switch_lang\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command(u'фзе-пуе', 'command not found: фзе-пуе'),\n    Command(u'λσ', 'command not found: λσ'),\n    Command(u'שפא-עקא', 'command not found: שפא-עקא'),\n    Command(u'ךד', 'command not found: ךד'),\n    Command(u'녀애 ㅣㄴ', 'command not found: 녀애 ㅣㄴ')])\ndef test_match(command):\n    assert switch_lang.match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command(u'pat-get', 'command not found: pat-get'),\n    Command(u'ls', 'command not found: ls'),\n    Command(u'агсл', 'command not found: агсл'),\n    Command(u'фзе-пуе', 'some info'),\n    Command(u'שפא-עקא', 'some info'),\n    Command(u'녀애 ㅣㄴ', 'some info')])\ndef test_not_match(command):\n    assert not switch_lang.match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command(u'фзе-пуе штыефдд мшь', ''), 'apt-get install vim'),\n    (Command(u'λσ -λα', ''), 'ls -la'),\n    (Command(u'שפא-עקא ןמדאשךך הןצ', ''), 'apt-get install vim'),\n    (Command(u'ךד -ךש', ''), 'ls -la'),\n    (Command(u'멧-ㅎㄷㅅ ㅑㅜㄴㅅ미ㅣ 퍄ㅡ', ''), 'apt-get install vim'),\n    (Command(u'ㅣㄴ -ㅣㅁ', ''), 'ls -la'),\n    (Command(u'ㅔㅁㅅ촤', ''), 'patchk'), ])\ndef test_get_new_command(command, new_command):\n    assert switch_lang.get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_systemctl.py",
    "content": "from thefuck.rules.systemctl import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef test_match():\n    assert match(Command('systemctl nginx start', 'Unknown operation \\'nginx\\'.'))\n    assert match(Command('sudo systemctl nginx start', 'Unknown operation \\'nginx\\'.'))\n    assert not match(Command('systemctl start nginx', ''))\n    assert not match(Command('systemctl start nginx', ''))\n    assert not match(Command('sudo systemctl nginx', 'Unknown operation \\'nginx\\'.'))\n    assert not match(Command('systemctl nginx', 'Unknown operation \\'nginx\\'.'))\n    assert not match(Command('systemctl start wtf', 'Failed to start wtf.service: Unit wtf.service failed to load: No such file or directory.'))\n\n\ndef test_get_new_command():\n    assert get_new_command(Command('systemctl nginx start', '')) == \"systemctl start nginx\"\n    assert get_new_command(Command('sudo systemctl nginx start', '')) == \"sudo systemctl start nginx\"\n"
  },
  {
    "path": "tests/rules/test_terraform_init.py",
    "content": "import pytest\nfrom thefuck.rules.terraform_init import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('script, output', [\n    ('terraform plan', 'Error: Initialization required. '\n                       'Please see the error message above.'),\n    ('terraform plan', 'This module is not yet installed. Run \"terraform init\" '\n                       'to install all modules required by this configuration.'),\n    ('terraform apply', 'Error: Initialization required. '\n                        'Please see the error message above.'),\n    ('terraform apply', 'This module is not yet installed. Run \"terraform init\" '\n                        'to install all modules required by this configuration.')])\ndef test_match(script, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output', [\n    ('terraform --version', 'Terraform v0.12.2'),\n    ('terraform plan', 'No changes. Infrastructure is up-to-date.'),\n    ('terraform apply', 'Apply complete! Resources: 0 added, 0 changed, 0 destroyed.'),\n])\ndef test_not_match(script, output):\n    assert not match(Command(script, output=output))\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('terraform plan', ''), 'terraform init && terraform plan'),\n    (Command('terraform apply', ''), 'terraform init && terraform apply'),\n])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_terraform_no_command.py",
    "content": "import pytest\nfrom thefuck.rules.terraform_no_command import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('script, output', [\n    ('terraform appyl', 'Terraform has no command named \"appyl\". Did you mean \"apply\"?'),\n    ('terraform destory', 'Terraform has no command named \"destory\". Did you mean \"destroy\"?')])\ndef test_match(script, output):\n    assert match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output', [\n    ('terraform --version', 'Terraform v0.12.2'),\n    ('terraform plan', 'No changes. Infrastructure is up-to-date.'),\n    ('terraform apply', 'Apply complete! Resources: 0 added, 0 changed, 0 destroyed.'),\n])\ndef test_not_match(script, output):\n    assert not match(Command(script, output))\n\n\n@pytest.mark.parametrize('script, output, new_command', [\n    ('terraform appyl', 'Terraform has no command named \"appyl\". Did you mean \"apply\"?', 'terraform apply',),\n    ('terraform destory --some-other-option', 'Terraform has no command named \"destory\". Did you mean \"destroy\"?', 'terraform destroy --some-other-option',),\n])\ndef test_get_new_command(script, output, new_command):\n    assert get_new_command(Command(script, output)) == new_command\n"
  },
  {
    "path": "tests/rules/test_tmux.py",
    "content": "import pytest\nfrom thefuck.rules.tmux import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture\ndef tmux_ambiguous():\n    return \"ambiguous command: list, could be: \" \\\n           \"list-buffers, list-clients, list-commands, list-keys, \" \\\n           \"list-panes, list-sessions, list-windows\"\n\n\ndef test_match(tmux_ambiguous):\n    assert match(Command('tmux list', tmux_ambiguous))\n\n\ndef test_get_new_command(tmux_ambiguous):\n    assert get_new_command(Command('tmux list', tmux_ambiguous))\\\n        == ['tmux list-keys', 'tmux list-panes', 'tmux list-windows']\n"
  },
  {
    "path": "tests/rules/test_touch.py",
    "content": "import pytest\nfrom thefuck.rules.touch import match, get_new_command\nfrom thefuck.types import Command\n\n\ndef output(is_bsd):\n    if is_bsd:\n        return \"touch: /a/b/c: No such file or directory\"\n    return \"touch: cannot touch '/a/b/c': No such file or directory\"\n\n\n@pytest.mark.parametrize('script, is_bsd', [\n    ('touch /a/b/c', False),\n    ('touch /a/b/c', True)])\ndef test_match(script, is_bsd):\n    command = Command(script, output(is_bsd))\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('touch /a/b/c', ''),\n    Command('ls /a/b/c', output(False))])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('script, is_bsd', [\n    ('touch /a/b/c', False),\n    ('touch /a/b/c', True)])\ndef test_get_new_command(script, is_bsd):\n    command = Command(script, output(is_bsd))\n    fixed_command = get_new_command(command)\n    assert fixed_command == 'mkdir -p /a/b && touch /a/b/c'\n"
  },
  {
    "path": "tests/rules/test_tsuru_login.py",
    "content": "import pytest\nfrom thefuck.rules.tsuru_login import match, get_new_command\nfrom thefuck.types import Command\n\n\nerror_msg = (\n    \"Error: you're not authenticated or your session has expired.\",\n    (\"You're not authenticated or your session has expired. \"\n     \"Please use \\\"login\\\" command for authentication.\"),\n)\n\n\n@pytest.mark.parametrize('command', [\n    Command('tsuru app-shell', error_msg[0]),\n    Command('tsuru app-log -f', error_msg[1]),\n])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('tsuru', ''),\n    Command('tsuru app-restart', 'Error: unauthorized'),\n    Command('tsuru app-log -f', 'Error: unparseable data'),\n])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('tsuru app-shell', error_msg[0]),\n     'tsuru login && tsuru app-shell'),\n    (Command('tsuru app-log -f', error_msg[1]),\n     'tsuru login && tsuru app-log -f'),\n])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_tsuru_not_command.py",
    "content": "import pytest\n\nfrom thefuck.types import Command\nfrom thefuck.rules.tsuru_not_command import match, get_new_command\n\n\n@pytest.mark.parametrize('command', [\n    Command('tsuru log', (\n        'tsuru: \"tchururu\" is not a tsuru command. See \"tsuru help\".\\n'\n        '\\nDid you mean?\\n'\n        '\\tapp-log\\n'\n        '\\tlogin\\n'\n        '\\tlogout\\n'\n    )),\n    Command('tsuru app-l', (\n        'tsuru: \"tchururu\" is not a tsuru command. See \"tsuru help\".\\n'\n        '\\nDid you mean?\\n'\n        '\\tapp-list\\n'\n        '\\tapp-log\\n'\n    )),\n    Command('tsuru user-list', (\n        'tsuru: \"tchururu\" is not a tsuru command. See \"tsuru help\".\\n'\n        '\\nDid you mean?\\n'\n        '\\tteam-user-list\\n'\n    )),\n    Command('tsuru targetlist', (\n        'tsuru: \"tchururu\" is not a tsuru command. See \"tsuru help\".\\n'\n        '\\nDid you mean?\\n'\n        '\\ttarget-list\\n'\n    )),\n])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('tsuru tchururu', (\n        'tsuru: \"tchururu\" is not a tsuru command. See \"tsuru help\".\\n'\n        '\\nDid you mean?\\n'\n    )),\n    Command('tsuru version', 'tsuru version 0.16.0.'),\n    Command('tsuru help', (\n        'tsuru version 0.16.0.\\n'\n        '\\nUsage: tsuru command [args]\\n'\n    )),\n    Command('tsuru platform-list', (\n        '- java\\n'\n        '- logstashgiro\\n'\n        '- newnode\\n'\n        '- nodejs\\n'\n        '- php\\n'\n        '- python\\n'\n        '- python3\\n'\n        '- ruby\\n'\n        '- ruby20\\n'\n        '- static\\n'\n    )),\n    Command('tsuru env-get', 'Error: App thefuck not found.'),\n])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_commands', [\n    (Command('tsuru log', (\n        'tsuru: \"log\" is not a tsuru command. See \"tsuru help\".\\n'\n        '\\nDid you mean?\\n'\n        '\\tapp-log\\n'\n        '\\tlogin\\n'\n        '\\tlogout\\n'\n    )), ['tsuru login', 'tsuru logout', 'tsuru app-log']),\n    (Command('tsuru app-l', (\n        'tsuru: \"app-l\" is not a tsuru command. See \"tsuru help\".\\n'\n        '\\nDid you mean?\\n'\n        '\\tapp-list\\n'\n        '\\tapp-log\\n'\n    )), ['tsuru app-log', 'tsuru app-list']),\n    (Command('tsuru user-list', (\n        'tsuru: \"user-list\" is not a tsuru command. See \"tsuru help\".\\n'\n        '\\nDid you mean?\\n'\n        '\\tteam-user-list\\n'\n    )), ['tsuru team-user-list']),\n    (Command('tsuru targetlist', (\n        'tsuru: \"targetlist\" is not a tsuru command. See \"tsuru help\".\\n'\n        '\\nDid you mean?\\n'\n        '\\ttarget-list\\n'\n    )), ['tsuru target-list']),\n])\ndef test_get_new_command(command, new_commands):\n    assert get_new_command(command) == new_commands\n"
  },
  {
    "path": "tests/rules/test_unknown_command.py",
    "content": "import pytest\nfrom thefuck.rules.unknown_command import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('./bin/hdfs dfs ls', 'ls: Unknown command\\nDid you mean -ls?  This command begins with a dash.'),\n    Command('hdfs dfs ls',\n            'ls: Unknown command\\nDid you mean -ls?  This command begins with a dash.'),\n    Command('hdfs dfs ls /foo/bar', 'ls: Unknown command\\nDid you mean -ls?  This command begins with a dash.')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('./bin/hdfs dfs -ls', ''),\n    Command('./bin/hdfs dfs -ls /foo/bar', ''),\n    Command('hdfs dfs -ls -R /foo/bar', ''),\n    Command('', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('hdfs dfs ls',\n             'ls: Unknown command\\nDid you mean -ls?  This command begins with a dash.'), ['hdfs dfs -ls']),\n    (Command('hdfs dfs rm /foo/bar',\n             'rm: Unknown command\\nDid you mean -rm?  This command begins with a dash.'), ['hdfs dfs -rm /foo/bar']),\n    (Command('./bin/hdfs dfs ls -R /foo/bar',\n             'ls: Unknown command\\nDid you mean -ls?  This command begins with a dash.'), ['./bin/hdfs dfs -ls -R /foo/bar']),\n    (Command('./bin/hdfs dfs -Dtest=fred ls -R /foo/bar',\n             'ls: Unknown command\\nDid you mean -ls?  This command begins with a dash.'), ['./bin/hdfs dfs -Dtest=fred -ls -R /foo/bar'])])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_unsudo.py",
    "content": "import pytest\nfrom thefuck.rules.unsudo import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('output', [\n    'you cannot perform this operation as root'])\ndef test_match(output):\n    assert match(Command('sudo ls', output))\n\n\ndef test_not_match():\n    assert not match(Command('', ''))\n    assert not match(Command('sudo ls', 'Permission denied'))\n    assert not match(Command('ls', 'you cannot perform this operation as root'))\n\n\n@pytest.mark.parametrize('before, after', [\n    ('sudo ls', 'ls'),\n    ('sudo pacaur -S helloworld', 'pacaur -S helloworld')])\ndef test_get_new_command(before, after):\n    assert get_new_command(Command(before, '')) == after\n"
  },
  {
    "path": "tests/rules/test_vagrant_up.py",
    "content": "import pytest\nfrom thefuck.rules.vagrant_up import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('vagrant ssh', 'VM must be running to open SSH connection. Run `vagrant up`\\nto start the virtual machine.'),\n    Command('vagrant ssh devbox', 'VM must be running to open SSH connection. Run `vagrant up`\\nto start the virtual machine.'),\n    Command('vagrant rdp',\n            'VM must be created before running this command. Run `vagrant up` first.'),\n    Command('vagrant rdp devbox',\n            'VM must be created before running this command. Run `vagrant up` first.')])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('vagrant ssh', ''),\n    Command('vagrant ssh jeff', 'The machine with the name \\'jeff\\' was not found configured for this Vagrant environment.'),\n    Command('vagrant ssh', 'A Vagrant environment or target machine is required to run this command. Run `vagrant init` to create a new Vagrant environment. Or, get an ID of a target machine from `vagrant global-status` to run this command on. A final option is to change to a directory with a Vagrantfile and to try again.'),\n    Command('', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('vagrant ssh', 'VM must be running to open SSH connection. Run `vagrant up`\\nto start the virtual machine.'), 'vagrant up && vagrant ssh'),\n    (Command('vagrant ssh devbox', 'VM must be running to open SSH connection. Run `vagrant up`\\nto start the virtual machine.'), ['vagrant up devbox && vagrant ssh devbox', 'vagrant up && vagrant ssh devbox']),\n    (Command('vagrant rdp',\n             'VM must be created before running this command. Run `vagrant up` first.'), 'vagrant up && vagrant rdp'),\n    (Command('vagrant rdp devbox',\n             'VM must be created before running this command. Run `vagrant up` first.'), ['vagrant up devbox && vagrant rdp devbox', 'vagrant up && vagrant rdp devbox'])])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_whois.py",
    "content": "import pytest\nfrom thefuck.rules.whois import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('command', [\n    Command('whois https://en.wikipedia.org/wiki/Main_Page', ''),\n    Command('whois https://en.wikipedia.org/', ''),\n    Command('whois meta.unix.stackexchange.com', '')])\ndef test_match(command):\n    assert match(command)\n\n\ndef test_not_match():\n    assert not match(Command('whois', ''))\n\n\n# `whois com` actually makes sense\n@pytest.mark.parametrize('command, new_command', [\n    (Command('whois https://en.wikipedia.org/wiki/Main_Page', ''),\n     'whois en.wikipedia.org'),\n    (Command('whois https://en.wikipedia.org/', ''),\n     'whois en.wikipedia.org'),\n    (Command('whois meta.unix.stackexchange.com', ''),\n     ['whois unix.stackexchange.com',\n      'whois stackexchange.com',\n      'whois com'])])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_workon_doesnt_exists.py",
    "content": "import pytest\nfrom thefuck.rules.workon_doesnt_exists import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture(autouse=True)\ndef envs(mocker):\n    return mocker.patch(\n        'thefuck.rules.workon_doesnt_exists._get_all_environments',\n        return_value=['thefuck', 'code_view'])\n\n\n@pytest.mark.parametrize('script', [\n    'workon tehfuck', 'workon code-view', 'workon new-env'])\ndef test_match(script):\n    assert match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script', [\n    'workon thefuck', 'workon code_view', 'work on tehfuck'])\ndef test_not_match(script):\n    assert not match(Command(script, ''))\n\n\n@pytest.mark.parametrize('script, result', [\n    ('workon tehfuck', 'workon thefuck'),\n    ('workon code-view', 'workon code_view'),\n    ('workon zzzz', 'mkvirtualenv zzzz')])\ndef test_get_new_command(script, result):\n    assert get_new_command(Command(script, ''))[0] == result\n"
  },
  {
    "path": "tests/rules/test_wrong_hyphen_before_subcommand.py",
    "content": "import pytest\n\nfrom thefuck.rules.wrong_hyphen_before_subcommand import match, get_new_command\nfrom thefuck.types import Command\n\n\n@pytest.fixture(autouse=True)\ndef get_all_executables(mocker):\n    mocker.patch(\n        \"thefuck.rules.wrong_hyphen_before_subcommand.get_all_executables\",\n        return_value=[\"git\", \"apt\", \"apt-get\", \"ls\", \"pwd\"],\n    )\n\n\n@pytest.mark.parametrize(\"script\", [\"git-log\", \"apt-install python\"])\ndef test_match(script):\n    assert match(Command(script, \"\"))\n\n\n@pytest.mark.parametrize(\"script\", [\"ls -la\", \"git2-make\", \"apt-get install python\"])\ndef test_not_match(script):\n    assert not match(Command(script, \"\"))\n\n\n@pytest.mark.parametrize(\n    \"script, new_command\",\n    [(\"git-log\", \"git log\"), (\"apt-install python\", \"apt install python\")],\n)\ndef test_get_new_command(script, new_command):\n    assert get_new_command(Command(script, \"\")) == new_command\n"
  },
  {
    "path": "tests/rules/test_yarn_alias.py",
    "content": "import pytest\nfrom thefuck.rules.yarn_alias import match, get_new_command\nfrom thefuck.types import Command\n\n\noutput_remove = 'error Did you mean `yarn remove`?'\noutput_etl = 'error Command \"etil\" not found. Did you mean \"etl\"?'\noutput_list = 'error Did you mean `yarn list`?'\n\n\n@pytest.mark.parametrize('command', [\n    Command('yarn rm', output_remove),\n    Command('yarn etil', output_etl),\n    Command('yarn ls', output_list)])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('yarn rm', output_remove), 'yarn remove'),\n    (Command('yarn etil', output_etl), 'yarn etl'),\n    (Command('yarn ls', output_list), 'yarn list')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_yarn_command_not_found.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom io import BytesIO\nimport pytest\nfrom thefuck.types import Command\nfrom thefuck.rules.yarn_command_not_found import match, get_new_command\n\noutput = '''\nerror Command \"{}\" not found.\n'''.format\n\nyarn_help_stdout = b'''\n\n  Usage: yarn [command] [flags]\n\n  Options:\n\n    -h, --help                      output usage information\n    -V, --version                   output the version number\n    --verbose                       output verbose messages on internal operations\n    --offline                       trigger an error if any required dependencies are not available in local cache\n    --prefer-offline                use network only if dependencies are not available in local cache\n    --strict-semver                 \n    --json                          \n    --ignore-scripts                don't run lifecycle scripts\n    --har                           save HAR output of network traffic\n    --ignore-platform               ignore platform checks\n    --ignore-engines                ignore engines check\n    --ignore-optional               ignore optional dependencies\n    --force                         ignore all caches\n    --no-bin-links                  don't generate bin links when setting up packages\n    --flat                          only allow one version of a package\n    --prod, --production [prod]     \n    --no-lockfile                   don't read or generate a lockfile\n    --pure-lockfile                 don't generate a lockfile\n    --frozen-lockfile               don't generate a lockfile and fail if an update is needed\n    --link-duplicates               create hardlinks to the repeated modules in node_modules\n    --global-folder <path>          \n    --modules-folder <path>         rather than installing modules into the node_modules folder relative to the cwd, output them here\n    --cache-folder <path>           specify a custom folder to store the yarn cache\n    --mutex <type>[:specifier]      use a mutex to ensure only one yarn instance is executing\n    --no-emoji                      disable emoji in output\n    --proxy <host>                  \n    --https-proxy <host>            \n    --no-progress                   disable progress bar\n    --network-concurrency <number>  maximum number of concurrent network requests\n\n  Commands:\n\n    - access\n    - add\n    - bin\n    - cache\n    - check\n    - clean\n    - config\n    - generate-lock-entry\n    - global\n    - import\n    - info\n    - init\n    - install\n    - licenses\n    - link\n    - list\n    - login\n    - logout\n    - outdated\n    - owner\n    - pack\n    - publish\n    - remove\n    - run\n    - tag\n    - team\n    - unlink\n    - upgrade\n    - upgrade-interactive\n    - version\n    - versions\n    - why\n\n  Run `yarn help COMMAND` for more information on specific commands.\n  Visit https://yarnpkg.com/en/docs/cli/ to learn more about Yarn.\n''' # noqa\n\n\n@pytest.fixture(autouse=True)\ndef yarn_help(mocker):\n    patch = mocker.patch('thefuck.rules.yarn_command_not_found.Popen')\n    patch.return_value.stdout = BytesIO(yarn_help_stdout)\n    return patch\n\n\n@pytest.mark.parametrize('command', [\n    Command('yarn whyy webpack', output('whyy'))])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('npm nuild', output('nuild')),\n    Command('yarn install', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, result', [\n    (Command('yarn whyy webpack', output('whyy')),\n     'yarn why webpack'),\n    (Command('yarn require lodash', output('require')),\n     'yarn add lodash')])\ndef test_get_new_command(command, result):\n    fixed_command = get_new_command(command)\n    if isinstance(fixed_command, list):\n        fixed_command = fixed_command[0]\n\n    assert fixed_command == result\n"
  },
  {
    "path": "tests/rules/test_yarn_command_replaced.py",
    "content": "import pytest\nfrom thefuck.types import Command\nfrom thefuck.rules.yarn_command_replaced import match, get_new_command\n\n\noutput = ('error `install` has been replaced with `add` to add new '\n          'dependencies. Run \"yarn add {}\" instead.').format\n\n\n@pytest.mark.parametrize('command', [\n    Command('yarn install redux', output('redux')),\n    Command('yarn install moment', output('moment')),\n    Command('yarn install lodash', output('lodash'))])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command', [\n    Command('yarn install', '')])\ndef test_not_match(command):\n    assert not match(command)\n\n\n@pytest.mark.parametrize('command, new_command', [\n    (Command('yarn install redux', output('redux')),\n     'yarn add redux'),\n    (Command('yarn install moment', output('moment')),\n     'yarn add moment'),\n    (Command('yarn install lodash', output('lodash')),\n     'yarn add lodash')])\ndef test_get_new_command(command, new_command):\n    assert get_new_command(command) == new_command\n"
  },
  {
    "path": "tests/rules/test_yarn_help.py",
    "content": "import pytest\nfrom thefuck.rules.yarn_help import match, get_new_command\nfrom thefuck.types import Command\nfrom thefuck.system import open_command\n\n\noutput_clean = '''\n\n  Usage: yarn [command] [flags]\n\n  Options:\n\n    -h, --help                      output usage information\n    -V, --version                   output the version number\n    --verbose                       output verbose messages on internal operations\n    --offline                       trigger an error if any required dependencies are not available in local cache\n    --prefer-offline                use network only if dependencies are not available in local cache\n    --strict-semver                 \n    --json                          \n    --ignore-scripts                don't run lifecycle scripts\n    --har                           save HAR output of network traffic\n    --ignore-platform               ignore platform checks\n    --ignore-engines                ignore engines check\n    --ignore-optional               ignore optional dependencies\n    --force                         ignore all caches\n    --no-bin-links                  don't generate bin links when setting up packages\n    --flat                          only allow one version of a package\n    --prod, --production [prod]     \n    --no-lockfile                   don't read or generate a lockfile\n    --pure-lockfile                 don't generate a lockfile\n    --frozen-lockfile               don't generate a lockfile and fail if an update is needed\n    --link-duplicates               create hardlinks to the repeated modules in node_modules\n    --global-folder <path>          \n    --modules-folder <path>         rather than installing modules into the node_modules folder relative to the cwd, output them here\n    --cache-folder <path>           specify a custom folder to store the yarn cache\n    --mutex <type>[:specifier]      use a mutex to ensure only one yarn instance is executing\n    --no-emoji                      disable emoji in output\n    --proxy <host>                  \n    --https-proxy <host>            \n    --no-progress                   disable progress bar\n    --network-concurrency <number>  maximum number of concurrent network requests\n\n  Visit https://yarnpkg.com/en/docs/cli/clean for documentation about this command.\n'''  # noqa\n\n\n@pytest.mark.parametrize('command', [\n    Command('yarn help clean', output_clean)])\ndef test_match(command):\n    assert match(command)\n\n\n@pytest.mark.parametrize('command, url', [\n    (Command('yarn help clean', output_clean),\n     'https://yarnpkg.com/en/docs/cli/clean')])\ndef test_get_new_command(command, url):\n    assert get_new_command(command) == open_command(url)\n"
  },
  {
    "path": "tests/rules/test_yum_invalid_operation.py",
    "content": "from io import BytesIO\n\nimport pytest\n\nfrom thefuck.rules.yum_invalid_operation import match, get_new_command, _get_operations\nfrom thefuck.types import Command\n\nyum_help_text = '''Loaded plugins: extras_suggestions, langpacks, priorities, update-motd\nUsage: yum [options] COMMAND\n\nList of Commands:\n\ncheck          Check for problems in the rpmdb\ncheck-update   Check for available package updates\nclean          Remove cached data\ndeplist        List a package's dependencies\ndistribution-synchronization Synchronize installed packages to the latest available versions\ndowngrade      downgrade a package\nerase          Remove a package or packages from your system\nfs             Acts on the filesystem data of the host, mainly for removing docs/lanuages for minimal hosts.\nfssnapshot     Creates filesystem snapshots, or lists/deletes current snapshots.\ngroups         Display, or use, the groups information\nhelp           Display a helpful usage message\nhistory        Display, or use, the transaction history\ninfo           Display details about a package or group of packages\ninstall        Install a package or packages on your system\nlangavailable  Check available languages\nlanginfo       List languages information\nlanginstall    Install appropriate language packs for a language\nlanglist       List installed languages\nlangremove     Remove installed language packs for a language\nlist           List a package or groups of packages\nload-transaction load a saved transaction from filename\nmakecache      Generate the metadata cache\nprovides       Find what package provides the given value\nreinstall      reinstall a package\nrepo-pkgs      Treat a repo. as a group of packages, so we can install/remove all of them\nrepolist       Display the configured software repositories\nsearch         Search package details for the given string\nshell          Run an interactive yum shell\nswap           Simple way to swap packages, instead of using shell\nupdate         Update a package or packages on your system\nupdate-minimal Works like upgrade, but goes to the 'newest' package match which fixes a problem that affects your system\nupdateinfo     Acts on repository update information\nupgrade        Update packages taking obsoletes into account\nversion        Display a version for the machine and/or available repos.\n\n\nOptions:\n  -h, --help            show this help message and exit\n  -t, --tolerant        be tolerant of errors\n  -C, --cacheonly       run entirely from system cache, don't update cache\n  -c [config file], --config=[config file]\n                        config file location\n  -R [minutes], --randomwait=[minutes]\n                        maximum command wait time\n  -d [debug level], --debuglevel=[debug level]\n                        debugging output level\n  --showduplicates      show duplicates, in repos, in list/search commands\n  -e [error level], --errorlevel=[error level]\n                        error output level\n  --rpmverbosity=[debug level name]\n                        debugging output level for rpm\n  -q, --quiet           quiet operation\n  -v, --verbose         verbose operation\n  -y, --assumeyes       answer yes for all questions\n  --assumeno            answer no for all questions\n  --version             show Yum version and exit\n  --installroot=[path]  set install root\n  --enablerepo=[repo]   enable one or more repositories (wildcards allowed)\n  --disablerepo=[repo]  disable one or more repositories (wildcards allowed)\n  -x [package], --exclude=[package]\n                        exclude package(s) by name or glob\n  --disableexcludes=[repo]\n                        disable exclude from main, for a repo or for\n                        everything\n  --disableincludes=[repo]\n                        disable includepkgs for a repo or for everything\n  --obsoletes           enable obsoletes processing during updates\n  --noplugins           disable Yum plugins\n  --nogpgcheck          disable gpg signature checking\n  --disableplugin=[plugin]\n                        disable plugins by name\n  --enableplugin=[plugin]\n                        enable plugins by name\n  --skip-broken         skip packages with depsolving problems\n  --color=COLOR         control whether color is used\n  --releasever=RELEASEVER\n                        set value of $releasever in yum config and repo files\n  --downloadonly        don't update, just download\n  --downloaddir=DLDIR   specifies an alternate directory to store packages\n  --setopt=SETOPTS      set arbitrary config and repo options\n  --bugfix              Include bugfix relevant packages, in updates\n  --security            Include security relevant packages, in updates\n  --advisory=ADVS, --advisories=ADVS\n                        Include packages needed to fix the given advisory, in\n                        updates\n  --bzs=BZS             Include packages needed to fix the given BZ, in\n                        updates\n  --cves=CVES           Include packages needed to fix the given CVE, in\n                        updates\n  --sec-severity=SEVS, --secseverity=SEVS\n                        Include security relevant packages matching the\n                        severity, in updates\n\n  Plugin Options:\n    --samearch-priorities\n                        Priority-exclude packages based on name + arch\n'''\nyum_unsuccessful_search_text = '''Warning: No matches found for: {}\nNo matches found\n'''\nyum_successful_vim_search_text = '''================================================== N/S matched: vim ===================================================\nprotobuf-vim.x86_64 : Vim syntax highlighting for Google Protocol Buffers descriptions\nvim-X11.x86_64 : The VIM version of the vi editor for the X Window System - GVim\nvim-common.x86_64 : The common files needed by any version of the VIM editor\nvim-enhanced.x86_64 : A version of the VIM editor which includes recent enhancements\nvim-filesystem.x86_64 : VIM filesystem layout\nvim-filesystem.noarch : VIM filesystem layout\nvim-minimal.x86_64 : A minimal version of the VIM editor\n\n  Name and summary matches only, use \"search all\" for everything.\n'''\n\nyum_invalid_op_text = '''Loaded plugins: extras_suggestions, langpacks, priorities, update-motd\nNo such command: {}. Please use /usr/bin/yum --help\n'''\n\nyum_operations = [\n    'check', 'check-update', 'clean', 'deplist', 'distribution-synchronization', 'downgrade', 'erase', 'fs',\n    'fssnapshot', 'groups', 'help', 'history', 'info', 'install', 'langavailable', 'langinfo', 'langinstall',\n    'langlist', 'langremove', 'list', 'load-transaction', 'makecache', 'provides', 'reinstall', 'repo-pkgs', 'repolist',\n    'search', 'shell', 'swap', 'update', 'update-minimal', 'updateinfo', 'upgrade', 'version', ]\n\n\n@pytest.mark.parametrize('command', [\n    'saerch', 'uninstall',\n])\ndef test_match(command):\n    assert match(Command('yum {}'.format(command), yum_invalid_op_text.format(command)))\n\n\n@pytest.mark.parametrize('command, output', [\n    ('vim', ''),\n    ('yum', yum_help_text,),\n    ('yum help', yum_help_text,),\n    ('yum search asdf', yum_unsuccessful_search_text.format('asdf'),),\n    ('yum search vim', yum_successful_vim_search_text)\n])\ndef test_not_match(command, output):\n    assert not match(Command(command, output))\n\n\n@pytest.fixture\ndef yum_help(mocker):\n    mock = mocker.patch('subprocess.Popen')\n    mock.return_value.stdout = BytesIO(bytes(yum_help_text.encode('utf-8')))\n    return mock\n\n\n@pytest.mark.usefixtures('no_memoize', 'yum_help')\ndef test_get_operations():\n    assert _get_operations() == yum_operations\n\n\n@pytest.mark.usefixtures('no_memoize', 'yum_help')\n@pytest.mark.parametrize('script, output, result', [\n    ('yum uninstall', yum_invalid_op_text.format('uninstall'), 'yum remove',),\n    ('yum saerch asdf', yum_invalid_op_text.format('saerch'), 'yum search asdf',),\n    ('yum hlep', yum_invalid_op_text.format('hlep'), 'yum help',),\n])\ndef test_get_new_command(script, output, result):\n    assert get_new_command(Command(script, output))[0] == result\n"
  },
  {
    "path": "tests/shells/__init__.py",
    "content": ""
  },
  {
    "path": "tests/shells/conftest.py",
    "content": "import pytest\n\n\n@pytest.fixture\ndef builtins_open(mocker):\n    return mocker.patch('six.moves.builtins.open')\n\n\n@pytest.fixture\ndef isfile(mocker):\n    return mocker.patch('os.path.isfile', return_value=True)\n\n\n@pytest.fixture\n@pytest.mark.usefixtures('isfile')\ndef history_lines(mocker):\n    def aux(lines):\n        mock = mocker.patch('io.open')\n        mock.return_value.__enter__ \\\n            .return_value.readlines.return_value = lines\n\n    return aux\n\n\n@pytest.fixture\ndef config_exists(mocker):\n    path_mock = mocker.patch('thefuck.shells.generic.Path')\n    return path_mock.return_value \\\n        .expanduser.return_value \\\n        .exists\n"
  },
  {
    "path": "tests/shells/test_bash.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport os\nimport pytest\nfrom thefuck.shells import Bash\n\n\n@pytest.mark.usefixtures('isfile', 'no_memoize', 'no_cache')\nclass TestBash(object):\n    @pytest.fixture\n    def shell(self):\n        return Bash()\n\n    @pytest.fixture(autouse=True)\n    def Popen(self, mocker):\n        mock = mocker.patch('thefuck.shells.bash.Popen')\n        return mock\n\n    @pytest.fixture(autouse=True)\n    def shell_aliases(self):\n        os.environ['TF_SHELL_ALIASES'] = (\n            'alias fuck=\\'eval $(thefuck $(fc -ln -1))\\'\\n'\n            'alias l=\\'ls -CF\\'\\n'\n            'alias la=\\'ls -A\\'\\n'\n            'alias ll=\\'ls -alF\\'')\n\n    @pytest.mark.parametrize('before, after', [\n        ('pwd', 'pwd'),\n        ('fuck', 'eval $(thefuck $(fc -ln -1))'),\n        ('awk', 'awk'),\n        ('ll', 'ls -alF')])\n    def test_from_shell(self, before, after, shell):\n        assert shell.from_shell(before) == after\n\n    def test_to_shell(self, shell):\n        assert shell.to_shell('pwd') == 'pwd'\n\n    def test_and_(self, shell):\n        assert shell.and_('ls', 'cd') == 'ls && cd'\n\n    def test_or_(self, shell):\n        assert shell.or_('ls', 'cd') == 'ls || cd'\n\n    def test_get_aliases(self, shell):\n        assert shell.get_aliases() == {'fuck': 'eval $(thefuck $(fc -ln -1))',\n                                       'l': 'ls -CF',\n                                       'la': 'ls -A',\n                                       'll': 'ls -alF'}\n\n    def test_app_alias(self, shell):\n        assert 'fuck () {' in shell.app_alias('fuck')\n        assert 'FUCK () {' in shell.app_alias('FUCK')\n        assert 'thefuck' in shell.app_alias('fuck')\n        assert 'PYTHONIOENCODING' in shell.app_alias('fuck')\n\n    def test_app_alias_variables_correctly_set(self, shell):\n        alias = shell.app_alias('fuck')\n        assert \"fuck () {\" in alias\n        assert 'TF_SHELL=bash' in alias\n        assert \"TF_ALIAS=fuck\" in alias\n        assert 'PYTHONIOENCODING=utf-8' in alias\n        assert 'TF_SHELL_ALIASES=$(alias)' in alias\n\n    def test_get_history(self, history_lines, shell):\n        history_lines(['ls', 'rm'])\n        assert list(shell.get_history()) == ['ls', 'rm']\n\n    def test_split_command(self, shell):\n        command = 'git log -p'\n        command_parts = ['git', 'log', '-p']\n        assert shell.split_command(command) == command_parts\n\n    def test_how_to_configure(self, shell, config_exists):\n        config_exists.return_value = True\n        assert shell.how_to_configure().can_configure_automatically\n\n    def test_how_to_configure_when_config_not_found(self, shell,\n                                                    config_exists):\n        config_exists.return_value = False\n        assert not shell.how_to_configure().can_configure_automatically\n\n    def test_info(self, shell, Popen):\n        Popen.return_value.stdout.read.side_effect = [b'3.5.9']\n        assert shell.info() == 'Bash 3.5.9'\n\n    def test_get_version_error(self, shell, Popen):\n        Popen.return_value.stdout.read.side_effect = OSError\n        with pytest.raises(OSError):\n            shell._get_version()\n        assert Popen.call_args[0][0] == ['bash', '-c', 'echo $BASH_VERSION']\n"
  },
  {
    "path": "tests/shells/test_fish.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport pytest\nfrom thefuck.const import ARGUMENT_PLACEHOLDER\nfrom thefuck.shells import Fish\n\n\n@pytest.mark.usefixtures('isfile', 'no_memoize', 'no_cache')\nclass TestFish(object):\n    @pytest.fixture\n    def shell(self):\n        return Fish()\n\n    @pytest.fixture(autouse=True)\n    def Popen(self, mocker):\n        mock = mocker.patch('thefuck.shells.fish.Popen')\n        mock.return_value.stdout.read.side_effect = [(\n            b'cd\\nfish_config\\nfuck\\nfunced\\nfuncsave\\ngrep\\nhistory\\nll\\nls\\n'\n            b'man\\nmath\\npopd\\npushd\\nruby'),\n            (b'alias fish_key_reader /usr/bin/fish_key_reader\\nalias g git\\n'\n             b'alias alias_with_equal_sign=echo\\ninvalid_alias'), b'func1\\nfunc2', b'']\n        return mock\n\n    @pytest.mark.parametrize('key, value', [\n        ('TF_OVERRIDDEN_ALIASES', 'cut,git,sed'),  # legacy\n        ('THEFUCK_OVERRIDDEN_ALIASES', 'cut,git,sed'),\n        ('THEFUCK_OVERRIDDEN_ALIASES', 'cut, git, sed'),\n        ('THEFUCK_OVERRIDDEN_ALIASES', ' cut,\\tgit,sed\\n'),\n        ('THEFUCK_OVERRIDDEN_ALIASES', '\\ncut,\\n\\ngit,\\tsed\\r')])\n    def test_get_overridden_aliases(self, shell, os_environ, key, value):\n        os_environ[key] = value\n        overridden = shell._get_overridden_aliases()\n        assert set(overridden) == {'cd', 'cut', 'git', 'grep',\n                                   'ls', 'man', 'open', 'sed'}\n\n    @pytest.mark.parametrize('before, after', [\n        ('cd', 'cd'),\n        ('pwd', 'pwd'),\n        ('fuck', 'fish -ic \"fuck\"'),\n        ('find', 'find'),\n        ('funced', 'fish -ic \"funced\"'),\n        ('grep', 'grep'),\n        ('awk', 'awk'),\n        ('math \"2 + 2\"', r'fish -ic \"math \\\"2 + 2\\\"\"'),\n        ('man', 'man'),\n        ('open', 'open'),\n        ('vim', 'vim'),\n        ('ll', 'fish -ic \"ll\"'),\n        ('ls', 'ls'),\n        ('g', 'git')])\n    def test_from_shell(self, before, after, shell):\n        assert shell.from_shell(before) == after\n\n    def test_to_shell(self, shell):\n        assert shell.to_shell('pwd') == 'pwd'\n\n    def test_and_(self, shell):\n        assert shell.and_('foo', 'bar') == 'foo; and bar'\n\n    def test_or_(self, shell):\n        assert shell.or_('foo', 'bar') == 'foo; or bar'\n\n    def test_get_aliases(self, shell):\n        assert shell.get_aliases() == {'fish_config': 'fish_config',\n                                       'fuck': 'fuck',\n                                       'funced': 'funced',\n                                       'funcsave': 'funcsave',\n                                       'history': 'history',\n                                       'll': 'll',\n                                       'math': 'math',\n                                       'popd': 'popd',\n                                       'pushd': 'pushd',\n                                       'ruby': 'ruby',\n                                       'g': 'git',\n                                       'fish_key_reader': '/usr/bin/fish_key_reader',\n                                       'alias_with_equal_sign': 'echo'}\n        assert shell.get_aliases() == {'func1': 'func1', 'func2': 'func2'}\n\n    def test_app_alias(self, shell):\n        assert 'function fuck' in shell.app_alias('fuck')\n        assert 'function FUCK' in shell.app_alias('FUCK')\n        assert 'thefuck' in shell.app_alias('fuck')\n        assert 'TF_SHELL=fish' in shell.app_alias('fuck')\n        assert 'TF_ALIAS=fuck PYTHONIOENCODING' in shell.app_alias('fuck')\n        assert 'PYTHONIOENCODING=utf-8 thefuck' in shell.app_alias('fuck')\n        assert ARGUMENT_PLACEHOLDER in shell.app_alias('fuck')\n\n    def test_app_alias_alter_history(self, settings, shell):\n        settings.alter_history = True\n        assert (\n            'builtin history delete --exact --case-sensitive -- $fucked_up_command\\n'\n            in shell.app_alias('FUCK')\n        )\n        assert 'builtin history merge\\n' in shell.app_alias('FUCK')\n        settings.alter_history = False\n        assert 'builtin history delete' not in shell.app_alias('FUCK')\n        assert 'builtin history merge' not in shell.app_alias('FUCK')\n\n    def test_get_history(self, history_lines, shell):\n        history_lines(['- cmd: ls', '  when: 1432613911',\n                       '- cmd: rm', '  when: 1432613916'])\n        assert list(shell.get_history()) == ['ls', 'rm']\n\n    @pytest.mark.parametrize('entry, entry_utf8', [\n        ('ls', '- cmd: ls\\n   when: 1430707243\\n'),\n        (u'echo café', '- cmd: echo café\\n   when: 1430707243\\n')])\n    def test_put_to_history(self, entry, entry_utf8, builtins_open, mocker, shell):\n        mocker.patch('thefuck.shells.fish.time', return_value=1430707243.3517463)\n        shell.put_to_history(entry)\n        builtins_open.return_value.__enter__.return_value. \\\n            write.assert_called_once_with(entry_utf8)\n\n    def test_how_to_configure(self, shell, config_exists):\n        config_exists.return_value = True\n        assert shell.how_to_configure().can_configure_automatically\n\n    def test_how_to_configure_when_config_not_found(self, shell,\n                                                    config_exists):\n        config_exists.return_value = False\n        assert not shell.how_to_configure().can_configure_automatically\n\n    def test_get_version(self, shell, Popen):\n        Popen.return_value.stdout.read.side_effect = [b'fish, version 3.5.9\\n']\n        assert shell._get_version() == '3.5.9'\n        assert Popen.call_args[0][0] == ['fish', '--version']\n\n    @pytest.mark.parametrize('side_effect, exception', [\n        ([b'\\n'], IndexError),\n        (OSError('file not found'), OSError),\n    ])\n    def test_get_version_error(self, side_effect, exception, shell, Popen):\n        Popen.return_value.stdout.read.side_effect = side_effect\n        with pytest.raises(exception):\n            shell._get_version()\n        assert Popen.call_args[0][0] == ['fish', '--version']\n"
  },
  {
    "path": "tests/shells/test_generic.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport pytest\nfrom thefuck.shells import Generic\n\n\nclass TestGeneric(object):\n    @pytest.fixture\n    def shell(self):\n        return Generic()\n\n    def test_from_shell(self, shell):\n        assert shell.from_shell('pwd') == 'pwd'\n\n    def test_to_shell(self, shell):\n        assert shell.to_shell('pwd') == 'pwd'\n\n    def test_and_(self, shell):\n        assert shell.and_('ls', 'cd') == 'ls && cd'\n\n    def test_or_(self, shell):\n        assert shell.or_('ls', 'cd') == 'ls || cd'\n\n    def test_get_aliases(self, shell):\n        assert shell.get_aliases() == {}\n\n    def test_app_alias(self, shell):\n        assert 'alias fuck' in shell.app_alias('fuck')\n        assert 'alias FUCK' in shell.app_alias('FUCK')\n        assert 'thefuck' in shell.app_alias('fuck')\n        assert 'TF_ALIAS=fuck PYTHONIOENCODING' in shell.app_alias('fuck')\n        assert 'PYTHONIOENCODING=utf-8 thefuck' in shell.app_alias('fuck')\n\n    def test_get_history(self, history_lines, shell):\n        history_lines(['ls', 'rm'])\n        # We don't know what to do in generic shell with history lines,\n        # so just ignore them:\n        assert list(shell.get_history()) == []\n\n    def test_split_command(self, shell):\n        assert shell.split_command('ls') == ['ls']\n        assert shell.split_command(u'echo café') == [u'echo', u'café']\n\n    def test_how_to_configure(self, shell):\n        assert shell.how_to_configure() is None\n\n    @pytest.mark.parametrize('side_effect, expected_info, warn', [\n        ([u'3.5.9'], u'Generic Shell 3.5.9', False),\n        ([OSError], u'Generic Shell', True),\n    ])\n    def test_info(self, side_effect, expected_info, warn, shell, mocker):\n        warn_mock = mocker.patch('thefuck.shells.generic.warn')\n        shell._get_version = mocker.Mock(side_effect=side_effect)\n        assert shell.info() == expected_info\n        assert warn_mock.called is warn\n        assert shell._get_version.called\n"
  },
  {
    "path": "tests/shells/test_powershell.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport pytest\nfrom thefuck.shells import Powershell\n\n\n@pytest.mark.usefixtures('isfile', 'no_memoize', 'no_cache')\nclass TestPowershell(object):\n    @pytest.fixture\n    def shell(self):\n        return Powershell()\n\n    @pytest.fixture(autouse=True)\n    def Popen(self, mocker):\n        mock = mocker.patch('thefuck.shells.powershell.Popen')\n        return mock\n\n    def test_and_(self, shell):\n        assert shell.and_('ls', 'cd') == '(ls) -and (cd)'\n\n    def test_app_alias(self, shell):\n        assert 'function fuck' in shell.app_alias('fuck')\n        assert 'function FUCK' in shell.app_alias('FUCK')\n        assert 'thefuck' in shell.app_alias('fuck')\n\n    def test_how_to_configure(self, shell):\n        assert not shell.how_to_configure().can_configure_automatically\n\n    @pytest.mark.parametrize('side_effect, expected_version, call_args', [\n        ([b'''Major  Minor  Build  Revision\n-----  -----  -----  --------\n5      1      17763  316     \\n'''], 'PowerShell 5.1.17763.316', ['powershell.exe']),\n        ([IOError, b'PowerShell 6.1.2\\n'], 'PowerShell 6.1.2', ['powershell.exe', 'pwsh'])])\n    def test_info(self, side_effect, expected_version, call_args, shell, Popen):\n        Popen.return_value.stdout.read.side_effect = side_effect\n        assert shell.info() == expected_version\n        assert Popen.call_count == len(call_args)\n        assert all([Popen.call_args_list[i][0][0][0] == call_arg for i, call_arg in enumerate(call_args)])\n\n    def test_get_version_error(self, shell, Popen):\n        Popen.return_value.stdout.read.side_effect = RuntimeError\n        with pytest.raises(RuntimeError):\n            shell._get_version()\n        assert Popen.call_args[0][0] == ['powershell.exe', '$PSVersionTable.PSVersion']\n"
  },
  {
    "path": "tests/shells/test_tcsh.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport pytest\nfrom thefuck.shells.tcsh import Tcsh\n\n\n@pytest.mark.usefixtures('isfile', 'no_memoize', 'no_cache')\nclass TestTcsh(object):\n    @pytest.fixture\n    def shell(self):\n        return Tcsh()\n\n    @pytest.fixture(autouse=True)\n    def Popen(self, mocker):\n        mock = mocker.patch('thefuck.shells.tcsh.Popen')\n        mock.return_value.stdout.read.return_value = (\n            b'fuck\\teval $(thefuck $(fc -ln -1))\\n'\n            b'l\\tls -CF\\n'\n            b'la\\tls -A\\n'\n            b'll\\tls -alF')\n        return mock\n\n    @pytest.mark.parametrize('before, after', [\n        ('pwd', 'pwd'),\n        ('fuck', 'eval $(thefuck $(fc -ln -1))'),\n        ('awk', 'awk'),\n        ('ll', 'ls -alF')])\n    def test_from_shell(self, before, after, shell):\n        assert shell.from_shell(before) == after\n\n    def test_to_shell(self, shell):\n        assert shell.to_shell('pwd') == 'pwd'\n\n    def test_and_(self, shell):\n        assert shell.and_('ls', 'cd') == 'ls && cd'\n\n    def test_or_(self, shell):\n        assert shell.or_('ls', 'cd') == 'ls || cd'\n\n    def test_get_aliases(self, shell):\n        assert shell.get_aliases() == {'fuck': 'eval $(thefuck $(fc -ln -1))',\n                                       'l': 'ls -CF',\n                                       'la': 'ls -A',\n                                       'll': 'ls -alF'}\n\n    def test_app_alias(self, shell):\n        assert 'setenv TF_SHELL tcsh' in shell.app_alias('fuck')\n        assert 'alias fuck' in shell.app_alias('fuck')\n        assert 'alias FUCK' in shell.app_alias('FUCK')\n        assert 'thefuck' in shell.app_alias('fuck')\n\n    def test_get_history(self, history_lines, shell):\n        history_lines(['ls', 'rm'])\n        assert list(shell.get_history()) == ['ls', 'rm']\n\n    def test_how_to_configure(self, shell, config_exists):\n        config_exists.return_value = True\n        assert shell.how_to_configure().can_configure_automatically\n\n    def test_how_to_configure_when_config_not_found(self, shell,\n                                                    config_exists):\n        config_exists.return_value = False\n        assert not shell.how_to_configure().can_configure_automatically\n\n    def test_info(self, shell, Popen):\n        Popen.return_value.stdout.read.side_effect = [\n            b'tcsh 6.20.00 (Astron) 2016-11-24 (unknown-unknown-bsd44) \\n']\n        assert shell.info() == 'Tcsh 6.20.00'\n        assert Popen.call_args[0][0] == ['tcsh', '--version']\n\n    @pytest.mark.parametrize('side_effect, exception', [\n        ([b'\\n'], IndexError), (OSError, OSError)])\n    def test_get_version_error(self, side_effect, exception, shell, Popen):\n        Popen.return_value.stdout.read.side_effect = side_effect\n        with pytest.raises(exception):\n            shell._get_version()\n        assert Popen.call_args[0][0] == ['tcsh', '--version']\n"
  },
  {
    "path": "tests/shells/test_zsh.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport os\nimport pytest\nfrom thefuck.shells.zsh import Zsh\n\n\n@pytest.mark.usefixtures('isfile', 'no_memoize', 'no_cache')\nclass TestZsh(object):\n    @pytest.fixture\n    def shell(self):\n        return Zsh()\n\n    @pytest.fixture(autouse=True)\n    def Popen(self, mocker):\n        mock = mocker.patch('thefuck.shells.zsh.Popen')\n        return mock\n\n    @pytest.fixture(autouse=True)\n    def shell_aliases(self):\n        os.environ['TF_SHELL_ALIASES'] = (\n            'fuck=\\'eval $(thefuck $(fc -ln -1 | tail -n 1))\\'\\n'\n            'l=\\'ls -CF\\'\\n'\n            'la=\\'ls -A\\'\\n'\n            'll=\\'ls -alF\\'')\n\n    @pytest.mark.parametrize('before, after', [\n        ('fuck', 'eval $(thefuck $(fc -ln -1 | tail -n 1))'),\n        ('pwd', 'pwd'),\n        ('ll', 'ls -alF')])\n    def test_from_shell(self, before, after, shell):\n        assert shell.from_shell(before) == after\n\n    def test_to_shell(self, shell):\n        assert shell.to_shell('pwd') == 'pwd'\n\n    def test_and_(self, shell):\n        assert shell.and_('ls', 'cd') == 'ls && cd'\n\n    def test_or_(self, shell):\n        assert shell.or_('ls', 'cd') == 'ls || cd'\n\n    def test_get_aliases(self, shell):\n        assert shell.get_aliases() == {\n            'fuck': 'eval $(thefuck $(fc -ln -1 | tail -n 1))',\n            'l': 'ls -CF',\n            'la': 'ls -A',\n            'll': 'ls -alF'}\n\n    def test_app_alias(self, shell):\n        assert 'fuck () {' in shell.app_alias('fuck')\n        assert 'FUCK () {' in shell.app_alias('FUCK')\n        assert 'thefuck' in shell.app_alias('fuck')\n        assert 'PYTHONIOENCODING' in shell.app_alias('fuck')\n\n    def test_app_alias_variables_correctly_set(self, shell):\n        alias = shell.app_alias('fuck')\n        assert \"fuck () {\" in alias\n        assert 'TF_SHELL=zsh' in alias\n        assert \"TF_ALIAS=fuck\" in alias\n        assert 'PYTHONIOENCODING=utf-8' in alias\n        assert 'TF_SHELL_ALIASES=$(alias)' in alias\n\n    def test_get_history(self, history_lines, shell):\n        history_lines([': 1432613911:0;ls', ': 1432613916:0;rm'])\n        assert list(shell.get_history()) == ['ls', 'rm']\n\n    def test_how_to_configure(self, shell, config_exists):\n        config_exists.return_value = True\n        assert shell.how_to_configure().can_configure_automatically\n\n    def test_how_to_configure_when_config_not_found(self, shell,\n                                                    config_exists):\n        config_exists.return_value = False\n        assert not shell.how_to_configure().can_configure_automatically\n\n    def test_info(self, shell, Popen):\n        Popen.return_value.stdout.read.side_effect = [b'3.5.9']\n        assert shell.info() == 'ZSH 3.5.9'\n\n    def test_get_version_error(self, shell, Popen):\n        Popen.return_value.stdout.read.side_effect = OSError\n        with pytest.raises(OSError):\n            shell._get_version()\n        assert Popen.call_args[0][0] == ['zsh', '-c', 'echo $ZSH_VERSION']\n"
  },
  {
    "path": "tests/specific/__init__.py",
    "content": ""
  },
  {
    "path": "tests/specific/test_git.py",
    "content": "import pytest\nfrom thefuck.specific.git import git_support\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('called, command, output', [\n    ('git co', 'git checkout', \"19:22:36.299340 git.c:282   trace: alias expansion: co => 'checkout'\"),\n    ('git com file', 'git commit --verbose file',\n     \"19:23:25.470911 git.c:282   trace: alias expansion: com => 'commit' '--verbose'\"),\n    ('git com -m \"Initial commit\"', 'git commit -m \"Initial commit\"',\n     \"19:22:36.299340 git.c:282   trace: alias expansion: com => 'commit'\"),\n    ('git br -d some_branch', 'git branch -d some_branch',\n     \"19:22:36.299340 git.c:282   trace: alias expansion: br => 'branch'\")])\ndef test_git_support(called, command, output):\n    @git_support\n    def fn(command):\n        return command.script\n\n    assert fn(Command(called, output)) == command\n\n\n@pytest.mark.parametrize('command, is_git', [\n    ('git pull', True),\n    ('hub pull', True),\n    ('git push --set-upstream origin foo', True),\n    ('hub push --set-upstream origin foo', True),\n    ('ls', False),\n    ('cat git', False),\n    ('cat hub', False)])\n@pytest.mark.parametrize('output', ['', None])\ndef test_git_support_match(command, is_git, output):\n    @git_support\n    def fn(command):\n        return True\n\n    assert fn(Command(command, output)) == is_git\n"
  },
  {
    "path": "tests/specific/test_npm.py",
    "content": "from io import BytesIO\n\nimport pytest\nfrom thefuck.specific.npm import get_scripts\n\nrun_script_stdout = b'''\nLifecycle scripts included in code-view-web:\n  test\n    jest\n\navailable via `npm run-script`:\n  build\n    cp node_modules/ace-builds/src-min/ -a resources/ace/ && webpack --progress --colors -p --config ./webpack.production.config.js\n  develop\n    cp node_modules/ace-builds/src/ -a resources/ace/ && webpack-dev-server --progress --colors\n  watch-test\n    jest --verbose --watch\n\n'''\n\n\n@pytest.mark.usefixtures('no_memoize')\ndef test_get_scripts(mocker):\n    patch = mocker.patch('thefuck.specific.npm.Popen')\n    patch.return_value.stdout = BytesIO(run_script_stdout)\n    assert get_scripts() == ['build', 'develop', 'watch-test']\n"
  },
  {
    "path": "tests/specific/test_sudo.py",
    "content": "import pytest\nfrom thefuck.specific.sudo import sudo_support\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('return_value, command, called, result', [\n    ('ls -lah', 'sudo ls', 'ls', 'sudo ls -lah'),\n    ('ls -lah', 'ls', 'ls', 'ls -lah'),\n    (['ls -lah'], 'sudo ls', 'ls', ['sudo ls -lah']),\n    (True, 'sudo ls', 'ls', True),\n    (True, 'ls', 'ls', True),\n    (False, 'sudo ls', 'ls', False),\n    (False, 'ls', 'ls', False)])\ndef test_sudo_support(return_value, command, called, result):\n    def fn(command):\n        assert command == Command(called, '')\n        return return_value\n\n    assert sudo_support(fn)(Command(command, '')) == result\n"
  },
  {
    "path": "tests/test_argument_parser.py",
    "content": "import pytest\nfrom thefuck.argument_parser import Parser\nfrom thefuck.const import ARGUMENT_PLACEHOLDER\n\n\ndef _args(**override):\n    args = {'alias': None, 'command': [], 'yes': False,\n            'help': False, 'version': False, 'debug': False,\n            'force_command': None, 'repeat': False,\n            'enable_experimental_instant_mode': False,\n            'shell_logger': None}\n    args.update(override)\n    return args\n\n\n@pytest.mark.parametrize('argv, result', [\n    (['thefuck'], _args()),\n    (['thefuck', '-a'], _args(alias='fuck')),\n    (['thefuck', '--alias', '--enable-experimental-instant-mode'],\n     _args(alias='fuck', enable_experimental_instant_mode=True)),\n    (['thefuck', '-a', 'fix'], _args(alias='fix')),\n    (['thefuck', 'git', 'branch', ARGUMENT_PLACEHOLDER, '-y'],\n     _args(command=['git', 'branch'], yes=True)),\n    (['thefuck', 'git', 'branch', '-a', ARGUMENT_PLACEHOLDER, '-y'],\n     _args(command=['git', 'branch', '-a'], yes=True)),\n    (['thefuck', ARGUMENT_PLACEHOLDER, '-v'], _args(version=True)),\n    (['thefuck', ARGUMENT_PLACEHOLDER, '--help'], _args(help=True)),\n    (['thefuck', 'git', 'branch', '-a', ARGUMENT_PLACEHOLDER, '-y', '-d'],\n     _args(command=['git', 'branch', '-a'], yes=True, debug=True)),\n    (['thefuck', 'git', 'branch', '-a', ARGUMENT_PLACEHOLDER, '-r', '-d'],\n     _args(command=['git', 'branch', '-a'], repeat=True, debug=True)),\n    (['thefuck', '-l', '/tmp/log'], _args(shell_logger='/tmp/log')),\n    (['thefuck', '--shell-logger', '/tmp/log'],\n     _args(shell_logger='/tmp/log'))])\ndef test_parse(argv, result):\n    assert vars(Parser().parse(argv)) == result\n"
  },
  {
    "path": "tests/test_conf.py",
    "content": "import pytest\nimport six\nimport os\nfrom mock import Mock\nfrom thefuck import const\n\n\n@pytest.fixture\ndef load_source(mocker):\n    return mocker.patch('thefuck.conf.load_source')\n\n\ndef test_settings_defaults(load_source, settings):\n    load_source.return_value = object()\n    settings.init()\n    for key, val in const.DEFAULT_SETTINGS.items():\n        assert getattr(settings, key) == val\n\n\nclass TestSettingsFromFile(object):\n    def test_from_file(self, load_source, settings):\n        load_source.return_value = Mock(rules=['test'],\n                                        wait_command=10,\n                                        require_confirmation=True,\n                                        no_colors=True,\n                                        priority={'vim': 100},\n                                        exclude_rules=['git'])\n        settings.init()\n        assert settings.rules == ['test']\n        assert settings.wait_command == 10\n        assert settings.require_confirmation is True\n        assert settings.no_colors is True\n        assert settings.priority == {'vim': 100}\n        assert settings.exclude_rules == ['git']\n\n    def test_from_file_with_DEFAULT(self, load_source, settings):\n        load_source.return_value = Mock(rules=const.DEFAULT_RULES + ['test'],\n                                        wait_command=10,\n                                        exclude_rules=[],\n                                        require_confirmation=True,\n                                        no_colors=True)\n        settings.init()\n        assert settings.rules == const.DEFAULT_RULES + ['test']\n\n\n@pytest.mark.usefixtures('load_source')\nclass TestSettingsFromEnv(object):\n    def test_from_env(self, os_environ, settings):\n        os_environ.update({'THEFUCK_RULES': 'bash:lisp',\n                           'THEFUCK_EXCLUDE_RULES': 'git:vim',\n                           'THEFUCK_WAIT_COMMAND': '55',\n                           'THEFUCK_REQUIRE_CONFIRMATION': 'true',\n                           'THEFUCK_NO_COLORS': 'false',\n                           'THEFUCK_PRIORITY': 'bash=10:lisp=wrong:vim=15',\n                           'THEFUCK_WAIT_SLOW_COMMAND': '999',\n                           'THEFUCK_SLOW_COMMANDS': 'lein:react-native:./gradlew',\n                           'THEFUCK_NUM_CLOSE_MATCHES': '359',\n                           'THEFUCK_EXCLUDED_SEARCH_PATH_PREFIXES': '/media/:/mnt/'})\n        settings.init()\n        assert settings.rules == ['bash', 'lisp']\n        assert settings.exclude_rules == ['git', 'vim']\n        assert settings.wait_command == 55\n        assert settings.require_confirmation is True\n        assert settings.no_colors is False\n        assert settings.priority == {'bash': 10, 'vim': 15}\n        assert settings.wait_slow_command == 999\n        assert settings.slow_commands == ['lein', 'react-native', './gradlew']\n        assert settings.num_close_matches == 359\n        assert settings.excluded_search_path_prefixes == ['/media/', '/mnt/']\n\n    def test_from_env_with_DEFAULT(self, os_environ, settings):\n        os_environ.update({'THEFUCK_RULES': 'DEFAULT_RULES:bash:lisp'})\n        settings.init()\n        assert settings.rules == const.DEFAULT_RULES + ['bash', 'lisp']\n\n\ndef test_settings_from_args(settings):\n    settings.init(Mock(yes=True, debug=True, repeat=True))\n    assert not settings.require_confirmation\n    assert settings.debug\n    assert settings.repeat\n\n\nclass TestInitializeSettingsFile(object):\n    def test_ignore_if_exists(self, settings):\n        settings_path_mock = Mock(is_file=Mock(return_value=True), open=Mock())\n        settings.user_dir = Mock(joinpath=Mock(return_value=settings_path_mock))\n        settings._init_settings_file()\n        assert settings_path_mock.is_file.call_count == 1\n        assert not settings_path_mock.open.called\n\n    def test_create_if_doesnt_exists(self, settings):\n        settings_file = six.StringIO()\n        settings_path_mock = Mock(\n            is_file=Mock(return_value=False),\n            open=Mock(return_value=Mock(\n                __exit__=lambda *args: None, __enter__=lambda *args: settings_file)))\n        settings.user_dir = Mock(joinpath=Mock(return_value=settings_path_mock))\n        settings._init_settings_file()\n        settings_file_contents = settings_file.getvalue()\n        assert settings_path_mock.is_file.call_count == 1\n        assert settings_path_mock.open.call_count == 1\n        assert const.SETTINGS_HEADER in settings_file_contents\n        for setting in const.DEFAULT_SETTINGS.items():\n            assert '# {} = {}\\n'.format(*setting) in settings_file_contents\n        settings_file.close()\n\n\n@pytest.mark.parametrize('legacy_dir_exists, xdg_config_home, result', [\n    (False, '~/.config', '~/.config/thefuck'),\n    (False, '/user/test/config/', '/user/test/config/thefuck'),\n    (True, '~/.config', '~/.thefuck'),\n    (True, '/user/test/config/', '~/.thefuck')])\ndef test_get_user_dir_path(mocker, os_environ, settings, legacy_dir_exists,\n                           xdg_config_home, result):\n    mocker.patch('thefuck.conf.Path.is_dir',\n                 return_value=legacy_dir_exists)\n\n    if xdg_config_home is not None:\n        os_environ['XDG_CONFIG_HOME'] = xdg_config_home\n    else:\n        os_environ.pop('XDG_CONFIG_HOME', None)\n\n    path = settings._get_user_dir_path().as_posix()\n    assert path == os.path.expanduser(result)\n"
  },
  {
    "path": "tests/test_corrector.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport pytest\nfrom tests.utils import Rule, CorrectedCommand\nfrom thefuck import corrector, const\nfrom thefuck.system import Path\nfrom thefuck.types import Command\nfrom thefuck.corrector import get_corrected_commands, organize_commands\n\n\n@pytest.fixture\ndef glob(mocker):\n    results = {}\n    mocker.patch('thefuck.system.Path.glob',\n                 new_callable=lambda: lambda *_: results.pop('value', []))\n    return lambda value: results.update({'value': value})\n\n\nclass TestGetRules(object):\n    @pytest.fixture(autouse=True)\n    def load_source(self, monkeypatch):\n        monkeypatch.setattr('thefuck.types.load_source',\n                            lambda x, _: Rule(x))\n\n    def _compare_names(self, rules, names):\n        assert {r.name for r in rules} == set(names)\n\n    @pytest.mark.parametrize('paths, conf_rules, exclude_rules, loaded_rules', [\n        (['git.py', 'bash.py'], const.DEFAULT_RULES, [], ['git', 'bash']),\n        (['git.py', 'bash.py'], ['git'], [], ['git']),\n        (['git.py', 'bash.py'], const.DEFAULT_RULES, ['git'], ['bash']),\n        (['git.py', 'bash.py'], ['git'], ['git'], [])])\n    def test_get_rules(self, glob, settings, paths, conf_rules, exclude_rules,\n                       loaded_rules):\n        glob([Path(path) for path in paths])\n        settings.update(rules=conf_rules,\n                        priority={},\n                        exclude_rules=exclude_rules)\n        rules = corrector.get_rules()\n        self._compare_names(rules, loaded_rules)\n\n\ndef test_get_rules_rule_exception(mocker, glob):\n    load_source = mocker.patch('thefuck.types.load_source',\n                               side_effect=ImportError(\"No module named foo...\"))\n    glob([Path('git.py')])\n    assert not corrector.get_rules()\n    load_source.assert_called_once_with('git', 'git.py')\n\n\ndef test_get_corrected_commands(mocker):\n    command = Command('test', 'test')\n    rules = [Rule(match=lambda _: False),\n             Rule(match=lambda _: True,\n                  get_new_command=lambda x: x.script + '!', priority=100),\n             Rule(match=lambda _: True,\n                  get_new_command=lambda x: [x.script + '@', x.script + ';'],\n                  priority=60)]\n    mocker.patch('thefuck.corrector.get_rules', return_value=rules)\n    assert ([cmd.script for cmd in get_corrected_commands(command)]\n            == ['test!', 'test@', 'test;'])\n\n\ndef test_organize_commands():\n    \"\"\"Ensures that the function removes duplicates and sorts commands.\"\"\"\n    commands = [CorrectedCommand('ls'), CorrectedCommand('ls -la', priority=9000),\n                CorrectedCommand('ls -lh', priority=100),\n                CorrectedCommand(u'echo café', priority=200),\n                CorrectedCommand('ls -lh', priority=9999)]\n    assert list(organize_commands(iter(commands))) \\\n        == [CorrectedCommand('ls'), CorrectedCommand('ls -lh', priority=100),\n            CorrectedCommand(u'echo café', priority=200),\n            CorrectedCommand('ls -la', priority=9000)]\n"
  },
  {
    "path": "tests/test_logs.py",
    "content": "import pytest\nfrom thefuck import logs\n\n\ndef test_color(settings):\n    settings.no_colors = False\n    assert logs.color('red') == 'red'\n    settings.no_colors = True\n    assert logs.color('red') == ''\n\n\n@pytest.mark.usefixtures('no_colors')\n@pytest.mark.parametrize('debug, stderr', [\n    (True, 'DEBUG: test\\n'),\n    (False, '')])\ndef test_debug(capsys, settings, debug, stderr):\n    settings.debug = debug\n    logs.debug('test')\n    assert capsys.readouterr() == ('', stderr)\n"
  },
  {
    "path": "tests/test_readme.py",
    "content": "def test_readme(source_root):\n    with source_root.joinpath('README.md').open() as f:\n        readme = f.read()\n\n        bundled = source_root.joinpath('thefuck') \\\n                             .joinpath('rules') \\\n                             .glob('*.py')\n\n        for rule in bundled:\n            if rule.stem != '__init__':\n                assert rule.stem in readme, \\\n                    'Missing rule \"{}\" in README.md'.format(rule.stem)\n"
  },
  {
    "path": "tests/test_types.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport os\nfrom subprocess import PIPE, STDOUT\nfrom mock import Mock\nimport pytest\nfrom tests.utils import CorrectedCommand, Rule\nfrom thefuck import const\nfrom thefuck.exceptions import EmptyCommand\nfrom thefuck.system import Path\nfrom thefuck.types import Command\n\n\nclass TestCorrectedCommand(object):\n\n    def test_equality(self):\n        assert (CorrectedCommand('ls', None, 100) ==\n                CorrectedCommand('ls', None, 200))\n        assert (CorrectedCommand('ls', None, 100) !=\n                CorrectedCommand('ls', lambda *_: _, 100))\n\n    def test_hashable(self):\n        assert {CorrectedCommand('ls', None, 100),\n                CorrectedCommand('ls', None, 200)} == {CorrectedCommand('ls')}\n\n    def test_representable(self):\n        assert '{}'.format(CorrectedCommand('ls', None, 100)) == \\\n               'CorrectedCommand(script=ls, side_effect=None, priority=100)'\n        assert u'{}'.format(CorrectedCommand(u'echo café', None, 100)) == \\\n               u'CorrectedCommand(script=echo café, side_effect=None, priority=100)'\n\n    @pytest.mark.parametrize('script, printed, override_settings', [\n        ('git branch', 'git branch', {'repeat': False, 'debug': False}),\n        ('git brunch',\n         \"git brunch || fuck --repeat --force-command 'git brunch'\",\n         {'repeat': True, 'debug': False}),\n        ('git brunch',\n         \"git brunch || fuck --repeat --debug --force-command 'git brunch'\",\n         {'repeat': True, 'debug': True})])\n    def test_run(self, capsys, settings, script, printed, override_settings):\n        settings.update(override_settings)\n        CorrectedCommand(script, None, 1000).run(Command(script, ''))\n        out, _ = capsys.readouterr()\n        assert out == printed\n\n\nclass TestRule(object):\n    def test_from_path_rule_exception(self, mocker):\n        load_source = mocker.patch('thefuck.types.load_source',\n                                   side_effect=ImportError(\"No module named foo...\"))\n        assert Rule.from_path(Path('git.py')) is None\n        load_source.assert_called_once_with('git', 'git.py')\n\n    def test_from_path(self, mocker):\n        match = object()\n        get_new_command = object()\n        load_source = mocker.patch(\n            'thefuck.types.load_source',\n            return_value=Mock(match=match,\n                              get_new_command=get_new_command,\n                              enabled_by_default=True,\n                              priority=900,\n                              requires_output=True))\n        rule_path = os.path.join(os.sep, 'rules', 'bash.py')\n        assert (Rule.from_path(Path(rule_path))\n                == Rule('bash', match, get_new_command, priority=900))\n        load_source.assert_called_once_with('bash', rule_path)\n\n    def test_from_path_excluded_rule(self, mocker, settings):\n        load_source = mocker.patch('thefuck.types.load_source')\n        settings.update(exclude_rules=['git'])\n        rule_path = os.path.join(os.sep, 'rules', 'git.py')\n        assert Rule.from_path(Path(rule_path)) is None\n        assert not load_source.called\n\n    @pytest.mark.parametrize('rules, rule, is_enabled', [\n        (const.DEFAULT_RULES, Rule('git', enabled_by_default=True), True),\n        (const.DEFAULT_RULES, Rule('git', enabled_by_default=False), False),\n        ([], Rule('git', enabled_by_default=False), False),\n        ([], Rule('git', enabled_by_default=True), False),\n        (const.DEFAULT_RULES + ['git'], Rule('git', enabled_by_default=False), True),\n        (['git'], Rule('git', enabled_by_default=False), True)])\n    def test_is_enabled(self, settings, rules, rule, is_enabled):\n        settings.update(rules=rules)\n        assert rule.is_enabled == is_enabled\n\n    def test_isnt_match(self):\n        assert not Rule('', lambda _: False).is_match(\n            Command('ls', ''))\n\n    def test_is_match(self):\n        rule = Rule('', lambda x: x.script == 'cd ..')\n        assert rule.is_match(Command('cd ..', ''))\n\n    @pytest.mark.usefixtures('no_colors')\n    def test_isnt_match_when_rule_failed(self, capsys):\n        rule = Rule('test', Mock(side_effect=OSError('Denied')),\n                    requires_output=False)\n        assert not rule.is_match(Command('ls', ''))\n        assert capsys.readouterr()[1].split('\\n')[0] == '[WARN] Rule test:'\n\n    def test_get_corrected_commands_with_rule_returns_list(self):\n        rule = Rule(get_new_command=lambda x: [x.script + '!', x.script + '@'],\n                    priority=100)\n        assert (list(rule.get_corrected_commands(Command('test', '')))\n                == [CorrectedCommand(script='test!', priority=100),\n                    CorrectedCommand(script='test@', priority=200)])\n\n    def test_get_corrected_commands_with_rule_returns_command(self):\n        rule = Rule(get_new_command=lambda x: x.script + '!',\n                    priority=100)\n        assert (list(rule.get_corrected_commands(Command('test', '')))\n                == [CorrectedCommand(script='test!', priority=100)])\n\n\nclass TestCommand(object):\n    @pytest.fixture(autouse=True)\n    def Popen(self, monkeypatch):\n        Popen = Mock()\n        Popen.return_value.stdout.read.return_value = b'output'\n        monkeypatch.setattr('thefuck.output_readers.rerun.Popen', Popen)\n        return Popen\n\n    @pytest.fixture(autouse=True)\n    def prepare(self, monkeypatch):\n        monkeypatch.setattr('thefuck.output_readers.rerun._wait_output',\n                            lambda *_: True)\n\n    def test_from_script_calls(self, Popen, settings, os_environ):\n        settings.env = {}\n        assert Command.from_raw_script(\n            ['apt-get', 'search', 'vim']) == Command(\n            'apt-get search vim', 'output')\n        Popen.assert_called_once_with('apt-get search vim',\n                                      shell=True,\n                                      stdin=PIPE,\n                                      stdout=PIPE,\n                                      stderr=STDOUT,\n                                      env=os_environ)\n\n    @pytest.mark.parametrize('script, result', [\n        ([], None),\n        ([''], None),\n        (['', ''], None),\n        (['ls', '-la'], 'ls -la'),\n        (['ls'], 'ls'),\n        (['echo \\\\ '], 'echo \\\\ '),\n        (['echo \\\\\\n'], 'echo \\\\\\n')])\n    def test_from_script(self, script, result):\n        if result:\n            assert Command.from_raw_script(script).script == result\n        else:\n            with pytest.raises(EmptyCommand):\n                Command.from_raw_script(script)\n"
  },
  {
    "path": "tests/test_ui.py",
    "content": "# -*- encoding: utf-8 -*-\n\nimport pytest\nfrom itertools import islice\nfrom thefuck import ui\nfrom thefuck.types import CorrectedCommand\nfrom thefuck import const\n\n\n@pytest.fixture\ndef patch_get_key(monkeypatch):\n    def patch(vals):\n        vals = iter(vals)\n        monkeypatch.setattr('thefuck.ui.get_key', lambda: next(vals))\n\n    return patch\n\n\ndef test_read_actions(patch_get_key):\n    patch_get_key([\n        # Enter:\n        '\\n',\n        # Enter:\n        '\\r',\n        # Ignored:\n        'x', 'y',\n        # Up:\n        const.KEY_UP, 'k',\n        # Down:\n        const.KEY_DOWN, 'j',\n        # Ctrl+C:\n        const.KEY_CTRL_C, 'q'])\n    assert (list(islice(ui.read_actions(), 8))\n            == [const.ACTION_SELECT, const.ACTION_SELECT,\n                const.ACTION_PREVIOUS, const.ACTION_PREVIOUS,\n                const.ACTION_NEXT, const.ACTION_NEXT,\n                const.ACTION_ABORT, const.ACTION_ABORT])\n\n\ndef test_command_selector():\n    selector = ui.CommandSelector(iter([1, 2, 3]))\n    assert selector.value == 1\n    selector.next()\n    assert selector.value == 2\n    selector.next()\n    assert selector.value == 3\n    selector.next()\n    assert selector.value == 1\n    selector.previous()\n    assert selector.value == 3\n\n\n@pytest.mark.usefixtures('no_colors')\nclass TestSelectCommand(object):\n    @pytest.fixture\n    def commands_with_side_effect(self):\n        return [CorrectedCommand('ls', lambda *_: None, 100),\n                CorrectedCommand('cd', lambda *_: None, 100)]\n\n    @pytest.fixture\n    def commands(self):\n        return [CorrectedCommand('ls', None, 100),\n                CorrectedCommand('cd', None, 100)]\n\n    def test_without_commands(self, capsys):\n        assert ui.select_command(iter([])) is None\n        assert capsys.readouterr() == ('', 'No fucks given\\n')\n\n    def test_without_confirmation(self, capsys, commands, settings):\n        settings.require_confirmation = False\n        assert ui.select_command(iter(commands)) == commands[0]\n        assert capsys.readouterr() == ('', const.USER_COMMAND_MARK + 'ls\\n')\n\n    def test_without_confirmation_with_side_effects(\n            self, capsys, commands_with_side_effect, settings):\n        settings.require_confirmation = False\n        assert (ui.select_command(iter(commands_with_side_effect))\n                == commands_with_side_effect[0])\n        assert capsys.readouterr() == ('', const.USER_COMMAND_MARK + 'ls (+side effect)\\n')\n\n    def test_with_confirmation(self, capsys, patch_get_key, commands):\n        patch_get_key(['\\n'])\n        assert ui.select_command(iter(commands)) == commands[0]\n        assert capsys.readouterr() == (\n            '', const.USER_COMMAND_MARK + u'\\x1b[1K\\rls [enter/↑/↓/ctrl+c]\\n')\n\n    def test_with_confirmation_abort(self, capsys, patch_get_key, commands):\n        patch_get_key([const.KEY_CTRL_C])\n        assert ui.select_command(iter(commands)) is None\n        assert capsys.readouterr() == (\n            '', const.USER_COMMAND_MARK + u'\\x1b[1K\\rls [enter/↑/↓/ctrl+c]\\nAborted\\n')\n\n    def test_with_confirmation_with_side_effct(self, capsys, patch_get_key,\n                                               commands_with_side_effect):\n        patch_get_key(['\\n'])\n        assert (ui.select_command(iter(commands_with_side_effect))\n                == commands_with_side_effect[0])\n        assert capsys.readouterr() == (\n            '', const.USER_COMMAND_MARK + u'\\x1b[1K\\rls (+side effect) [enter/↑/↓/ctrl+c]\\n')\n\n    def test_with_confirmation_select_second(self, capsys, patch_get_key, commands):\n        patch_get_key([const.KEY_DOWN, '\\n'])\n        assert ui.select_command(iter(commands)) == commands[1]\n        stderr = (\n            u'{mark}\\x1b[1K\\rls [enter/↑/↓/ctrl+c]'\n            u'{mark}\\x1b[1K\\rcd [enter/↑/↓/ctrl+c]\\n'\n        ).format(mark=const.USER_COMMAND_MARK)\n        assert capsys.readouterr() == ('', stderr)\n"
  },
  {
    "path": "tests/test_utils.py",
    "content": "# -*- coding: utf-8 -*-\n\nimport pytest\nimport warnings\nfrom mock import Mock, call, patch\nfrom thefuck.utils import default_settings, \\\n    memoize, get_closest, get_all_executables, replace_argument, \\\n    get_all_matched_commands, is_app, for_app, cache, \\\n    get_valid_history_without_current, _cache, get_close_matches\nfrom thefuck.types import Command\n\n\n@pytest.mark.parametrize('override, old, new', [\n    ({'key': 'val'}, {}, {'key': 'val'}),\n    ({'key': 'new-val'}, {'key': 'val'}, {'key': 'val'}),\n    ({'key': 'new-val', 'unset': 'unset'}, {'key': 'val'}, {'key': 'val', 'unset': 'unset'})])\ndef test_default_settings(settings, override, old, new):\n    settings.clear()\n    settings.update(old)\n    default_settings(override)(lambda _: _)(None)\n    assert settings == new\n\n\ndef test_memoize():\n    fn = Mock(__name__='fn')\n    memoized = memoize(fn)\n    memoized()\n    memoized()\n    fn.assert_called_once_with()\n\n\n@pytest.mark.usefixtures('no_memoize')\ndef test_no_memoize():\n    fn = Mock(__name__='fn')\n    memoized = memoize(fn)\n    memoized()\n    memoized()\n    assert fn.call_count == 2\n\n\nclass TestGetClosest(object):\n    def test_when_can_match(self):\n        assert 'branch' == get_closest('brnch', ['branch', 'status'])\n\n    def test_when_cant_match(self):\n        assert 'status' == get_closest('st', ['status', 'reset'])\n\n    def test_without_fallback(self):\n        assert get_closest('st', ['status', 'reset'],\n                           fallback_to_first=False) is None\n\n\nclass TestGetCloseMatches(object):\n    @patch('thefuck.utils.difflib_get_close_matches')\n    def test_call_with_n(self, difflib_mock):\n        get_close_matches('', [], 1)\n        assert difflib_mock.call_args[0][2] == 1\n\n    @patch('thefuck.utils.difflib_get_close_matches')\n    def test_call_without_n(self, difflib_mock, settings):\n        get_close_matches('', [])\n        assert difflib_mock.call_args[0][2] == settings.get('num_close_matches')\n\n\n@pytest.fixture\ndef get_aliases(mocker):\n    mocker.patch('thefuck.shells.shell.get_aliases',\n                 return_value=['vim', 'apt-get', 'fsck', 'fuck'])\n\n\n@pytest.mark.usefixtures('no_memoize', 'get_aliases')\ndef test_get_all_executables():\n    all_callables = get_all_executables()\n    assert 'vim' in all_callables\n    assert 'fsck' in all_callables\n    assert 'fuck' not in all_callables\n\n\n@pytest.fixture\ndef os_environ_pathsep(monkeypatch, path, pathsep):\n    env = {'PATH': path}\n    monkeypatch.setattr('os.environ', env)\n    monkeypatch.setattr('os.pathsep', pathsep)\n    return env\n\n\n@pytest.mark.usefixtures('no_memoize', 'os_environ_pathsep')\n@pytest.mark.parametrize('path, pathsep', [\n    ('/foo:/bar:/baz:/foo/bar', ':'),\n    (r'C:\\\\foo;C:\\\\bar;C:\\\\baz;C:\\\\foo\\\\bar', ';')])\ndef test_get_all_executables_pathsep(path, pathsep):\n    with patch('thefuck.utils.Path') as Path_mock:\n        get_all_executables()\n        Path_mock.assert_has_calls([call(p) for p in path.split(pathsep)], True)\n\n\n@pytest.mark.usefixtures('no_memoize', 'os_environ_pathsep')\n@pytest.mark.parametrize('path, pathsep, excluded', [\n    ('/foo:/bar:/baz:/foo/bar:/mnt/foo', ':', '/mnt/foo'),\n    (r'C:\\\\foo;C:\\\\bar;C:\\\\baz;C:\\\\foo\\\\bar;Z:\\\\foo', ';', r'Z:\\\\foo')])\ndef test_get_all_executables_exclude_paths(path, pathsep, excluded, settings):\n    settings.init()\n    settings.excluded_search_path_prefixes = [excluded]\n    with patch('thefuck.utils.Path') as Path_mock:\n        get_all_executables()\n        path_list = path.split(pathsep)\n        assert call(path_list[-1]) not in Path_mock.mock_calls\n        assert all(call(p) in Path_mock.mock_calls for p in path_list[:-1])\n\n\n@pytest.mark.parametrize('args, result', [\n    (('apt-get instol vim', 'instol', 'install'), 'apt-get install vim'),\n    (('git brnch', 'brnch', 'branch'), 'git branch')])\ndef test_replace_argument(args, result):\n    assert replace_argument(*args) == result\n\n\n@pytest.mark.parametrize('stderr, result', [\n    ((\"git: 'cone' is not a git command. See 'git --help'.\\n\"\n      '\\n'\n      'Did you mean one of these?\\n'\n      '\\tclone'), ['clone']),\n    ((\"git: 're' is not a git command. See 'git --help'.\\n\"\n      '\\n'\n      'Did you mean one of these?\\n'\n      '\\trebase\\n'\n      '\\treset\\n'\n      '\\tgrep\\n'\n      '\\trm'), ['rebase', 'reset', 'grep', 'rm']),\n    (('tsuru: \"target\" is not a tsuru command. See \"tsuru help\".\\n'\n      '\\n'\n      'Did you mean one of these?\\n'\n      '\\tservice-add\\n'\n      '\\tservice-bind\\n'\n      '\\tservice-doc\\n'\n      '\\tservice-info\\n'\n      '\\tservice-list\\n'\n      '\\tservice-remove\\n'\n      '\\tservice-status\\n'\n      '\\tservice-unbind'), ['service-add', 'service-bind', 'service-doc',\n                            'service-info', 'service-list', 'service-remove',\n                            'service-status', 'service-unbind'])])\ndef test_get_all_matched_commands(stderr, result):\n    assert list(get_all_matched_commands(stderr)) == result\n\n\n@pytest.mark.usefixtures('no_memoize')\n@pytest.mark.parametrize('script, names, result', [\n    ('/usr/bin/git diff', ['git', 'hub'], True),\n    ('/bin/hdfs dfs -rm foo', ['hdfs'], True),\n    ('git diff', ['git', 'hub'], True),\n    ('hub diff', ['git', 'hub'], True),\n    ('hg diff', ['git', 'hub'], False)])\ndef test_is_app(script, names, result):\n    assert is_app(Command(script, ''), *names) == result\n\n\n@pytest.mark.usefixtures('no_memoize')\n@pytest.mark.parametrize('script, names, result', [\n    ('/usr/bin/git diff', ['git', 'hub'], True),\n    ('/bin/hdfs dfs -rm foo', ['hdfs'], True),\n    ('git diff', ['git', 'hub'], True),\n    ('hub diff', ['git', 'hub'], True),\n    ('hg diff', ['git', 'hub'], False)])\ndef test_for_app(script, names, result):\n    @for_app(*names)\n    def match(command):\n        return True\n\n    assert match(Command(script, '')) == result\n\n\nclass TestCache(object):\n    @pytest.fixture\n    def shelve(self, mocker):\n        value = {}\n\n        class _Shelve(object):\n            def __init__(self, path):\n                pass\n\n            def __setitem__(self, k, v):\n                value[k] = v\n\n            def __getitem__(self, k):\n                return value[k]\n\n            def get(self, k, v=None):\n                return value.get(k, v)\n\n            def close(self):\n                return\n\n        mocker.patch('thefuck.utils.shelve.open', new_callable=lambda: _Shelve)\n        return value\n\n    @pytest.fixture(autouse=True)\n    def enable_cache(self, monkeypatch, shelve):\n        monkeypatch.setattr('thefuck.utils.cache.disabled', False)\n        _cache._init_db()\n\n    @pytest.fixture(autouse=True)\n    def mtime(self, mocker):\n        mocker.patch('thefuck.utils.os.path.getmtime', return_value=0)\n\n    @pytest.fixture\n    def fn(self):\n        @cache('~/.bashrc')\n        def fn():\n            return 'test'\n\n        return fn\n\n    @pytest.fixture\n    def key(self, monkeypatch):\n        monkeypatch.setattr('thefuck.utils.Cache._get_key',\n                            lambda *_: 'key')\n        return 'key'\n\n    def test_with_blank_cache(self, shelve, fn, key):\n        assert shelve == {}\n        assert fn() == 'test'\n        assert shelve == {key: {'etag': '0', 'value': 'test'}}\n\n    def test_with_filled_cache(self, shelve, fn, key):\n        cache_value = {key: {'etag': '0', 'value': 'new-value'}}\n        shelve.update(cache_value)\n        assert fn() == 'new-value'\n        assert shelve == cache_value\n\n    def test_when_etag_changed(self, shelve, fn, key):\n        shelve.update({key: {'etag': '-1', 'value': 'old-value'}})\n        assert fn() == 'test'\n        assert shelve == {key: {'etag': '0', 'value': 'test'}}\n\n\nclass TestGetValidHistoryWithoutCurrent(object):\n    @pytest.fixture(autouse=True)\n    def fail_on_warning(self):\n        warnings.simplefilter('error')\n        yield\n        warnings.resetwarnings()\n\n    @pytest.fixture(autouse=True)\n    def history(self, mocker):\n        mock = mocker.patch('thefuck.shells.shell.get_history')\n        #  Passing as an argument causes `UnicodeDecodeError`\n        #  with newer pytest and python 2.7\n        mock.return_value = ['le cat', 'fuck', 'ls cat',\n                             'diff x', 'nocommand x', u'café ô']\n        return mock\n\n    @pytest.fixture(autouse=True)\n    def alias(self, mocker):\n        return mocker.patch('thefuck.utils.get_alias',\n                            return_value='fuck')\n\n    @pytest.fixture(autouse=True)\n    def bins(self, mocker):\n        callables = list()\n        for name in ['diff', 'ls', 'café']:\n            bin_mock = mocker.Mock(name=name)\n            bin_mock.configure_mock(name=name, is_dir=lambda: False)\n            callables.append(bin_mock)\n        path_mock = mocker.Mock(iterdir=mocker.Mock(return_value=callables))\n        return mocker.patch('thefuck.utils.Path', return_value=path_mock)\n\n    @pytest.mark.parametrize('script, result', [\n        ('le cat', ['ls cat', 'diff x', u'café ô']),\n        ('diff x', ['ls cat', u'café ô']),\n        ('fuck', ['ls cat', 'diff x', u'café ô']),\n        (u'cafe ô', ['ls cat', 'diff x', u'café ô']),\n    ])\n    def test_get_valid_history_without_current(self, script, result):\n        command = Command(script, '')\n        assert get_valid_history_without_current(command) == result\n"
  },
  {
    "path": "tests/utils.py",
    "content": "from thefuck import types\nfrom thefuck.const import DEFAULT_PRIORITY\n\n\nclass Rule(types.Rule):\n    def __init__(self, name='', match=lambda *_: True,\n                 get_new_command=lambda *_: '',\n                 enabled_by_default=True,\n                 side_effect=None,\n                 priority=DEFAULT_PRIORITY,\n                 requires_output=True):\n        super(Rule, self).__init__(name, match, get_new_command,\n                                   enabled_by_default, side_effect,\n                                   priority, requires_output)\n\n\nclass CorrectedCommand(types.CorrectedCommand):\n    def __init__(self, script='', side_effect=None, priority=DEFAULT_PRIORITY):\n        super(CorrectedCommand, self).__init__(\n            script, side_effect, priority)\n"
  },
  {
    "path": "thefuck/__init__.py",
    "content": ""
  },
  {
    "path": "thefuck/argument_parser.py",
    "content": "import sys\nfrom argparse import ArgumentParser, SUPPRESS\nfrom .const import ARGUMENT_PLACEHOLDER\nfrom .utils import get_alias\n\n\nclass Parser(object):\n    \"\"\"Argument parser that can handle arguments with our special\n    placeholder.\n\n    \"\"\"\n\n    def __init__(self):\n        self._parser = ArgumentParser(prog='thefuck', add_help=False)\n        self._add_arguments()\n\n    def _add_arguments(self):\n        \"\"\"Adds arguments to parser.\"\"\"\n        self._parser.add_argument(\n            '-v', '--version',\n            action='store_true',\n            help=\"show program's version number and exit\")\n        self._parser.add_argument(\n            '-a', '--alias',\n            nargs='?',\n            const=get_alias(),\n            help='[custom-alias-name] prints alias for current shell')\n        self._parser.add_argument(\n            '-l', '--shell-logger',\n            action='store',\n            help='log shell output to the file')\n        self._parser.add_argument(\n            '--enable-experimental-instant-mode',\n            action='store_true',\n            help='enable experimental instant mode, use on your own risk')\n        self._parser.add_argument(\n            '-h', '--help',\n            action='store_true',\n            help='show this help message and exit')\n        self._add_conflicting_arguments()\n        self._parser.add_argument(\n            '-d', '--debug',\n            action='store_true',\n            help='enable debug output')\n        self._parser.add_argument(\n            '--force-command',\n            action='store',\n            help=SUPPRESS)\n        self._parser.add_argument(\n            'command',\n            nargs='*',\n            help='command that should be fixed')\n\n    def _add_conflicting_arguments(self):\n        \"\"\"It's too dangerous to use `-y` and `-r` together.\"\"\"\n        group = self._parser.add_mutually_exclusive_group()\n        group.add_argument(\n            '-y', '--yes', '--yeah', '--hard',\n            action='store_true',\n            help='execute fixed command without confirmation')\n        group.add_argument(\n            '-r', '--repeat',\n            action='store_true',\n            help='repeat on failure')\n\n    def _prepare_arguments(self, argv):\n        \"\"\"Prepares arguments by:\n\n        - removing placeholder and moving arguments after it to beginning,\n          we need this to distinguish arguments from `command` with ours;\n\n        - adding `--` before `command`, so our parse would ignore arguments\n          of `command`.\n\n        \"\"\"\n        if ARGUMENT_PLACEHOLDER in argv:\n            index = argv.index(ARGUMENT_PLACEHOLDER)\n            return argv[index + 1:] + ['--'] + argv[:index]\n        elif argv and not argv[0].startswith('-') and argv[0] != '--':\n            return ['--'] + argv\n        else:\n            return argv\n\n    def parse(self, argv):\n        arguments = self._prepare_arguments(argv[1:])\n        return self._parser.parse_args(arguments)\n\n    def print_usage(self):\n        self._parser.print_usage(sys.stderr)\n\n    def print_help(self):\n        self._parser.print_help(sys.stderr)\n"
  },
  {
    "path": "thefuck/conf.py",
    "content": "import os\nimport sys\nfrom warnings import warn\nfrom six import text_type\nfrom . import const\nfrom .system import Path\n\ntry:\n    import importlib.util\n\n    def load_source(name, pathname, _file=None):\n        module_spec = importlib.util.spec_from_file_location(name, pathname)\n        module = importlib.util.module_from_spec(module_spec)\n        module_spec.loader.exec_module(module)\n        return module\nexcept ImportError:\n    from imp import load_source\n\n\nclass Settings(dict):\n    def __getattr__(self, item):\n        return self.get(item)\n\n    def __setattr__(self, key, value):\n        self[key] = value\n\n    def init(self, args=None):\n        \"\"\"Fills `settings` with values from `settings.py` and env.\"\"\"\n        from .logs import exception\n\n        self._setup_user_dir()\n        self._init_settings_file()\n\n        try:\n            self.update(self._settings_from_file())\n        except Exception:\n            exception(\"Can't load settings from file\", sys.exc_info())\n\n        try:\n            self.update(self._settings_from_env())\n        except Exception:\n            exception(\"Can't load settings from env\", sys.exc_info())\n\n        self.update(self._settings_from_args(args))\n\n    def _init_settings_file(self):\n        settings_path = self.user_dir.joinpath('settings.py')\n        if not settings_path.is_file():\n            with settings_path.open(mode='w') as settings_file:\n                settings_file.write(const.SETTINGS_HEADER)\n                for setting in const.DEFAULT_SETTINGS.items():\n                    settings_file.write(u'# {} = {}\\n'.format(*setting))\n\n    def _get_user_dir_path(self):\n        \"\"\"Returns Path object representing the user config resource\"\"\"\n        xdg_config_home = os.environ.get('XDG_CONFIG_HOME', '~/.config')\n        user_dir = Path(xdg_config_home, 'thefuck').expanduser()\n        legacy_user_dir = Path('~', '.thefuck').expanduser()\n\n        # For backward compatibility use legacy '~/.thefuck' if it exists:\n        if legacy_user_dir.is_dir():\n            warn(u'Config path {} is deprecated. Please move to {}'.format(\n                legacy_user_dir, user_dir))\n            return legacy_user_dir\n        else:\n            return user_dir\n\n    def _setup_user_dir(self):\n        \"\"\"Returns user config dir, create it when it doesn't exist.\"\"\"\n        user_dir = self._get_user_dir_path()\n\n        rules_dir = user_dir.joinpath('rules')\n        if not rules_dir.is_dir():\n            rules_dir.mkdir(parents=True)\n        self.user_dir = user_dir\n\n    def _settings_from_file(self):\n        \"\"\"Loads settings from file.\"\"\"\n        settings = load_source(\n            'settings', text_type(self.user_dir.joinpath('settings.py')))\n        return {key: getattr(settings, key)\n                for key in const.DEFAULT_SETTINGS.keys()\n                if hasattr(settings, key)}\n\n    def _rules_from_env(self, val):\n        \"\"\"Transforms rules list from env-string to python.\"\"\"\n        val = val.split(':')\n        if 'DEFAULT_RULES' in val:\n            val = const.DEFAULT_RULES + [rule for rule in val if rule != 'DEFAULT_RULES']\n        return val\n\n    def _priority_from_env(self, val):\n        \"\"\"Gets priority pairs from env.\"\"\"\n        for part in val.split(':'):\n            try:\n                rule, priority = part.split('=')\n                yield rule, int(priority)\n            except ValueError:\n                continue\n\n    def _val_from_env(self, env, attr):\n        \"\"\"Transforms env-strings to python.\"\"\"\n        val = os.environ[env]\n        if attr in ('rules', 'exclude_rules'):\n            return self._rules_from_env(val)\n        elif attr == 'priority':\n            return dict(self._priority_from_env(val))\n        elif attr in ('wait_command', 'history_limit', 'wait_slow_command',\n                      'num_close_matches'):\n            return int(val)\n        elif attr in ('require_confirmation', 'no_colors', 'debug',\n                      'alter_history', 'instant_mode'):\n            return val.lower() == 'true'\n        elif attr in ('slow_commands', 'excluded_search_path_prefixes'):\n            return val.split(':')\n        else:\n            return val\n\n    def _settings_from_env(self):\n        \"\"\"Loads settings from env.\"\"\"\n        return {attr: self._val_from_env(env, attr)\n                for env, attr in const.ENV_TO_ATTR.items()\n                if env in os.environ}\n\n    def _settings_from_args(self, args):\n        \"\"\"Loads settings from args.\"\"\"\n        if not args:\n            return {}\n\n        from_args = {}\n        if args.yes:\n            from_args['require_confirmation'] = not args.yes\n        if args.debug:\n            from_args['debug'] = args.debug\n        if args.repeat:\n            from_args['repeat'] = args.repeat\n        return from_args\n\n\nsettings = Settings(const.DEFAULT_SETTINGS)\n"
  },
  {
    "path": "thefuck/const.py",
    "content": "# -*- encoding: utf-8 -*-\n\n\nclass _GenConst(object):\n    def __init__(self, name):\n        self._name = name\n\n    def __repr__(self):\n        return u'<const: {}>'.format(self._name)\n\n\nKEY_UP = _GenConst('↑')\nKEY_DOWN = _GenConst('↓')\nKEY_CTRL_C = _GenConst('Ctrl+C')\nKEY_CTRL_N = _GenConst('Ctrl+N')\nKEY_CTRL_P = _GenConst('Ctrl+P')\n\nKEY_MAPPING = {'\\x0e': KEY_CTRL_N,\n               '\\x03': KEY_CTRL_C,\n               '\\x10': KEY_CTRL_P}\n\nACTION_SELECT = _GenConst('select')\nACTION_ABORT = _GenConst('abort')\nACTION_PREVIOUS = _GenConst('previous')\nACTION_NEXT = _GenConst('next')\n\nALL_ENABLED = _GenConst('All rules enabled')\nDEFAULT_RULES = [ALL_ENABLED]\nDEFAULT_PRIORITY = 1000\n\nDEFAULT_SETTINGS = {'rules': DEFAULT_RULES,\n                    'exclude_rules': [],\n                    'wait_command': 3,\n                    'require_confirmation': True,\n                    'no_colors': False,\n                    'debug': False,\n                    'priority': {},\n                    'history_limit': None,\n                    'alter_history': True,\n                    'wait_slow_command': 15,\n                    'slow_commands': ['lein', 'react-native', 'gradle',\n                                      './gradlew', 'vagrant'],\n                    'repeat': False,\n                    'instant_mode': False,\n                    'num_close_matches': 3,\n                    'env': {'LC_ALL': 'C', 'LANG': 'C', 'GIT_TRACE': '1'},\n                    'excluded_search_path_prefixes': []}\n\nENV_TO_ATTR = {'THEFUCK_RULES': 'rules',\n               'THEFUCK_EXCLUDE_RULES': 'exclude_rules',\n               'THEFUCK_WAIT_COMMAND': 'wait_command',\n               'THEFUCK_REQUIRE_CONFIRMATION': 'require_confirmation',\n               'THEFUCK_NO_COLORS': 'no_colors',\n               'THEFUCK_DEBUG': 'debug',\n               'THEFUCK_PRIORITY': 'priority',\n               'THEFUCK_HISTORY_LIMIT': 'history_limit',\n               'THEFUCK_ALTER_HISTORY': 'alter_history',\n               'THEFUCK_WAIT_SLOW_COMMAND': 'wait_slow_command',\n               'THEFUCK_SLOW_COMMANDS': 'slow_commands',\n               'THEFUCK_REPEAT': 'repeat',\n               'THEFUCK_INSTANT_MODE': 'instant_mode',\n               'THEFUCK_NUM_CLOSE_MATCHES': 'num_close_matches',\n               'THEFUCK_EXCLUDED_SEARCH_PATH_PREFIXES': 'excluded_search_path_prefixes'}\n\nSETTINGS_HEADER = u\"\"\"# The Fuck settings file\n#\n# The rules are defined as in the example bellow:\n#\n# rules = ['cd_parent', 'git_push', 'python_command', 'sudo']\n#\n# The default values are as follows. Uncomment and change to fit your needs.\n# See https://github.com/nvbn/thefuck#settings for more information.\n#\n\n\"\"\"\n\nARGUMENT_PLACEHOLDER = 'THEFUCK_ARGUMENT_PLACEHOLDER'\n\nCONFIGURATION_TIMEOUT = 60\n\nUSER_COMMAND_MARK = u'\\u200B' * 10\n\nLOG_SIZE_IN_BYTES = 1024 * 1024\n\nLOG_SIZE_TO_CLEAN = 10 * 1024\n\nDIFF_WITH_ALIAS = 0.5\n\nSHELL_LOGGER_SOCKET_ENV = 'SHELL_LOGGER_SOCKET'\n\nSHELL_LOGGER_LIMIT = 5\n"
  },
  {
    "path": "thefuck/corrector.py",
    "content": "import sys\nfrom .conf import settings\nfrom .types import Rule\nfrom .system import Path\nfrom . import logs\n\n\ndef get_loaded_rules(rules_paths):\n    \"\"\"Yields all available rules.\n\n    :type rules_paths: [Path]\n    :rtype: Iterable[Rule]\n\n    \"\"\"\n    for path in rules_paths:\n        if path.name != '__init__.py':\n            rule = Rule.from_path(path)\n            if rule and rule.is_enabled:\n                yield rule\n\n\ndef get_rules_import_paths():\n    \"\"\"Yields all rules import paths.\n\n    :rtype: Iterable[Path]\n\n    \"\"\"\n    # Bundled rules:\n    yield Path(__file__).parent.joinpath('rules')\n    # Rules defined by user:\n    yield settings.user_dir.joinpath('rules')\n    # Packages with third-party rules:\n    for path in sys.path:\n        for contrib_module in Path(path).glob('thefuck_contrib_*'):\n            contrib_rules = contrib_module.joinpath('rules')\n            if contrib_rules.is_dir():\n                yield contrib_rules\n\n\ndef get_rules():\n    \"\"\"Returns all enabled rules.\n\n    :rtype: [Rule]\n\n    \"\"\"\n    paths = [rule_path for path in get_rules_import_paths()\n             for rule_path in sorted(path.glob('*.py'))]\n    return sorted(get_loaded_rules(paths),\n                  key=lambda rule: rule.priority)\n\n\ndef organize_commands(corrected_commands):\n    \"\"\"Yields sorted commands without duplicates.\n\n    :type corrected_commands: Iterable[thefuck.types.CorrectedCommand]\n    :rtype: Iterable[thefuck.types.CorrectedCommand]\n\n    \"\"\"\n    try:\n        first_command = next(corrected_commands)\n        yield first_command\n    except StopIteration:\n        return\n\n    without_duplicates = {\n        command for command in sorted(\n            corrected_commands, key=lambda command: command.priority)\n        if command != first_command}\n\n    sorted_commands = sorted(\n        without_duplicates,\n        key=lambda corrected_command: corrected_command.priority)\n\n    logs.debug(u'Corrected commands: {}'.format(\n        ', '.join(u'{}'.format(cmd) for cmd in [first_command] + sorted_commands)))\n\n    for command in sorted_commands:\n        yield command\n\n\ndef get_corrected_commands(command):\n    \"\"\"Returns generator with sorted and unique corrected commands.\n\n    :type command: thefuck.types.Command\n    :rtype: Iterable[thefuck.types.CorrectedCommand]\n\n    \"\"\"\n    corrected_commands = (\n        corrected for rule in get_rules()\n        if rule.is_match(command)\n        for corrected in rule.get_corrected_commands(command))\n    return organize_commands(corrected_commands)\n"
  },
  {
    "path": "thefuck/entrypoints/__init__.py",
    "content": ""
  },
  {
    "path": "thefuck/entrypoints/alias.py",
    "content": "import six\nfrom ..conf import settings\nfrom ..logs import warn\nfrom ..shells import shell\nfrom ..utils import which\n\n\ndef _get_alias(known_args):\n    if six.PY2:\n        warn(\"The Fuck will drop Python 2 support soon, more details \"\n             \"https://github.com/nvbn/thefuck/issues/685\")\n\n    alias = shell.app_alias(known_args.alias)\n\n    if known_args.enable_experimental_instant_mode:\n        if six.PY2:\n            warn(\"Instant mode requires Python 3\")\n        elif not which('script'):\n            warn(\"Instant mode requires `script` app\")\n        else:\n            return shell.instant_mode_alias(known_args.alias)\n\n    return alias\n\n\ndef print_alias(known_args):\n    settings.init(known_args)\n    print(_get_alias(known_args))\n"
  },
  {
    "path": "thefuck/entrypoints/fix_command.py",
    "content": "from pprint import pformat\nimport os\nimport sys\nfrom difflib import SequenceMatcher\nfrom .. import logs, types, const\nfrom ..conf import settings\nfrom ..corrector import get_corrected_commands\nfrom ..exceptions import EmptyCommand\nfrom ..ui import select_command\nfrom ..utils import get_alias, get_all_executables\n\n\ndef _get_raw_command(known_args):\n    if known_args.force_command:\n        return [known_args.force_command]\n    elif not os.environ.get('TF_HISTORY'):\n        return known_args.command\n    else:\n        history = os.environ['TF_HISTORY'].split('\\n')[::-1]\n        alias = get_alias()\n        executables = get_all_executables()\n        for command in history:\n            diff = SequenceMatcher(a=alias, b=command).ratio()\n            if diff < const.DIFF_WITH_ALIAS or command in executables:\n                return [command]\n    return []\n\n\ndef fix_command(known_args):\n    \"\"\"Fixes previous command. Used when `thefuck` called without arguments.\"\"\"\n    settings.init(known_args)\n    with logs.debug_time('Total'):\n        logs.debug(u'Run with settings: {}'.format(pformat(settings)))\n        raw_command = _get_raw_command(known_args)\n\n        try:\n            command = types.Command.from_raw_script(raw_command)\n        except EmptyCommand:\n            logs.debug('Empty command, nothing to do')\n            return\n\n        corrected_commands = get_corrected_commands(command)\n        selected_command = select_command(corrected_commands)\n\n        if selected_command:\n            selected_command.run(command)\n        else:\n            sys.exit(1)\n"
  },
  {
    "path": "thefuck/entrypoints/main.py",
    "content": "# Initialize output before importing any module, that can use colorama.\nfrom ..system import init_output\n\ninit_output()\n\nimport os  # noqa: E402\nimport sys  # noqa: E402\nfrom .. import logs  # noqa: E402\nfrom ..argument_parser import Parser  # noqa: E402\nfrom ..utils import get_installation_version  # noqa: E402\nfrom ..shells import shell  # noqa: E402\nfrom .alias import print_alias  # noqa: E402\nfrom .fix_command import fix_command  # noqa: E402\n\n\ndef main():\n    parser = Parser()\n    known_args = parser.parse(sys.argv)\n\n    if known_args.help:\n        parser.print_help()\n    elif known_args.version:\n        logs.version(get_installation_version(),\n                     sys.version.split()[0], shell.info())\n    # It's important to check if an alias is being requested before checking if\n    # `TF_HISTORY` is in `os.environ`, otherwise it might mess with subshells.\n    # Check https://github.com/nvbn/thefuck/issues/921 for reference\n    elif known_args.alias:\n        print_alias(known_args)\n    elif known_args.command or 'TF_HISTORY' in os.environ:\n        fix_command(known_args)\n    elif known_args.shell_logger:\n        try:\n            from .shell_logger import shell_logger  # noqa: E402\n        except ImportError:\n            logs.warn('Shell logger supports only Linux and macOS')\n        else:\n            shell_logger(known_args.shell_logger)\n    else:\n        parser.print_usage()\n"
  },
  {
    "path": "thefuck/entrypoints/not_configured.py",
    "content": "# Initialize output before importing any module, that can use colorama.\nfrom ..system import init_output\n\ninit_output()\n\nimport getpass  # noqa: E402\nimport os  # noqa: E402\nimport json  # noqa: E402\nfrom tempfile import gettempdir  # noqa: E402\nimport time  # noqa: E402\nimport six  # noqa: E402\nfrom psutil import Process  # noqa: E402\nfrom .. import logs, const  # noqa: E402\nfrom ..shells import shell  # noqa: E402\nfrom ..conf import settings  # noqa: E402\nfrom ..system import Path  # noqa: E402\n\n\ndef _get_shell_pid():\n    \"\"\"Returns parent process pid.\"\"\"\n    proc = Process(os.getpid())\n\n    try:\n        return proc.parent().pid\n    except TypeError:\n        return proc.parent.pid\n\n\ndef _get_not_configured_usage_tracker_path():\n    \"\"\"Returns path of special file where we store latest shell pid.\"\"\"\n    return Path(gettempdir()).joinpath(u'thefuck.last_not_configured_run_{}'.format(\n        getpass.getuser(),\n    ))\n\n\ndef _record_first_run():\n    \"\"\"Records shell pid to tracker file.\"\"\"\n    info = {'pid': _get_shell_pid(),\n            'time': time.time()}\n\n    mode = 'wb' if six.PY2 else 'w'\n    with _get_not_configured_usage_tracker_path().open(mode) as tracker:\n        json.dump(info, tracker)\n\n\ndef _get_previous_command():\n    history = shell.get_history()\n\n    if history:\n        return history[-1]\n    else:\n        return None\n\n\ndef _is_second_run():\n    \"\"\"Returns `True` when we know that `fuck` called second time.\"\"\"\n    tracker_path = _get_not_configured_usage_tracker_path()\n    if not tracker_path.exists():\n        return False\n\n    current_pid = _get_shell_pid()\n    with tracker_path.open('r') as tracker:\n        try:\n            info = json.load(tracker)\n        except ValueError:\n            return False\n\n    if not (isinstance(info, dict) and info.get('pid') == current_pid):\n        return False\n\n    return (_get_previous_command() == 'fuck' or\n            time.time() - info.get('time', 0) < const.CONFIGURATION_TIMEOUT)\n\n\ndef _is_already_configured(configuration_details):\n    \"\"\"Returns `True` when alias already in shell config.\"\"\"\n    path = Path(configuration_details.path).expanduser()\n    with path.open('r') as shell_config:\n        return configuration_details.content in shell_config.read()\n\n\ndef _configure(configuration_details):\n    \"\"\"Adds alias to shell config.\"\"\"\n    path = Path(configuration_details.path).expanduser()\n    with path.open('a') as shell_config:\n        shell_config.write(u'\\n')\n        shell_config.write(configuration_details.content)\n        shell_config.write(u'\\n')\n\n\ndef main():\n    \"\"\"Shows useful information about how-to configure alias on a first run\n    and configure automatically on a second.\n\n    It'll be only visible when user type fuck and when alias isn't configured.\n\n    \"\"\"\n    settings.init()\n    configuration_details = shell.how_to_configure()\n    if (\n        configuration_details and\n        configuration_details.can_configure_automatically\n    ):\n        if _is_already_configured(configuration_details):\n            logs.already_configured(configuration_details)\n            return\n        elif _is_second_run():\n            _configure(configuration_details)\n            logs.configured_successfully(configuration_details)\n            return\n        else:\n            _record_first_run()\n\n    logs.how_to_configure_alias(configuration_details)\n"
  },
  {
    "path": "thefuck/entrypoints/shell_logger.py",
    "content": "import array\nimport fcntl\nfrom functools import partial\nimport mmap\nimport os\nimport pty\nimport signal\nimport sys\nimport termios\nimport tty\nfrom .. import logs, const\n\n\ndef _read(f, fd):\n    data = os.read(fd, 1024)\n    try:\n        f.write(data)\n    except ValueError:\n        position = const.LOG_SIZE_IN_BYTES - const.LOG_SIZE_TO_CLEAN\n        f.move(0, const.LOG_SIZE_TO_CLEAN, position)\n        f.seek(position)\n        f.write(b'\\x00' * const.LOG_SIZE_TO_CLEAN)\n        f.seek(position)\n    return data\n\n\ndef _set_pty_size(master_fd):\n    buf = array.array('h', [0, 0, 0, 0])\n    fcntl.ioctl(pty.STDOUT_FILENO, termios.TIOCGWINSZ, buf, True)\n    fcntl.ioctl(master_fd, termios.TIOCSWINSZ, buf)\n\n\ndef _spawn(shell, master_read):\n    \"\"\"Create a spawned process.\n\n    Modified version of pty.spawn with terminal size support.\n\n    \"\"\"\n    pid, master_fd = pty.fork()\n\n    if pid == pty.CHILD:\n        os.execlp(shell, shell)\n\n    try:\n        mode = tty.tcgetattr(pty.STDIN_FILENO)\n        tty.setraw(pty.STDIN_FILENO)\n        restore = True\n    except tty.error:    # This is the same as termios.error\n        restore = False\n\n    _set_pty_size(master_fd)\n    signal.signal(signal.SIGWINCH, lambda *_: _set_pty_size(master_fd))\n\n    try:\n        pty._copy(master_fd, master_read, pty._read)\n    except OSError:\n        if restore:\n            tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode)\n\n    os.close(master_fd)\n    return os.waitpid(pid, 0)[1]\n\n\ndef shell_logger(output):\n    \"\"\"Logs shell output to the `output`.\n\n    Works like unix script command with `-f` flag.\n\n    \"\"\"\n    if not os.environ.get('SHELL'):\n        logs.warn(\"Shell logger doesn't support your platform.\")\n        sys.exit(1)\n\n    fd = os.open(output, os.O_CREAT | os.O_TRUNC | os.O_RDWR)\n    os.write(fd, b'\\x00' * const.LOG_SIZE_IN_BYTES)\n    buffer = mmap.mmap(fd, const.LOG_SIZE_IN_BYTES, mmap.MAP_SHARED, mmap.PROT_WRITE)\n    return_code = _spawn(os.environ['SHELL'], partial(_read, buffer))\n\n    sys.exit(return_code)\n"
  },
  {
    "path": "thefuck/exceptions.py",
    "content": "class EmptyCommand(Exception):\n    \"\"\"Raised when empty command passed to `thefuck`.\"\"\"\n\n\nclass NoRuleMatched(Exception):\n    \"\"\"Raised when no rule matched for some command.\"\"\"\n\n\nclass ScriptNotInLog(Exception):\n    \"\"\"Script not found in log.\"\"\"\n"
  },
  {
    "path": "thefuck/logs.py",
    "content": "# -*- encoding: utf-8 -*-\n\nfrom contextlib import contextmanager\nfrom datetime import datetime\nimport sys\nfrom traceback import format_exception\nimport colorama\nfrom .conf import settings\nfrom . import const\n\n\ndef color(color_):\n    \"\"\"Utility for ability to disabling colored output.\"\"\"\n    if settings.no_colors:\n        return ''\n    else:\n        return color_\n\n\ndef warn(title):\n    sys.stderr.write(u'{warn}[WARN] {title}{reset}\\n'.format(\n        warn=color(colorama.Back.RED + colorama.Fore.WHITE\n                   + colorama.Style.BRIGHT),\n        reset=color(colorama.Style.RESET_ALL),\n        title=title))\n\n\ndef exception(title, exc_info):\n    sys.stderr.write(\n        u'{warn}[WARN] {title}:{reset}\\n{trace}'\n        u'{warn}----------------------------{reset}\\n\\n'.format(\n            warn=color(colorama.Back.RED + colorama.Fore.WHITE\n                       + colorama.Style.BRIGHT),\n            reset=color(colorama.Style.RESET_ALL),\n            title=title,\n            trace=''.join(format_exception(*exc_info))))\n\n\ndef rule_failed(rule, exc_info):\n    exception(u'Rule {}'.format(rule.name), exc_info)\n\n\ndef failed(msg):\n    sys.stderr.write(u'{red}{msg}{reset}\\n'.format(\n        msg=msg,\n        red=color(colorama.Fore.RED),\n        reset=color(colorama.Style.RESET_ALL)))\n\n\ndef show_corrected_command(corrected_command):\n    sys.stderr.write(u'{prefix}{bold}{script}{reset}{side_effect}\\n'.format(\n        prefix=const.USER_COMMAND_MARK,\n        script=corrected_command.script,\n        side_effect=u' (+side effect)' if corrected_command.side_effect else u'',\n        bold=color(colorama.Style.BRIGHT),\n        reset=color(colorama.Style.RESET_ALL)))\n\n\ndef confirm_text(corrected_command):\n    sys.stderr.write(\n        (u'{prefix}{clear}{bold}{script}{reset}{side_effect} '\n         u'[{green}enter{reset}/{blue}↑{reset}/{blue}↓{reset}'\n         u'/{red}ctrl+c{reset}]').format(\n            prefix=const.USER_COMMAND_MARK,\n            script=corrected_command.script,\n            side_effect=' (+side effect)' if corrected_command.side_effect else '',\n            clear='\\033[1K\\r',\n            bold=color(colorama.Style.BRIGHT),\n            green=color(colorama.Fore.GREEN),\n            red=color(colorama.Fore.RED),\n            reset=color(colorama.Style.RESET_ALL),\n            blue=color(colorama.Fore.BLUE)))\n\n\ndef debug(msg):\n    if settings.debug:\n        sys.stderr.write(u'{blue}{bold}DEBUG:{reset} {msg}\\n'.format(\n            msg=msg,\n            reset=color(colorama.Style.RESET_ALL),\n            blue=color(colorama.Fore.BLUE),\n            bold=color(colorama.Style.BRIGHT)))\n\n\n@contextmanager\ndef debug_time(msg):\n    started = datetime.now()\n    try:\n        yield\n    finally:\n        debug(u'{} took: {}'.format(msg, datetime.now() - started))\n\n\ndef how_to_configure_alias(configuration_details):\n    print(u\"Seems like {bold}fuck{reset} alias isn't configured!\".format(\n        bold=color(colorama.Style.BRIGHT),\n        reset=color(colorama.Style.RESET_ALL)))\n\n    if configuration_details:\n        print(\n            u\"Please put {bold}{content}{reset} in your \"\n            u\"{bold}{path}{reset} and apply \"\n            u\"changes with {bold}{reload}{reset} or restart your shell.\".format(\n                bold=color(colorama.Style.BRIGHT),\n                reset=color(colorama.Style.RESET_ALL),\n                **configuration_details._asdict()))\n\n        if configuration_details.can_configure_automatically:\n            print(\n                u\"Or run {bold}fuck{reset} a second time to configure\"\n                u\" it automatically.\".format(\n                    bold=color(colorama.Style.BRIGHT),\n                    reset=color(colorama.Style.RESET_ALL)))\n\n    print(u'More details - https://github.com/nvbn/thefuck#manual-installation')\n\n\ndef already_configured(configuration_details):\n    print(\n        u\"Seems like {bold}fuck{reset} alias already configured!\\n\"\n        u\"For applying changes run {bold}{reload}{reset}\"\n        u\" or restart your shell.\".format(\n            bold=color(colorama.Style.BRIGHT),\n            reset=color(colorama.Style.RESET_ALL),\n            reload=configuration_details.reload))\n\n\ndef configured_successfully(configuration_details):\n    print(\n        u\"{bold}fuck{reset} alias configured successfully!\\n\"\n        u\"For applying changes run {bold}{reload}{reset}\"\n        u\" or restart your shell.\".format(\n            bold=color(colorama.Style.BRIGHT),\n            reset=color(colorama.Style.RESET_ALL),\n            reload=configuration_details.reload))\n\n\ndef version(thefuck_version, python_version, shell_info):\n    sys.stderr.write(\n        u'The Fuck {} using Python {} and {}\\n'.format(thefuck_version,\n                                                       python_version,\n                                                       shell_info))\n"
  },
  {
    "path": "thefuck/output_readers/__init__.py",
    "content": "from ..conf import settings\nfrom . import read_log, rerun, shell_logger\n\n\ndef get_output(script, expanded):\n    \"\"\"Get output of the script.\n\n    :param script: Console script.\n    :type script: str\n    :param expanded: Console script with expanded aliases.\n    :type expanded: str\n    :rtype: str\n\n    \"\"\"\n    if shell_logger.is_available():\n        return shell_logger.get_output(script)\n    if settings.instant_mode:\n        return read_log.get_output(script)\n    else:\n        return rerun.get_output(script, expanded)\n"
  },
  {
    "path": "thefuck/output_readers/read_log.py",
    "content": "import os\nimport shlex\nimport mmap\nimport re\ntry:\n    from shutil import get_terminal_size\nexcept ImportError:\n    from backports.shutil_get_terminal_size import get_terminal_size\nimport six\nimport pyte\nfrom ..exceptions import ScriptNotInLog\nfrom .. import const, logs\n\n\ndef _group_by_calls(log):\n    ps1 = os.environ['PS1']\n    ps1_newlines = ps1.count('\\\\n') + ps1.count('\\n')\n    ps1_counter = 0\n\n    script_line = None\n    lines = []\n    for line in log:\n        if const.USER_COMMAND_MARK in line or ps1_counter > 0:\n            if script_line and ps1_counter == 0:\n                yield script_line, lines\n\n            if ps1_newlines > 0:\n                if ps1_counter <= 0:\n                    ps1_counter = ps1_newlines\n                else:\n                    ps1_counter -= 1\n\n            script_line = line\n            lines = [line]\n        elif script_line is not None:\n            lines.append(line)\n\n    if script_line:\n        yield script_line, lines\n\n\ndef _get_script_group_lines(grouped, script):\n    if six.PY2:\n        script = script.encode('utf-8')\n\n    parts = shlex.split(script)\n\n    for script_line, lines in reversed(grouped):\n        if all(part in script_line for part in parts):\n            return lines\n\n    raise ScriptNotInLog\n\n\ndef _get_output_lines(script, log_file):\n    data = log_file.read().decode()\n    data = re.sub(r'\\x00+$', '', data)\n    lines = data.split('\\n')\n    grouped = list(_group_by_calls(lines))\n    script_lines = _get_script_group_lines(grouped, script)\n    screen = pyte.Screen(get_terminal_size().columns, len(script_lines))\n    stream = pyte.Stream(screen)\n    stream.feed('\\n'.join(script_lines))\n    return screen.display\n\n\ndef _skip_old_lines(log_file):\n    size = os.path.getsize(os.environ['THEFUCK_OUTPUT_LOG'])\n    if size > const.LOG_SIZE_IN_BYTES:\n        log_file.seek(size - const.LOG_SIZE_IN_BYTES)\n\n\ndef get_output(script):\n    \"\"\"Reads script output from log.\n\n    :type script: str\n    :rtype: str | None\n\n    \"\"\"\n    if six.PY2:\n        logs.warn('Experimental instant mode is Python 3+ only')\n        return None\n\n    if 'THEFUCK_OUTPUT_LOG' not in os.environ:\n        logs.warn(\"Output log isn't specified\")\n        return None\n\n    if const.USER_COMMAND_MARK not in os.environ.get('PS1', ''):\n        logs.warn(\n            \"PS1 doesn't contain user command mark, please ensure \"\n            \"that PS1 is not changed after The Fuck alias initialization\")\n        return None\n\n    try:\n        with logs.debug_time(u'Read output from log'):\n            fd = os.open(os.environ['THEFUCK_OUTPUT_LOG'], os.O_RDONLY)\n            buffer = mmap.mmap(fd, const.LOG_SIZE_IN_BYTES, mmap.MAP_SHARED, mmap.PROT_READ)\n            _skip_old_lines(buffer)\n            lines = _get_output_lines(script, buffer)\n            output = '\\n'.join(lines).strip()\n            logs.debug(u'Received output: {}'.format(output))\n            return output\n    except OSError:\n        logs.warn(\"Can't read output log\")\n        return None\n    except ScriptNotInLog:\n        logs.warn(\"Script not found in output log\")\n        return None\n"
  },
  {
    "path": "thefuck/output_readers/rerun.py",
    "content": "import os\nimport shlex\nimport six\nfrom subprocess import Popen, PIPE, STDOUT\nfrom psutil import AccessDenied, Process, TimeoutExpired\nfrom .. import logs\nfrom ..conf import settings\n\n\ndef _kill_process(proc):\n    \"\"\"Tries to kill the process otherwise just logs a debug message, the\n    process will be killed when thefuck terminates.\n\n    :type proc: Process\n\n    \"\"\"\n    try:\n        proc.kill()\n    except AccessDenied:\n        logs.debug(u'Rerun: process PID {} ({}) could not be terminated'.format(\n            proc.pid, proc.exe()))\n\n\ndef _wait_output(popen, is_slow):\n    \"\"\"Returns `True` if we can get output of the command in the\n    `settings.wait_command` time.\n\n    Command will be killed if it wasn't finished in the time.\n\n    :type popen: Popen\n    :rtype: bool\n\n    \"\"\"\n    proc = Process(popen.pid)\n    try:\n        proc.wait(settings.wait_slow_command if is_slow\n                  else settings.wait_command)\n        return True\n    except TimeoutExpired:\n        for child in proc.children(recursive=True):\n            _kill_process(child)\n        _kill_process(proc)\n        return False\n\n\ndef get_output(script, expanded):\n    \"\"\"Runs the script and obtains stdin/stderr.\n\n    :type script: str\n    :type expanded: str\n    :rtype: str | None\n\n    \"\"\"\n    env = dict(os.environ)\n    env.update(settings.env)\n\n    if six.PY2:\n        expanded = expanded.encode('utf-8')\n\n    split_expand = shlex.split(expanded)\n    is_slow = split_expand[0] in settings.slow_commands if split_expand else False\n    with logs.debug_time(u'Call: {}; with env: {}; is slow: {}'.format(\n            script, env, is_slow)):\n        result = Popen(expanded, shell=True, stdin=PIPE,\n                       stdout=PIPE, stderr=STDOUT, env=env)\n        if _wait_output(result, is_slow):\n            output = result.stdout.read().decode('utf-8', errors='replace')\n            logs.debug(u'Received output: {}'.format(output))\n            return output\n        else:\n            logs.debug(u'Execution timed out!')\n            return None\n"
  },
  {
    "path": "thefuck/output_readers/shell_logger.py",
    "content": "import json\nimport os\nimport socket\ntry:\n    from shutil import get_terminal_size\nexcept ImportError:\n    from backports.shutil_get_terminal_size import get_terminal_size\nimport pyte\nfrom .. import const, logs\n\n\ndef _get_socket_path():\n    return os.environ.get(const.SHELL_LOGGER_SOCKET_ENV)\n\n\ndef is_available():\n    \"\"\"Returns `True` if shell logger socket available.\n\n    :rtype: book\n\n    \"\"\"\n    path = _get_socket_path()\n    if not path:\n        return False\n\n    return os.path.exists(path)\n\n\ndef _get_last_n(n):\n    with socket.socket(socket.AF_UNIX) as client:\n        client.connect(_get_socket_path())\n        request = json.dumps({\n            \"type\": \"list\",\n            \"count\": n,\n        }) + '\\n'\n        client.sendall(request.encode('utf-8'))\n        response = client.makefile().readline()\n        return json.loads(response)['commands']\n\n\ndef _get_output_lines(output):\n    lines = output.split('\\n')\n    screen = pyte.Screen(get_terminal_size().columns, len(lines))\n    stream = pyte.Stream(screen)\n    stream.feed('\\n'.join(lines))\n    return screen.display\n\n\ndef get_output(script):\n    \"\"\"Gets command output from shell logger.\"\"\"\n    with logs.debug_time(u'Read output from external shell logger'):\n        commands = _get_last_n(const.SHELL_LOGGER_LIMIT)\n        for command in commands:\n            if command['command'] == script:\n                lines = _get_output_lines(command['output'])\n                output = '\\n'.join(lines).strip()\n                return output\n            else:\n                logs.warn(\"Output isn't available in shell logger\")\n                return None\n"
  },
  {
    "path": "thefuck/rules/__init__.py",
    "content": ""
  },
  {
    "path": "thefuck/rules/adb_unknown_command.py",
    "content": "from thefuck.utils import is_app, get_closest, replace_argument\n\n\n_ADB_COMMANDS = (\n    'backup',\n    'bugreport',\n    'connect',\n    'devices',\n    'disable-verity',\n    'disconnect',\n    'enable-verity',\n    'emu',\n    'forward',\n    'get-devpath',\n    'get-serialno',\n    'get-state',\n    'install',\n    'install-multiple',\n    'jdwp',\n    'keygen',\n    'kill-server',\n    'logcat',\n    'pull',\n    'push',\n    'reboot',\n    'reconnect',\n    'restore',\n    'reverse',\n    'root',\n    'run-as',\n    'shell',\n    'sideload',\n    'start-server',\n    'sync',\n    'tcpip',\n    'uninstall',\n    'unroot',\n    'usb',\n    'wait-for',\n)\n\n\ndef match(command):\n    return (is_app(command, 'adb')\n            and command.output.startswith('Android Debug Bridge version'))\n\n\ndef get_new_command(command):\n    for idx, arg in enumerate(command.script_parts[1:]):\n        # allowed params to ADB are a/d/e/s/H/P/L where s, H, P and L take additional args\n        # for example 'adb -s 111 logcat' or 'adb -e logcat'\n        if not arg[0] == '-' and not command.script_parts[idx] in ('-s', '-H', '-P', '-L'):\n            adb_cmd = get_closest(arg, _ADB_COMMANDS)\n            return replace_argument(command.script, arg, adb_cmd)\n"
  },
  {
    "path": "thefuck/rules/ag_literal.py",
    "content": "from thefuck.utils import for_app\n\n\n@for_app('ag')\ndef match(command):\n    return command.output.endswith('run ag with -Q\\n')\n\n\ndef get_new_command(command):\n    return command.script.replace('ag', 'ag -Q', 1)\n"
  },
  {
    "path": "thefuck/rules/apt_get.py",
    "content": "from types import ModuleType\nfrom thefuck.specific.apt import apt_available\nfrom thefuck.utils import memoize, which\nfrom thefuck.shells import shell\n\ntry:\n    from CommandNotFound import CommandNotFound\n\n    enabled_by_default = apt_available\n\n    if isinstance(CommandNotFound, ModuleType):\n        # For ubuntu 18.04+\n        _get_packages = CommandNotFound.CommandNotFound().get_packages\n    else:\n        # For older versions\n        _get_packages = CommandNotFound().getPackages\nexcept ImportError:\n    enabled_by_default = False\n\n\ndef _get_executable(command):\n    if command.script_parts[0] == 'sudo':\n        return command.script_parts[1]\n    else:\n        return command.script_parts[0]\n\n\n@memoize\ndef get_package(executable):\n    try:\n        packages = _get_packages(executable)\n        return packages[0][0]\n    except IndexError:\n        # IndexError is thrown when no matching package is found\n        return None\n\n\ndef match(command):\n    if 'not found' in command.output or 'not installed' in command.output:\n        executable = _get_executable(command)\n        return not which(executable) and get_package(executable)\n    else:\n        return False\n\n\ndef get_new_command(command):\n    executable = _get_executable(command)\n    name = get_package(executable)\n    formatme = shell.and_('sudo apt-get install {}', '{}')\n    return formatme.format(name, command.script)\n"
  },
  {
    "path": "thefuck/rules/apt_get_search.py",
    "content": "import re\nfrom thefuck.specific.apt import apt_available\nfrom thefuck.utils import for_app\n\nenabled_by_default = apt_available\n\n\n@for_app('apt-get')\ndef match(command):\n    return command.script.startswith('apt-get search')\n\n\ndef get_new_command(command):\n    return re.sub(r'^apt-get', 'apt-cache', command.script)\n"
  },
  {
    "path": "thefuck/rules/apt_invalid_operation.py",
    "content": "import subprocess\nfrom thefuck.specific.apt import apt_available\nfrom thefuck.specific.sudo import sudo_support\nfrom thefuck.utils import for_app, eager, replace_command\n\nenabled_by_default = apt_available\n\n\n@sudo_support\n@for_app('apt', 'apt-get', 'apt-cache')\ndef match(command):\n    return 'E: Invalid operation' in command.output\n\n\n@eager\ndef _parse_apt_operations(help_text_lines):\n    is_commands_list = False\n    for line in help_text_lines:\n        line = line.decode().strip()\n        if is_commands_list and line:\n            yield line.split()[0]\n        elif line.startswith('Basic commands:') \\\n                or line.startswith('Most used commands:'):\n            is_commands_list = True\n\n\n@eager\ndef _parse_apt_get_and_cache_operations(help_text_lines):\n    is_commands_list = False\n    for line in help_text_lines:\n        line = line.decode().strip()\n        if is_commands_list:\n            if not line:\n                return\n\n            yield line.split()[0]\n        elif line.startswith('Commands:') \\\n                or line.startswith('Most used commands:'):\n            is_commands_list = True\n\n\ndef _get_operations(app):\n    proc = subprocess.Popen([app, '--help'],\n                            stdout=subprocess.PIPE,\n                            stderr=subprocess.PIPE)\n    lines = proc.stdout.readlines()\n\n    if app == 'apt':\n        return _parse_apt_operations(lines)\n    else:\n        return _parse_apt_get_and_cache_operations(lines)\n\n\n@sudo_support\ndef get_new_command(command):\n    invalid_operation = command.output.split()[-1]\n\n    if invalid_operation == 'uninstall':\n        return [command.script.replace('uninstall', 'remove')]\n\n    else:\n        operations = _get_operations(command.script_parts[0])\n        return replace_command(command, invalid_operation, operations)\n"
  },
  {
    "path": "thefuck/rules/apt_list_upgradable.py",
    "content": "from thefuck.specific.apt import apt_available\nfrom thefuck.specific.sudo import sudo_support\nfrom thefuck.utils import for_app\n\nenabled_by_default = apt_available\n\n\n@sudo_support\n@for_app('apt')\ndef match(command):\n    return 'apt list --upgradable' in command.output\n\n\n@sudo_support\ndef get_new_command(command):\n    return 'apt list --upgradable'\n"
  },
  {
    "path": "thefuck/rules/apt_upgrade.py",
    "content": "from thefuck.specific.apt import apt_available\nfrom thefuck.specific.sudo import sudo_support\nfrom thefuck.utils import for_app\n\nenabled_by_default = apt_available\n\n\n@sudo_support\n@for_app('apt')\ndef match(command):\n    return command.script == \"apt list --upgradable\" and len(command.output.strip().split('\\n')) > 1\n\n\n@sudo_support\ndef get_new_command(command):\n    return 'apt upgrade'\n"
  },
  {
    "path": "thefuck/rules/aws_cli.py",
    "content": "import re\n\nfrom thefuck.utils import for_app, replace_argument\n\nINVALID_CHOICE = \"(?<=Invalid choice: ')(.*)(?=', maybe you meant:)\"\nOPTIONS = \"^\\\\s*\\\\*\\\\s(.*)\"\n\n\n@for_app('aws')\ndef match(command):\n    return \"usage:\" in command.output and \"maybe you meant:\" in command.output\n\n\ndef get_new_command(command):\n    mistake = re.search(INVALID_CHOICE, command.output).group(0)\n    options = re.findall(OPTIONS, command.output, flags=re.MULTILINE)\n    return [replace_argument(command.script, mistake, o) for o in options]\n"
  },
  {
    "path": "thefuck/rules/az_cli.py",
    "content": "import re\n\nfrom thefuck.utils import for_app, replace_argument\n\nINVALID_CHOICE = \"(?=az)(?:.*): '(.*)' is not in the '.*' command group.\"\nOPTIONS = \"^The most similar choice to '.*' is:\\n\\\\s*(.*)$\"\n\n\n@for_app('az')\ndef match(command):\n    return \"is not in the\" in command.output and \"command group\" in command.output\n\n\ndef get_new_command(command):\n    mistake = re.search(INVALID_CHOICE, command.output).group(1)\n    options = re.findall(OPTIONS, command.output, flags=re.MULTILINE)\n    return [replace_argument(command.script, mistake, o) for o in options]\n"
  },
  {
    "path": "thefuck/rules/brew_cask_dependency.py",
    "content": "from thefuck.utils import for_app, eager\nfrom thefuck.shells import shell\nfrom thefuck.specific.brew import brew_available\n\n\n@for_app('brew')\ndef match(command):\n    return (u'install' in command.script_parts\n            and u'brew cask install' in command.output)\n\n\n@eager\ndef _get_cask_install_lines(output):\n    for line in output.split('\\n'):\n        line = line.strip()\n        if line.startswith('brew cask install'):\n            yield line\n\n\ndef _get_script_for_brew_cask(output):\n    cask_install_lines = _get_cask_install_lines(output)\n    if len(cask_install_lines) > 1:\n        return shell.and_(*cask_install_lines)\n    else:\n        return cask_install_lines[0]\n\n\ndef get_new_command(command):\n    brew_cask_script = _get_script_for_brew_cask(command.output)\n    return shell.and_(brew_cask_script, command.script)\n\n\nenabled_by_default = brew_available\n"
  },
  {
    "path": "thefuck/rules/brew_install.py",
    "content": "import re\nfrom thefuck.utils import for_app\nfrom thefuck.specific.brew import brew_available\n\nenabled_by_default = brew_available\n\n\ndef _get_suggestions(str):\n    suggestions = str.replace(\" or \", \", \").split(\", \")\n    return suggestions\n\n\n@for_app('brew', at_least=2)\ndef match(command):\n    is_proper_command = ('install' in command.script and\n                         'No available formula' in command.output and\n                         'Did you mean' in command.output)\n    return is_proper_command\n\n\ndef get_new_command(command):\n    matcher = re.search('Warning: No available formula with the name \"(?:[^\"]+)\". Did you mean (.+)\\\\?', command.output)\n    suggestions = _get_suggestions(matcher.group(1))\n    return [\"brew install \" + formula for formula in suggestions]\n"
  },
  {
    "path": "thefuck/rules/brew_link.py",
    "content": "from thefuck.utils import for_app\n\n\n@for_app('brew', at_least=2)\ndef match(command):\n    return (command.script_parts[1] in ['ln', 'link']\n            and \"brew link --overwrite --dry-run\" in command.output)\n\n\ndef get_new_command(command):\n    command_parts = command.script_parts[:]\n    command_parts[1] = 'link'\n    command_parts.insert(2, '--overwrite')\n    command_parts.insert(3, '--dry-run')\n    return ' '.join(command_parts)\n"
  },
  {
    "path": "thefuck/rules/brew_reinstall.py",
    "content": "import re\nfrom thefuck.utils import for_app\n\n\nwarning_regex = re.compile(r'Warning: (?:.(?!is ))+ is already installed and '\n                           r'up-to-date')\nmessage_regex = re.compile(r'To reinstall (?:(?!, ).)+, run `brew reinstall '\n                           r'[^`]+`')\n\n\n@for_app('brew', at_least=2)\ndef match(command):\n    return ('install' in command.script\n            and warning_regex.search(command.output)\n            and message_regex.search(command.output))\n\n\ndef get_new_command(command):\n    return command.script.replace('install', 'reinstall')\n"
  },
  {
    "path": "thefuck/rules/brew_uninstall.py",
    "content": "from thefuck.utils import for_app\n\n\n@for_app('brew', at_least=2)\ndef match(command):\n    return (command.script_parts[1] in ['uninstall', 'rm', 'remove']\n            and \"brew uninstall --force\" in command.output)\n\n\ndef get_new_command(command):\n    command_parts = command.script_parts[:]\n    command_parts[1] = 'uninstall'\n    command_parts.insert(2, '--force')\n    return ' '.join(command_parts)\n"
  },
  {
    "path": "thefuck/rules/brew_unknown_command.py",
    "content": "import os\nimport re\nfrom thefuck.utils import get_closest, replace_command\nfrom thefuck.specific.brew import get_brew_path_prefix, brew_available\n\nBREW_CMD_PATH = '/Homebrew/Library/Homebrew/cmd'\nTAP_PATH = '/Homebrew/Library/Taps'\nTAP_CMD_PATH = '/%s/%s/cmd'\n\nenabled_by_default = brew_available\n\n\ndef _get_brew_commands(brew_path_prefix):\n    \"\"\"To get brew default commands on local environment\"\"\"\n    brew_cmd_path = brew_path_prefix + BREW_CMD_PATH\n\n    return [name[:-3] for name in os.listdir(brew_cmd_path)\n            if name.endswith(('.rb', '.sh'))]\n\n\ndef _get_brew_tap_specific_commands(brew_path_prefix):\n    \"\"\"To get tap's specific commands\n    https://github.com/Homebrew/homebrew/blob/master/Library/brew.rb#L115\"\"\"\n    commands = []\n    brew_taps_path = brew_path_prefix + TAP_PATH\n\n    for user in _get_directory_names_only(brew_taps_path):\n        taps = _get_directory_names_only(brew_taps_path + '/%s' % user)\n\n        # Brew Taps's naming rule\n        # https://github.com/Homebrew/homebrew/blob/master/share/doc/homebrew/brew-tap.md#naming-conventions-and-limitations\n        taps = (tap for tap in taps if tap.startswith('homebrew-'))\n        for tap in taps:\n            tap_cmd_path = brew_taps_path + TAP_CMD_PATH % (user, tap)\n\n            if os.path.isdir(tap_cmd_path):\n                commands += (name.replace('brew-', '').replace('.rb', '')\n                             for name in os.listdir(tap_cmd_path)\n                             if _is_brew_tap_cmd_naming(name))\n\n    return commands\n\n\ndef _is_brew_tap_cmd_naming(name):\n    return name.startswith('brew-') and name.endswith('.rb')\n\n\ndef _get_directory_names_only(path):\n    return [d for d in os.listdir(path)\n            if os.path.isdir(os.path.join(path, d))]\n\n\ndef _brew_commands():\n    brew_path_prefix = get_brew_path_prefix()\n    if brew_path_prefix:\n        try:\n            return (_get_brew_commands(brew_path_prefix)\n                    + _get_brew_tap_specific_commands(brew_path_prefix))\n        except OSError:\n            pass\n\n    # Failback commands for testing (Based on Homebrew 0.9.5)\n    return ['info', 'home', 'options', 'install', 'uninstall',\n            'search', 'list', 'update', 'upgrade', 'pin', 'unpin',\n            'doctor', 'create', 'edit', 'cask']\n\n\ndef match(command):\n    is_proper_command = ('brew' in command.script and\n                         'Unknown command' in command.output)\n\n    if is_proper_command:\n        broken_cmd = re.findall(r'Error: Unknown command: ([a-z]+)',\n                                command.output)[0]\n        return bool(get_closest(broken_cmd, _brew_commands()))\n    return False\n\n\ndef get_new_command(command):\n    broken_cmd = re.findall(r'Error: Unknown command: ([a-z]+)',\n                            command.output)[0]\n    return replace_command(command, broken_cmd, _brew_commands())\n"
  },
  {
    "path": "thefuck/rules/brew_update_formula.py",
    "content": "from thefuck.utils import for_app\n\n\n@for_app('brew', at_least=2)\ndef match(command):\n    return ('update' in command.script\n            and \"Error: This command updates brew itself\" in command.output\n            and \"Use `brew upgrade\" in command.output)\n\n\ndef get_new_command(command):\n    return command.script.replace('update', 'upgrade')\n"
  },
  {
    "path": "thefuck/rules/cargo.py",
    "content": "def match(command):\n    return command.script == 'cargo'\n\n\ndef get_new_command(command):\n    return 'cargo build'\n"
  },
  {
    "path": "thefuck/rules/cargo_no_command.py",
    "content": "import re\nfrom thefuck.utils import replace_argument, for_app\n\n\n@for_app('cargo', at_least=1)\ndef match(command):\n    return ('no such subcommand' in command.output.lower()\n            and 'Did you mean' in command.output)\n\n\ndef get_new_command(command):\n    broken = command.script_parts[1]\n    fix = re.findall(r'Did you mean `([^`]*)`', command.output)[0]\n\n    return replace_argument(command.script, broken, fix)\n"
  },
  {
    "path": "thefuck/rules/cat_dir.py",
    "content": "import os\nfrom thefuck.utils import for_app\n\n\n@for_app('cat', at_least=1)\ndef match(command):\n    return (\n        command.output.startswith('cat: ') and\n        os.path.isdir(command.script_parts[1])\n    )\n\n\ndef get_new_command(command):\n    return command.script.replace('cat', 'ls', 1)\n"
  },
  {
    "path": "thefuck/rules/cd_correction.py",
    "content": "\"\"\"Attempts to spellcheck and correct failed cd commands\"\"\"\n\nimport os\nimport six\nfrom thefuck.specific.sudo import sudo_support\nfrom thefuck.rules import cd_mkdir\nfrom thefuck.utils import for_app, get_close_matches\n\n__author__ = \"mmussomele\"\n\nMAX_ALLOWED_DIFF = 0.6\n\n\ndef _get_sub_dirs(parent):\n    \"\"\"Returns a list of the child directories of the given parent directory\"\"\"\n    return [child for child in os.listdir(parent) if os.path.isdir(os.path.join(parent, child))]\n\n\n@sudo_support\n@for_app('cd')\ndef match(command):\n    \"\"\"Match function copied from cd_mkdir.py\"\"\"\n    return (\n        command.script.startswith('cd ') and any((\n            'no such file or directory' in command.output.lower(),\n            'cd: can\\'t cd to' in command.output.lower(),\n            'does not exist' in command.output.lower()\n        )))\n\n\n@sudo_support\ndef get_new_command(command):\n    \"\"\"\n    Attempt to rebuild the path string by spellchecking the directories.\n    If it fails (i.e. no directories are a close enough match), then it\n    defaults to the rules of cd_mkdir.\n    Change sensitivity by changing MAX_ALLOWED_DIFF. Default value is 0.6\n    \"\"\"\n    dest = command.script_parts[1].split(os.sep)\n    if dest[-1] == '':\n        dest = dest[:-1]\n\n    if dest[0] == '':\n        cwd = os.sep\n        dest = dest[1:]\n    elif six.PY2:\n        cwd = os.getcwdu()\n    else:\n        cwd = os.getcwd()\n    for directory in dest:\n        if directory == \".\":\n            continue\n        elif directory == \"..\":\n            cwd = os.path.split(cwd)[0]\n            continue\n        best_matches = get_close_matches(directory, _get_sub_dirs(cwd), cutoff=MAX_ALLOWED_DIFF)\n        if best_matches:\n            cwd = os.path.join(cwd, best_matches[0])\n        else:\n            return cd_mkdir.get_new_command(command)\n    return u'cd \"{0}\"'.format(cwd)\n"
  },
  {
    "path": "thefuck/rules/cd_cs.py",
    "content": "# -*- encoding: utf-8 -*-\n\n# Redirects cs to cd when there is a typo\n# Due to the proximity of the keys - d and s - this seems like a common typo\n# ~ > cs /etc/\n# cs: command not found\n# ~ > fuck\n# cd /etc/ [enter/↑/↓/ctrl+c]\n# /etc >\n\n\ndef match(command):\n    if command.script_parts[0] == 'cs':\n        return True\n\n\ndef get_new_command(command):\n    return 'cd' + ''.join(command.script[2:])\n\n\npriority = 900\n"
  },
  {
    "path": "thefuck/rules/cd_mkdir.py",
    "content": "import re\nfrom thefuck.utils import for_app\nfrom thefuck.specific.sudo import sudo_support\nfrom thefuck.shells import shell\n\n\n@sudo_support\n@for_app('cd')\ndef match(command):\n    return (\n        command.script.startswith('cd ') and any((\n            'no such file or directory' in command.output.lower(),\n            'cd: can\\'t cd to' in command.output.lower(),\n            'does not exist' in command.output.lower()\n        )))\n\n\n@sudo_support\ndef get_new_command(command):\n    repl = shell.and_('mkdir -p \\\\1', 'cd \\\\1')\n    return re.sub(r'^cd (.*)', repl, command.script)\n"
  },
  {
    "path": "thefuck/rules/cd_parent.py",
    "content": "# Adds the missing space between the cd command and the target directory\n# when trying to cd to the parent directory.\n#\n# Does not really save chars, but is fun :D\n#\n# Example:\n# > cd..\n# cd..: command not found\n\n\ndef match(command):\n    return command.script == 'cd..'\n\n\ndef get_new_command(command):\n    return 'cd ..'\n"
  },
  {
    "path": "thefuck/rules/chmod_x.py",
    "content": "import os\nfrom thefuck.shells import shell\n\n\ndef match(command):\n    return (command.script.startswith('./')\n            and 'permission denied' in command.output.lower()\n            and os.path.exists(command.script_parts[0])\n            and not os.access(command.script_parts[0], os.X_OK))\n\n\ndef get_new_command(command):\n    return shell.and_(\n        'chmod +x {}'.format(command.script_parts[0][2:]),\n        command.script)\n"
  },
  {
    "path": "thefuck/rules/choco_install.py",
    "content": "from thefuck.utils import for_app, which\n\n\n@for_app(\"choco\", \"cinst\")\ndef match(command):\n    return ((command.script.startswith('choco install') or 'cinst' in command.script_parts)\n            and 'Installing the following packages' in command.output)\n\n\ndef get_new_command(command):\n    # Find the argument that is the package name\n    for script_part in command.script_parts:\n        if (\n            script_part not in [\"choco\", \"cinst\", \"install\"]\n            # Need exact match (bc chocolatey is a package)\n            and not script_part.startswith('-')\n            # Leading hyphens are parameters; some packages contain them though\n            and '=' not in script_part and '/' not in script_part\n            # These are certainly parameters\n        ):\n            return command.script.replace(script_part, script_part + \".install\")\n    return []\n\n\nenabled_by_default = bool(which(\"choco\")) or bool(which(\"cinst\"))\n"
  },
  {
    "path": "thefuck/rules/composer_not_command.py",
    "content": "import re\nfrom thefuck.utils import replace_argument, for_app\n\n\n@for_app('composer')\ndef match(command):\n    return (('did you mean this?' in command.output.lower()\n             or 'did you mean one of these?' in command.output.lower())) or (\n        \"install\" in command.script_parts and \"composer require\" in command.output.lower()\n    )\n\n\ndef get_new_command(command):\n    if \"install\" in command.script_parts and \"composer require\" in command.output.lower():\n        broken_cmd, new_cmd = \"install\", \"require\"\n    else:\n        broken_cmd = re.findall(r\"Command \\\"([^']*)\\\" is not defined\", command.output)[0]\n        new_cmd = re.findall(r'Did you mean this\\?[^\\n]*\\n\\s*([^\\n]*)', command.output)\n        if not new_cmd:\n            new_cmd = re.findall(r'Did you mean one of these\\?[^\\n]*\\n\\s*([^\\n]*)', command.output)\n        new_cmd = new_cmd[0].strip()\n    return replace_argument(command.script, broken_cmd, new_cmd)\n"
  },
  {
    "path": "thefuck/rules/conda_mistype.py",
    "content": "import re\nfrom thefuck.utils import replace_command, for_app\n\n\n@for_app(\"conda\")\ndef match(command):\n    \"\"\"\n    Match a mistyped command\n    \"\"\"\n    return \"Did you mean 'conda\" in command.output\n\n\ndef get_new_command(command):\n    match = re.findall(r\"'conda ([^']*)'\", command.output)\n    broken_cmd = match[0]\n    correct_cmd = match[1]\n    return replace_command(command, broken_cmd, [correct_cmd])\n"
  },
  {
    "path": "thefuck/rules/cp_create_destination.py",
    "content": "from thefuck.shells import shell\nfrom thefuck.utils import for_app\n\n\n@for_app(\"cp\", \"mv\")\ndef match(command):\n    return (\n        \"No such file or directory\" in command.output\n        or command.output.startswith(\"cp: directory\")\n        and command.output.rstrip().endswith(\"does not exist\")\n    )\n\n\ndef get_new_command(command):\n    return shell.and_(u\"mkdir -p {}\".format(command.script_parts[-1]), command.script)\n"
  },
  {
    "path": "thefuck/rules/cp_omitting_directory.py",
    "content": "import re\nfrom thefuck.specific.sudo import sudo_support\nfrom thefuck.utils import for_app\n\n\n@sudo_support\n@for_app('cp')\ndef match(command):\n    output = command.output.lower()\n    return 'omitting directory' in output or 'is a directory' in output\n\n\n@sudo_support\ndef get_new_command(command):\n    return re.sub(r'^cp', 'cp -a', command.script)\n"
  },
  {
    "path": "thefuck/rules/cpp11.py",
    "content": "from thefuck.utils import for_app\n\n\n@for_app('g++', 'clang++')\ndef match(command):\n    return ('This file requires compiler and library support for the '\n            'ISO C++ 2011 standard.' in command.output or\n            '-Wc++11-extensions' in command.output)\n\n\ndef get_new_command(command):\n    return command.script + ' -std=c++11'\n"
  },
  {
    "path": "thefuck/rules/dirty_untar.py",
    "content": "import tarfile\nimport os\nfrom thefuck.utils import for_app\nfrom thefuck.shells import shell\n\n\ntar_extensions = ('.tar', '.tar.Z', '.tar.bz2', '.tar.gz', '.tar.lz',\n                  '.tar.lzma', '.tar.xz', '.taz', '.tb2', '.tbz', '.tbz2',\n                  '.tgz', '.tlz', '.txz', '.tz')\n\n\ndef _is_tar_extract(cmd):\n    if '--extract' in cmd:\n        return True\n\n    cmd = cmd.split()\n\n    return len(cmd) > 1 and 'x' in cmd[1]\n\n\ndef _tar_file(cmd):\n    for c in cmd:\n        for ext in tar_extensions:\n            if c.endswith(ext):\n                return (c, c[0:len(c) - len(ext)])\n\n\n@for_app('tar')\ndef match(command):\n    return ('-C' not in command.script\n            and _is_tar_extract(command.script)\n            and _tar_file(command.script_parts) is not None)\n\n\ndef get_new_command(command):\n    dir = shell.quote(_tar_file(command.script_parts)[1])\n    return shell.and_('mkdir -p {dir}', '{cmd} -C {dir}') \\\n        .format(dir=dir, cmd=command.script)\n\n\ndef side_effect(old_cmd, command):\n    with tarfile.TarFile(_tar_file(old_cmd.script_parts)[0]) as archive:\n        for file in archive.getnames():\n            if not os.path.abspath(file).startswith(os.getcwd()):\n                # it's unsafe to overwrite files outside of the current directory\n                continue\n\n            try:\n                os.remove(file)\n            except OSError:\n                # does not try to remove directories as we cannot know if they\n                # already existed before\n                pass\n"
  },
  {
    "path": "thefuck/rules/dirty_unzip.py",
    "content": "import os\nimport zipfile\nfrom thefuck.utils import for_app\nfrom thefuck.shells import shell\n\n\ndef _is_bad_zip(file):\n    try:\n        with zipfile.ZipFile(file, 'r') as archive:\n            return len(archive.namelist()) > 1\n    except Exception:\n        return False\n\n\ndef _zip_file(command):\n    # unzip works that way:\n    # unzip [-flags] file[.zip] [file(s) ...] [-x file(s) ...]\n    #                ^          ^ files to unzip from the archive\n    #                archive to unzip\n    for c in command.script_parts[1:]:\n        if not c.startswith('-'):\n            if c.endswith('.zip'):\n                return c\n            else:\n                return u'{}.zip'.format(c)\n\n\n@for_app('unzip')\ndef match(command):\n    if '-d' in command.script:\n        return False\n\n    zip_file = _zip_file(command)\n    if zip_file:\n        return _is_bad_zip(zip_file)\n    else:\n        return False\n\n\ndef get_new_command(command):\n    return u'{} -d {}'.format(\n        command.script, shell.quote(_zip_file(command)[:-4]))\n\n\ndef side_effect(old_cmd, command):\n    with zipfile.ZipFile(_zip_file(old_cmd), 'r') as archive:\n        for file in archive.namelist():\n            if not os.path.abspath(file).startswith(os.getcwd()):\n                # it's unsafe to overwrite files outside of the current directory\n                continue\n\n            try:\n                os.remove(file)\n            except OSError:\n                # does not try to remove directories as we cannot know if they\n                # already existed before\n                pass\n\n\nrequires_output = False\n"
  },
  {
    "path": "thefuck/rules/django_south_ghost.py",
    "content": "def match(command):\n    return 'manage.py' in command.script and \\\n           'migrate' in command.script \\\n           and 'or pass --delete-ghost-migrations' in command.output\n\n\ndef get_new_command(command):\n    return u'{} --delete-ghost-migrations'.format(command.script)\n"
  },
  {
    "path": "thefuck/rules/django_south_merge.py",
    "content": "def match(command):\n    return 'manage.py' in command.script and \\\n           'migrate' in command.script \\\n           and '--merge: will just attempt the migration' in command.output\n\n\ndef get_new_command(command):\n    return u'{} --merge'.format(command.script)\n"
  },
  {
    "path": "thefuck/rules/dnf_no_such_command.py",
    "content": "import subprocess\nimport re\nfrom thefuck.specific.sudo import sudo_support\nfrom thefuck.utils import for_app, replace_command\nfrom thefuck.specific.dnf import dnf_available\n\n\nregex = re.compile(r'No such command: (.*)\\.')\n\n\n@sudo_support\n@for_app('dnf')\ndef match(command):\n    return 'no such command' in command.output.lower()\n\n\ndef _parse_operations(help_text_lines):\n    operation_regex = re.compile(r'^([a-z-]+) +', re.MULTILINE)\n    return operation_regex.findall(help_text_lines)\n\n\ndef _get_operations():\n    proc = subprocess.Popen([\"dnf\", '--help'],\n                            stdout=subprocess.PIPE,\n                            stderr=subprocess.PIPE)\n    lines = proc.stdout.read().decode(\"utf-8\")\n\n    return _parse_operations(lines)\n\n\n@sudo_support\ndef get_new_command(command):\n    misspelled_command = regex.findall(command.output)[0]\n    return replace_command(command, misspelled_command, _get_operations())\n\n\nenabled_by_default = dnf_available\n"
  },
  {
    "path": "thefuck/rules/docker_image_being_used_by_container.py",
    "content": "from thefuck.utils import for_app\nfrom thefuck.shells import shell\n\n\n@for_app('docker')\ndef match(command):\n    '''\n    Matches a command's output with docker's output\n    warning you that you need to remove a container before removing an image.\n    '''\n    return 'image is being used by running container' in command.output\n\n\ndef get_new_command(command):\n    '''\n    Prepends docker container rm -f {container ID} to\n    the previous docker image rm {image ID} command\n    '''\n    container_id = command.output.strip().split(' ')\n    return shell.and_('docker container rm -f {}', '{}').format(container_id[-1], command.script)\n"
  },
  {
    "path": "thefuck/rules/docker_login.py",
    "content": "from thefuck.utils import for_app\nfrom thefuck.shells import shell\n\n\n@for_app('docker')\ndef match(command):\n    return ('docker' in command.script\n            and \"access denied\" in command.output\n            and \"may require 'docker login'\" in command.output)\n\n\ndef get_new_command(command):\n    return shell.and_('docker login', command.script)\n"
  },
  {
    "path": "thefuck/rules/docker_not_command.py",
    "content": "from itertools import dropwhile, takewhile, islice\nimport re\nimport subprocess\nfrom thefuck.utils import replace_command, for_app, which, cache\nfrom thefuck.specific.sudo import sudo_support\n\n\n@sudo_support\n@for_app('docker')\ndef match(command):\n    return 'is not a docker command' in command.output or 'Usage:\tdocker' in command.output\n\n\ndef _parse_commands(lines, starts_with):\n    lines = dropwhile(lambda line: not line.startswith(starts_with), lines)\n    lines = islice(lines, 1, None)\n    lines = list(takewhile(lambda line: line.strip(), lines))\n    return [line.strip().split(' ')[0] for line in lines]\n\n\ndef get_docker_commands():\n    proc = subprocess.Popen('docker', stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n\n    # Old version docker returns its output to stdout, while newer version returns to stderr.\n    lines = proc.stdout.readlines() or proc.stderr.readlines()\n    lines = [line.decode('utf-8') for line in lines]\n\n    # Only newer versions of docker have management commands in the help text.\n    if 'Management Commands:\\n' in lines:\n        management_commands = _parse_commands(lines, 'Management Commands:')\n    else:\n        management_commands = []\n    regular_commands = _parse_commands(lines, 'Commands:')\n    return management_commands + regular_commands\n\n\nif which('docker'):\n    get_docker_commands = cache(which('docker'))(get_docker_commands)\n\n\n@sudo_support\ndef get_new_command(command):\n    if 'Usage:' in command.output and len(command.script_parts) > 1:\n        management_subcommands = _parse_commands(command.output.split('\\n'), 'Commands:')\n        return replace_command(command, command.script_parts[2], management_subcommands)\n\n    wrong_command = re.findall(\n        r\"docker: '(\\w+)' is not a docker command.\", command.output)[0]\n    return replace_command(command, wrong_command, get_docker_commands())\n"
  },
  {
    "path": "thefuck/rules/dry.py",
    "content": "def match(command):\n    split_command = command.script_parts\n\n    return (split_command\n            and len(split_command) >= 2\n            and split_command[0] == split_command[1])\n\n\ndef get_new_command(command):\n    return ' '.join(command.script_parts[1:])\n\n\n# it should be rare enough to actually have to type twice the same word, so\n# this rule can have a higher priority to come before things like \"cd cd foo\"\npriority = 900\n"
  },
  {
    "path": "thefuck/rules/fab_command_not_found.py",
    "content": "from thefuck.utils import eager, get_closest, for_app\n\n\n@for_app('fab')\ndef match(command):\n    return 'Warning: Command(s) not found:' in command.output\n\n\n# We need different behavior then in get_all_matched_commands.\n@eager\ndef _get_between(content, start, end=None):\n    should_yield = False\n    for line in content.split('\\n'):\n        if start in line:\n            should_yield = True\n            continue\n\n        if end and end in line:\n            return\n\n        if should_yield and line:\n            yield line.strip().split(' ')[0]\n\n\ndef get_new_command(command):\n    not_found_commands = _get_between(\n        command.output, 'Warning: Command(s) not found:',\n        'Available commands:')\n    possible_commands = _get_between(\n        command.output, 'Available commands:')\n\n    script = command.script\n    for not_found in not_found_commands:\n        fix = get_closest(not_found, possible_commands)\n        script = script.replace(' {}'.format(not_found),\n                                ' {}'.format(fix))\n\n    return script\n"
  },
  {
    "path": "thefuck/rules/fix_alt_space.py",
    "content": "# -*- encoding: utf-8 -*-\n\nimport re\nfrom thefuck.specific.sudo import sudo_support\n\n\n@sudo_support\ndef match(command):\n    return ('command not found' in command.output.lower()\n            and u' ' in command.script)\n\n\n@sudo_support\ndef get_new_command(command):\n    return re.sub(u' ', ' ', command.script)\n"
  },
  {
    "path": "thefuck/rules/fix_file.py",
    "content": "import re\nimport os\nfrom thefuck.utils import memoize, default_settings\nfrom thefuck.conf import settings\nfrom thefuck.shells import shell\n\n\n# order is important: only the first match is considered\npatterns = (\n    # js, node:\n    '^    at {file}:{line}:{col}',\n    # cargo:\n    '^   {file}:{line}:{col}',\n    # python, thefuck:\n    '^  File \"{file}\", line {line}',\n    # awk:\n    '^awk: {file}:{line}:',\n    # git\n    '^fatal: bad config file line {line} in {file}',\n    # llc:\n    '^llc: {file}:{line}:{col}:',\n    # lua:\n    '^lua: {file}:{line}:',\n    # fish:\n    '^{file} \\\\(line {line}\\\\):',\n    # bash, sh, ssh:\n    '^{file}: line {line}: ',\n    # cargo, clang, gcc, go, pep8, rustc:\n    '^{file}:{line}:{col}',\n    # ghc, make, ruby, zsh:\n    '^{file}:{line}:',\n    # perl:\n    'at {file} line {line}',\n)\n\n\n# for the sake of readability do not use named groups above\ndef _make_pattern(pattern):\n    pattern = pattern.replace('{file}', '(?P<file>[^:\\n]+)') \\\n                     .replace('{line}', '(?P<line>[0-9]+)') \\\n                     .replace('{col}', '(?P<col>[0-9]+)')\n    return re.compile(pattern, re.MULTILINE)\n\n\npatterns = [_make_pattern(p).search for p in patterns]\n\n\n@memoize\ndef _search(output):\n    for pattern in patterns:\n        m = pattern(output)\n        if m and os.path.isfile(m.group('file')):\n            return m\n\n\ndef match(command):\n    if 'EDITOR' not in os.environ:\n        return False\n\n    return _search(command.output)\n\n\n@default_settings({'fixlinecmd': u'{editor} {file} +{line}',\n                   'fixcolcmd': None})\ndef get_new_command(command):\n    m = _search(command.output)\n\n    # Note: there does not seem to be a standard for columns, so they are just\n    # ignored by default\n    if settings.fixcolcmd and 'col' in m.groupdict():\n        editor_call = settings.fixcolcmd.format(editor=os.environ['EDITOR'],\n                                                file=m.group('file'),\n                                                line=m.group('line'),\n                                                col=m.group('col'))\n    else:\n        editor_call = settings.fixlinecmd.format(editor=os.environ['EDITOR'],\n                                                 file=m.group('file'),\n                                                 line=m.group('line'))\n\n    return shell.and_(editor_call, command.script)\n"
  },
  {
    "path": "thefuck/rules/gem_unknown_command.py",
    "content": "import re\nimport subprocess\nfrom thefuck.utils import for_app, eager, replace_command, cache, which\n\n\n@for_app('gem')\ndef match(command):\n    return ('ERROR:  While executing gem ... (Gem::CommandLineError)'\n            in command.output\n            and 'Unknown command' in command.output)\n\n\ndef _get_unknown_command(command):\n    return re.findall(r'Unknown command (.*)$', command.output)[0]\n\n\n@eager\ndef _get_all_commands():\n    proc = subprocess.Popen(['gem', 'help', 'commands'],\n                            stdout=subprocess.PIPE)\n\n    for line in proc.stdout.readlines():\n        line = line.decode()\n\n        if line.startswith('    '):\n            yield line.strip().split(' ')[0]\n\n\nif which('gem'):\n    _get_all_commands = cache(which('gem'))(_get_all_commands)\n\n\ndef get_new_command(command):\n    unknown_command = _get_unknown_command(command)\n    all_commands = _get_all_commands()\n    return replace_command(command, unknown_command, all_commands)\n"
  },
  {
    "path": "thefuck/rules/git_add.py",
    "content": "import re\nfrom thefuck.shells import shell\nfrom thefuck.specific.git import git_support\nfrom thefuck.system import Path\nfrom thefuck.utils import memoize\n\n\n@memoize\ndef _get_missing_file(command):\n    pathspec = re.findall(\n        r\"error: pathspec '([^']*)' \"\n        r'did not match any file\\(s\\) known to git.', command.output)[0]\n    if Path(pathspec).exists():\n        return pathspec\n\n\n@git_support\ndef match(command):\n    return ('did not match any file(s) known to git.' in command.output\n            and _get_missing_file(command))\n\n\n@git_support\ndef get_new_command(command):\n    missing_file = _get_missing_file(command)\n    formatme = shell.and_('git add -- {}', '{}')\n    return formatme.format(missing_file, command.script)\n"
  },
  {
    "path": "thefuck/rules/git_add_force.py",
    "content": "from thefuck.utils import replace_argument\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('add' in command.script_parts\n            and 'Use -f if you really want to add them.' in command.output)\n\n\n@git_support\ndef get_new_command(command):\n    return replace_argument(command.script, 'add', 'add --force')\n"
  },
  {
    "path": "thefuck/rules/git_bisect_usage.py",
    "content": "import re\nfrom thefuck.utils import replace_command\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('bisect' in command.script_parts and\n            'usage: git bisect' in command.output)\n\n\n@git_support\ndef get_new_command(command):\n    broken = re.findall(r'git bisect ([^ $]*).*', command.script)[0]\n    usage = re.findall(r'usage: git bisect \\[([^\\]]+)\\]', command.output)[0]\n    return replace_command(command, broken, usage.split('|'))\n"
  },
  {
    "path": "thefuck/rules/git_branch_0flag.py",
    "content": "from thefuck.shells import shell\nfrom thefuck.specific.git import git_support\nfrom thefuck.utils import memoize\n\n\n@memoize\ndef first_0flag(script_parts):\n    return next((p for p in script_parts if len(p) == 2 and p.startswith(\"0\")), None)\n\n\n@git_support\ndef match(command):\n    return command.script_parts[1] == \"branch\" and first_0flag(command.script_parts)\n\n\n@git_support\ndef get_new_command(command):\n    branch_name = first_0flag(command.script_parts)\n    fixed_flag = branch_name.replace(\"0\", \"-\")\n    fixed_script = command.script.replace(branch_name, fixed_flag)\n    if \"A branch named '\" in command.output and \"' already exists.\" in command.output:\n        delete_branch = u\"git branch -D {}\".format(branch_name)\n        return shell.and_(delete_branch, fixed_script)\n    return fixed_script\n"
  },
  {
    "path": "thefuck/rules/git_branch_delete.py",
    "content": "from thefuck.utils import replace_argument\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('branch -d' in command.script\n            and 'If you are sure you want to delete it' in command.output)\n\n\n@git_support\ndef get_new_command(command):\n    return replace_argument(command.script, '-d', '-D')\n"
  },
  {
    "path": "thefuck/rules/git_branch_delete_checked_out.py",
    "content": "from thefuck.shells import shell\nfrom thefuck.specific.git import git_support\nfrom thefuck.utils import replace_argument\n\n\n@git_support\ndef match(command):\n    return (\n        (\"branch -d\" in command.script or \"branch -D\" in command.script)\n        and \"error: Cannot delete branch '\" in command.output\n        and \"' checked out at '\" in command.output\n    )\n\n\n@git_support\ndef get_new_command(command):\n    return shell.and_(\"git checkout master\", \"{}\").format(\n        replace_argument(command.script, \"-d\", \"-D\")\n    )\n"
  },
  {
    "path": "thefuck/rules/git_branch_exists.py",
    "content": "import re\nfrom thefuck.shells import shell\nfrom thefuck.specific.git import git_support\nfrom thefuck.utils import eager\n\n\n@git_support\ndef match(command):\n    return (\"fatal: A branch named '\" in command.output\n            and \"' already exists.\" in command.output)\n\n\n@git_support\n@eager\ndef get_new_command(command):\n    branch_name = re.findall(\n        r\"fatal: A branch named '(.+)' already exists.\", command.output)[0]\n    branch_name = branch_name.replace(\"'\", r\"\\'\")\n    new_command_templates = [['git branch -d {0}', 'git branch {0}'],\n                             ['git branch -d {0}', 'git checkout -b {0}'],\n                             ['git branch -D {0}', 'git branch {0}'],\n                             ['git branch -D {0}', 'git checkout -b {0}'],\n                             ['git checkout {0}']]\n    for new_command_template in new_command_templates:\n        yield shell.and_(*new_command_template).format(branch_name)\n"
  },
  {
    "path": "thefuck/rules/git_branch_list.py",
    "content": "from thefuck.shells import shell\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    # catches \"git branch list\" in place of \"git branch\"\n    return (command.script_parts\n            and command.script_parts[1:] == 'branch list'.split())\n\n\n@git_support\ndef get_new_command(command):\n    return shell.and_('git branch --delete list', 'git branch')\n"
  },
  {
    "path": "thefuck/rules/git_checkout.py",
    "content": "import re\nimport subprocess\nfrom thefuck import utils\nfrom thefuck.utils import replace_argument\nfrom thefuck.specific.git import git_support\nfrom thefuck.shells import shell\n\n\n@git_support\ndef match(command):\n    return ('did not match any file(s) known to git' in command.output\n            and \"Did you forget to 'git add'?\" not in command.output)\n\n\ndef get_branches():\n    proc = subprocess.Popen(\n        ['git', 'branch', '-a', '--no-color', '--no-column'],\n        stdout=subprocess.PIPE)\n    for line in proc.stdout.readlines():\n        line = line.decode('utf-8')\n        if '->' in line:    # Remote HEAD like b'  remotes/origin/HEAD -> origin/master'\n            continue\n        if line.startswith('*'):\n            line = line.split(' ')[1]\n        if line.strip().startswith('remotes/'):\n            line = '/'.join(line.split('/')[2:])\n        yield line.strip()\n\n\n@git_support\ndef get_new_command(command):\n    missing_file = re.findall(\n        r\"error: pathspec '([^']*)' \"\n        r\"did not match any file\\(s\\) known to git\", command.output)[0]\n    closest_branch = utils.get_closest(missing_file, get_branches(),\n                                       fallback_to_first=False)\n\n    new_commands = []\n\n    if closest_branch:\n        new_commands.append(replace_argument(command.script, missing_file, closest_branch))\n    if command.script_parts[1] == 'checkout':\n        new_commands.append(replace_argument(command.script, 'checkout', 'checkout -b'))\n\n    if not new_commands:\n        new_commands.append(shell.and_('git branch {}', '{}').format(\n            missing_file, command.script))\n\n    return new_commands\n"
  },
  {
    "path": "thefuck/rules/git_clone_git_clone.py",
    "content": "from thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return (' git clone ' in command.script\n            and 'fatal: Too many arguments.' in command.output)\n\n\n@git_support\ndef get_new_command(command):\n    return command.script.replace(' git clone ', ' ', 1)\n"
  },
  {
    "path": "thefuck/rules/git_clone_missing.py",
    "content": "'''\nRule: git_clone_missing\n\nCorrect missing `git clone` command when pasting a git URL\n\n```sh\n>>> https://github.com/nvbn/thefuck.git\ngit clone https://github.com/nvbn/thefuck.git\n```\n\nAuthor: Miguel Guthridge\n'''\nfrom six.moves.urllib import parse\nfrom thefuck.utils import which\n\n\ndef match(command):\n    # We want it to be a URL by itself\n    if len(command.script_parts) != 1:\n        return False\n    # Ensure we got the error we expected\n    if which(command.script_parts[0]) or not (\n        'No such file or directory' in command.output\n        or 'not found' in command.output\n        or 'is not recognised as' in command.output\n    ):\n        return False\n    url = parse.urlparse(command.script, scheme='ssh')\n    # HTTP URLs need a network address\n    if not url.netloc and url.scheme != 'ssh':\n        return False\n    # SSH needs a username and a splitter between the path\n    if url.scheme == 'ssh' and not (\n        '@' in command.script\n        and ':' in command.script\n    ):\n        return False\n    return url.scheme in ['http', 'https', 'ssh']\n\n\ndef get_new_command(command):\n    return 'git clone ' + command.script\n"
  },
  {
    "path": "thefuck/rules/git_commit_add.py",
    "content": "from thefuck.utils import eager, replace_argument\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return (\n        \"commit\" in command.script_parts\n        and \"no changes added to commit\" in command.output\n    )\n\n\n@eager\n@git_support\ndef get_new_command(command):\n    for opt in (\"-a\", \"-p\"):\n        yield replace_argument(command.script, \"commit\", \"commit {}\".format(opt))\n"
  },
  {
    "path": "thefuck/rules/git_commit_amend.py",
    "content": "from thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('commit' in command.script_parts)\n\n\n@git_support\ndef get_new_command(command):\n    return 'git commit --amend'\n"
  },
  {
    "path": "thefuck/rules/git_commit_reset.py",
    "content": "from thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('commit' in command.script_parts)\n\n\n@git_support\ndef get_new_command(command):\n    return 'git reset HEAD~'\n"
  },
  {
    "path": "thefuck/rules/git_diff_no_index.py",
    "content": "from thefuck.utils import replace_argument\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    files = [arg for arg in command.script_parts[2:]\n             if not arg.startswith('-')]\n    return ('diff' in command.script\n            and '--no-index' not in command.script\n            and len(files) == 2)\n\n\n@git_support\ndef get_new_command(command):\n    return replace_argument(command.script, 'diff', 'diff --no-index')\n"
  },
  {
    "path": "thefuck/rules/git_diff_staged.py",
    "content": "from thefuck.utils import replace_argument\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('diff' in command.script and\n            '--staged' not in command.script)\n\n\n@git_support\ndef get_new_command(command):\n    return replace_argument(command.script, 'diff', 'diff --staged')\n"
  },
  {
    "path": "thefuck/rules/git_fix_stash.py",
    "content": "from thefuck import utils\nfrom thefuck.utils import replace_argument\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    if command.script_parts and len(command.script_parts) > 1:\n        return (command.script_parts[1] == 'stash'\n                and 'usage:' in command.output)\n    else:\n        return False\n\n\n# git's output here is too complicated to be parsed (see the test file)\nstash_commands = (\n    'apply',\n    'branch',\n    'clear',\n    'drop',\n    'list',\n    'pop',\n    'save',\n    'show')\n\n\n@git_support\ndef get_new_command(command):\n    stash_cmd = command.script_parts[2]\n    fixed = utils.get_closest(stash_cmd, stash_commands, fallback_to_first=False)\n\n    if fixed is not None:\n        return replace_argument(command.script, stash_cmd, fixed)\n    else:\n        cmd = command.script_parts[:]\n        cmd.insert(2, 'save')\n        return ' '.join(cmd)\n"
  },
  {
    "path": "thefuck/rules/git_flag_after_filename.py",
    "content": "import re\nfrom thefuck.specific.git import git_support\n\nerror_pattern = \"fatal: bad flag '(.*?)' used after filename\"\nerror_pattern2 = \"fatal: option '(.*?)' must come before non-option arguments\"\n\n\n@git_support\ndef match(command):\n    return re.search(error_pattern, command.output) or re.search(error_pattern2, command.output)\n\n\n@git_support\ndef get_new_command(command):\n    command_parts = command.script_parts[:]\n\n    # find the bad flag\n    bad_flag = match(command).group(1)\n    bad_flag_index = command_parts.index(bad_flag)\n\n    # find the filename\n    for index in reversed(range(bad_flag_index)):\n        if command_parts[index][0] != '-':\n            filename_index = index\n            break\n\n    # swap them\n    command_parts[bad_flag_index], command_parts[filename_index] = \\\n    command_parts[filename_index], command_parts[bad_flag_index]  # noqa: E122\n\n    return u' '.join(command_parts)\n"
  },
  {
    "path": "thefuck/rules/git_help_aliased.py",
    "content": "from thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return 'help' in command.script and ' is aliased to ' in command.output\n\n\n@git_support\ndef get_new_command(command):\n    aliased = command.output.split('`', 2)[2].split(\"'\", 1)[0].split(' ', 1)[0]\n    return 'git help {}'.format(aliased)\n"
  },
  {
    "path": "thefuck/rules/git_hook_bypass.py",
    "content": "from thefuck.utils import replace_argument\nfrom thefuck.specific.git import git_support\n\nhooked_commands = (\"am\", \"commit\", \"push\")\n\n\n@git_support\ndef match(command):\n    return any(\n        hooked_command in command.script_parts for hooked_command in hooked_commands\n    )\n\n\n@git_support\ndef get_new_command(command):\n    hooked_command = next(\n        hooked_command\n        for hooked_command in hooked_commands\n        if hooked_command in command.script_parts\n    )\n    return replace_argument(\n        command.script, hooked_command, hooked_command + \" --no-verify\"\n    )\n\n\npriority = 1100\nrequires_output = False\n"
  },
  {
    "path": "thefuck/rules/git_lfs_mistype.py",
    "content": "import re\nfrom thefuck.utils import get_all_matched_commands, replace_command\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    '''\n    Match a mistyped command\n    '''\n    return 'lfs' in command.script and 'Did you mean this?' in command.output\n\n\n@git_support\ndef get_new_command(command):\n    broken_cmd = re.findall(r'Error: unknown command \"([^\"]*)\" for \"git-lfs\"', command.output)[0]\n    matched = get_all_matched_commands(command.output, ['Did you mean', ' for usage.'])\n    return replace_command(command, broken_cmd, matched)\n"
  },
  {
    "path": "thefuck/rules/git_main_master.py",
    "content": "from thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return \"'master'\" in command.output or \"'main'\" in command.output\n\n\n@git_support\ndef get_new_command(command):\n    if \"'master'\" in command.output:\n        return command.script.replace(\"master\", \"main\")\n    return command.script.replace(\"main\", \"master\")\n\n\npriority = 1200\n"
  },
  {
    "path": "thefuck/rules/git_merge.py",
    "content": "import re\nfrom thefuck.utils import replace_argument\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('merge' in command.script\n            and ' - not something we can merge' in command.output\n            and 'Did you mean this?' in command.output)\n\n\n@git_support\ndef get_new_command(command):\n    unknown_branch = re.findall(r'merge: (.+) - not something we can merge', command.output)[0]\n    remote_branch = re.findall(r'Did you mean this\\?\\n\\t([^\\n]+)', command.output)[0]\n\n    return replace_argument(command.script, unknown_branch, remote_branch)\n"
  },
  {
    "path": "thefuck/rules/git_merge_unrelated.py",
    "content": "from thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('merge' in command.script\n            and 'fatal: refusing to merge unrelated histories' in command.output)\n\n\n@git_support\ndef get_new_command(command):\n    return command.script + ' --allow-unrelated-histories'\n"
  },
  {
    "path": "thefuck/rules/git_not_command.py",
    "content": "import re\nfrom thefuck.utils import get_all_matched_commands, replace_command\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return (\" is not a git command. See 'git --help'.\" in command.output\n            and ('The most similar command' in command.output\n                 or 'Did you mean' in command.output))\n\n\n@git_support\ndef get_new_command(command):\n    broken_cmd = re.findall(r\"git: '([^']*)' is not a git command\",\n                            command.output)[0]\n    matched = get_all_matched_commands(command.output, ['The most similar command', 'Did you mean'])\n    return replace_command(command, broken_cmd, matched)\n"
  },
  {
    "path": "thefuck/rules/git_pull.py",
    "content": "from thefuck.shells import shell\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return 'pull' in command.script and 'set-upstream' in command.output\n\n\n@git_support\ndef get_new_command(command):\n    line = command.output.split('\\n')[-3].strip()\n    branch = line.split(' ')[-1]\n    set_upstream = line.replace('<remote>', 'origin')\\\n                       .replace('<branch>', branch)\n    return shell.and_(set_upstream, command.script)\n"
  },
  {
    "path": "thefuck/rules/git_pull_clone.py",
    "content": "from thefuck.utils import replace_argument\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('fatal: Not a git repository' in command.output\n            and \"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).\" in command.output)\n\n\n@git_support\ndef get_new_command(command):\n    return replace_argument(command.script, 'pull', 'clone')\n"
  },
  {
    "path": "thefuck/rules/git_pull_uncommitted_changes.py",
    "content": "from thefuck.shells import shell\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('pull' in command.script\n            and ('You have unstaged changes' in command.output\n                 or 'contains uncommitted changes' in command.output))\n\n\n@git_support\ndef get_new_command(command):\n    return shell.and_('git stash', 'git pull', 'git stash pop')\n"
  },
  {
    "path": "thefuck/rules/git_push.py",
    "content": "import re\nfrom thefuck.utils import replace_argument\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('push' in command.script_parts\n            and 'git push --set-upstream' in command.output)\n\n\ndef _get_upstream_option_index(command_parts):\n    if '--set-upstream' in command_parts:\n        return command_parts.index('--set-upstream')\n    elif '-u' in command_parts:\n        return command_parts.index('-u')\n    else:\n        return None\n\n\n@git_support\ndef get_new_command(command):\n    # If --set-upstream or -u are passed, remove it and its argument. This is\n    # because the remaining arguments are concatenated onto the command suggested\n    # by git, which includes --set-upstream and its argument\n    command_parts = command.script_parts[:]\n    upstream_option_index = _get_upstream_option_index(command_parts)\n\n    if upstream_option_index is not None:\n        command_parts.pop(upstream_option_index)\n\n        # In case of `git push -u` we don't have next argument:\n        if len(command_parts) > upstream_option_index:\n            command_parts.pop(upstream_option_index)\n    else:\n        # the only non-qualified permitted options are the repository and refspec; git's\n        # suggestion include them, so they won't be lost, but would be duplicated otherwise.\n        push_idx = command_parts.index('push') + 1\n        while len(command_parts) > push_idx and command_parts[len(command_parts) - 1][0] != '-':\n            command_parts.pop(len(command_parts) - 1)\n\n    arguments = re.findall(r'git push (.*)', command.output)[-1].replace(\"'\", r\"\\'\").strip()\n    return replace_argument(\" \".join(command_parts), 'push',\n                            'push {}'.format(arguments))\n"
  },
  {
    "path": "thefuck/rules/git_push_different_branch_names.py",
    "content": "import re\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return \"push\" in command.script and \"The upstream branch of your current branch does not match\" in command.output\n\n\n@git_support\ndef get_new_command(command):\n    return re.findall(r'^ +(git push [^\\s]+ [^\\s]+)', command.output, re.MULTILINE)[0]\n"
  },
  {
    "path": "thefuck/rules/git_push_force.py",
    "content": "from thefuck.utils import replace_argument\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('push' in command.script\n            and '! [rejected]' in command.output\n            and 'failed to push some refs to' in command.output\n            and 'Updates were rejected because the tip of your current branch is behind' in command.output)\n\n\n@git_support\ndef get_new_command(command):\n    return replace_argument(command.script, 'push', 'push --force-with-lease')\n\n\nenabled_by_default = False\n"
  },
  {
    "path": "thefuck/rules/git_push_pull.py",
    "content": "from thefuck.shells import shell\nfrom thefuck.utils import replace_argument\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('push' in command.script and\n            '! [rejected]' in command.output and\n            'failed to push some refs to' in command.output and\n            ('Updates were rejected because the tip of your'\n             ' current branch is behind' in command.output or\n             'Updates were rejected because the remote '\n             'contains work that you do' in command.output))\n\n\n@git_support\ndef get_new_command(command):\n    return shell.and_(replace_argument(command.script, 'push', 'pull'),\n                      command.script)\n"
  },
  {
    "path": "thefuck/rules/git_push_without_commits.py",
    "content": "import re\nfrom thefuck.shells import shell\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return bool(re.search(r\"src refspec \\w+ does not match any\", command.output))\n\n\ndef get_new_command(command):\n    return shell.and_('git commit -m \"Initial commit\"', command.script)\n"
  },
  {
    "path": "thefuck/rules/git_rebase_merge_dir.py",
    "content": "from thefuck.utils import get_close_matches\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return (' rebase' in command.script and\n            'It seems that there is already a rebase-merge directory' in command.output and\n            'I wonder if you are in the middle of another rebase' in command.output)\n\n\n@git_support\ndef get_new_command(command):\n    command_list = ['git rebase --continue', 'git rebase --abort', 'git rebase --skip']\n    rm_cmd = command.output.split('\\n')[-4]\n    command_list.append(rm_cmd.strip())\n    return get_close_matches(command.script, command_list, 4, 0)\n"
  },
  {
    "path": "thefuck/rules/git_rebase_no_changes.py",
    "content": "from thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return (\n        {'rebase', '--continue'}.issubset(command.script_parts) and\n        'No changes - did you forget to use \\'git add\\'?' in command.output\n    )\n\n\ndef get_new_command(command):\n    return 'git rebase --skip'\n"
  },
  {
    "path": "thefuck/rules/git_remote_delete.py",
    "content": "import re\n\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return \"remote delete\" in command.script\n\n\n@git_support\ndef get_new_command(command):\n    return re.sub(r\"delete\", \"remove\", command.script, 1)\n"
  },
  {
    "path": "thefuck/rules/git_remote_seturl_add.py",
    "content": "from thefuck.utils import replace_argument\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('set-url' in command.script\n            and 'fatal: No such remote' in command.output)\n\n\ndef get_new_command(command):\n    return replace_argument(command.script, 'set-url', 'add')\n"
  },
  {
    "path": "thefuck/rules/git_rm_local_modifications.py",
    "content": "from thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return (' rm ' in command.script and\n            'error: the following file has local modifications' in command.output and\n            'use --cached to keep the file, or -f to force removal' in command.output)\n\n\n@git_support\ndef get_new_command(command):\n    command_parts = command.script_parts[:]\n    index = command_parts.index('rm') + 1\n    command_parts.insert(index, '--cached')\n    command_list = [u' '.join(command_parts)]\n    command_parts[index] = '-f'\n    command_list.append(u' '.join(command_parts))\n    return command_list\n"
  },
  {
    "path": "thefuck/rules/git_rm_recursive.py",
    "content": "from thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return (' rm ' in command.script\n            and \"fatal: not removing '\" in command.output\n            and \"' recursively without -r\" in command.output)\n\n\n@git_support\ndef get_new_command(command):\n    command_parts = command.script_parts[:]\n    index = command_parts.index('rm') + 1\n    command_parts.insert(index, '-r')\n    return u' '.join(command_parts)\n"
  },
  {
    "path": "thefuck/rules/git_rm_staged.py",
    "content": "from thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return (' rm ' in command.script and\n            'error: the following file has changes staged in the index' in command.output and\n            'use --cached to keep the file, or -f to force removal' in command.output)\n\n\n@git_support\ndef get_new_command(command):\n    command_parts = command.script_parts[:]\n    index = command_parts.index('rm') + 1\n    command_parts.insert(index, '--cached')\n    command_list = [u' '.join(command_parts)]\n    command_parts[index] = '-f'\n    command_list.append(u' '.join(command_parts))\n    return command_list\n"
  },
  {
    "path": "thefuck/rules/git_stash.py",
    "content": "from thefuck.shells import shell\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    # catches \"Please commit or stash them\" and \"Please, commit your changes or\n    # stash them before you can switch branches.\"\n    return 'or stash them' in command.output\n\n\n@git_support\ndef get_new_command(command):\n    formatme = shell.and_('git stash', '{}')\n    return formatme.format(command.script)\n"
  },
  {
    "path": "thefuck/rules/git_stash_pop.py",
    "content": "from thefuck.shells import shell\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('stash' in command.script\n            and 'pop' in command.script\n            and 'Your local changes to the following files would be overwritten by merge' in command.output)\n\n\n@git_support\ndef get_new_command(command):\n    return shell.and_('git add --update', 'git stash pop', 'git reset .')\n\n\n# make it come before the other applicable rules\npriority = 900\n"
  },
  {
    "path": "thefuck/rules/git_tag_force.py",
    "content": "from thefuck.utils import replace_argument\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('tag' in command.script_parts\n            and 'already exists' in command.output)\n\n\n@git_support\ndef get_new_command(command):\n    return replace_argument(command.script, 'tag', 'tag --force')\n"
  },
  {
    "path": "thefuck/rules/git_two_dashes.py",
    "content": "from thefuck.utils import replace_argument\nfrom thefuck.specific.git import git_support\n\n\n@git_support\ndef match(command):\n    return ('error: did you mean `' in command.output\n            and '` (with two dashes ?)' in command.output)\n\n\n@git_support\ndef get_new_command(command):\n    to = command.output.split('`')[1]\n    return replace_argument(command.script, to[1:], to)\n"
  },
  {
    "path": "thefuck/rules/go_run.py",
    "content": "from thefuck.utils import for_app\n# Appends .go when compiling go files\n#\n# Example:\n# > go run foo\n# error: go run: no go files listed\n\n\n@for_app('go')\ndef match(command):\n    return (command.script.startswith('go run ')\n            and not command.script.endswith('.go'))\n\n\ndef get_new_command(command):\n    return command.script + '.go'\n"
  },
  {
    "path": "thefuck/rules/go_unknown_command.py",
    "content": "from itertools import dropwhile, islice, takewhile\nimport subprocess\n\nfrom thefuck.utils import get_closest, replace_argument, for_app, which, cache\n\n\ndef get_golang_commands():\n    proc = subprocess.Popen('go', stderr=subprocess.PIPE)\n    lines = [line.decode('utf-8').strip() for line in proc.stderr.readlines()]\n    lines = dropwhile(lambda line: line != 'The commands are:', lines)\n    lines = islice(lines, 2, None)\n    lines = takewhile(lambda line: line, lines)\n    return [line.split(' ')[0] for line in lines]\n\n\nif which('go'):\n    get_golang_commands = cache(which('go'))(get_golang_commands)\n\n\n@for_app('go')\ndef match(command):\n    return 'unknown command' in command.output\n\n\ndef get_new_command(command):\n    closest_subcommand = get_closest(command.script_parts[1], get_golang_commands())\n    return replace_argument(command.script, command.script_parts[1],\n                            closest_subcommand)\n"
  },
  {
    "path": "thefuck/rules/gradle_no_task.py",
    "content": "import re\nfrom subprocess import Popen, PIPE\nfrom thefuck.utils import for_app, eager, replace_command\n\nregex = re.compile(r\"Task '(.*)' (is ambiguous|not found)\")\n\n\n@for_app('gradle', 'gradlew')\ndef match(command):\n    return regex.findall(command.output)\n\n\n@eager\ndef _get_all_tasks(gradle):\n    proc = Popen([gradle, 'tasks'], stdout=PIPE)\n    should_yield = False\n    for line in proc.stdout.readlines():\n        line = line.decode().strip()\n        if line.startswith('----'):\n            should_yield = True\n            continue\n\n        if not line.strip():\n            should_yield = False\n            continue\n\n        if should_yield and not line.startswith('All tasks runnable from root project'):\n            yield line.split(' ')[0]\n\n\ndef get_new_command(command):\n    wrong_task = regex.findall(command.output)[0][0]\n    all_tasks = _get_all_tasks(command.script_parts[0])\n    return replace_command(command, wrong_task, all_tasks)\n"
  },
  {
    "path": "thefuck/rules/gradle_wrapper.py",
    "content": "import os\nfrom thefuck.utils import for_app, which\n\n\n@for_app('gradle')\ndef match(command):\n    return (not which(command.script_parts[0])\n            and 'not found' in command.output\n            and os.path.isfile('gradlew'))\n\n\ndef get_new_command(command):\n    return u'./gradlew {}'.format(' '.join(command.script_parts[1:]))\n"
  },
  {
    "path": "thefuck/rules/grep_arguments_order.py",
    "content": "import os\nfrom thefuck.utils import for_app\n\n\ndef _get_actual_file(parts):\n    for part in parts[1:]:\n        if os.path.isfile(part) or os.path.isdir(part):\n            return part\n\n\n@for_app('grep', 'egrep')\ndef match(command):\n    return ': No such file or directory' in command.output \\\n        and _get_actual_file(command.script_parts)\n\n\ndef get_new_command(command):\n    actual_file = _get_actual_file(command.script_parts)\n    parts = command.script_parts[::]\n    # Moves file to the end of the script:\n    parts.remove(actual_file)\n    parts.append(actual_file)\n    return ' '.join(parts)\n"
  },
  {
    "path": "thefuck/rules/grep_recursive.py",
    "content": "from thefuck.utils import for_app\n\n\n@for_app('grep')\ndef match(command):\n    return 'is a directory' in command.output.lower()\n\n\ndef get_new_command(command):\n    return u'grep -r {}'.format(command.script[5:])\n"
  },
  {
    "path": "thefuck/rules/grunt_task_not_found.py",
    "content": "import re\nfrom subprocess import Popen, PIPE\nfrom thefuck.utils import for_app, eager, get_closest, cache\n\nregex = re.compile(r'Warning: Task \"(.*)\" not found.')\n\n\n@for_app('grunt')\ndef match(command):\n    return regex.findall(command.output)\n\n\n@cache('Gruntfile.js')\n@eager\ndef _get_all_tasks():\n    proc = Popen(['grunt', '--help'], stdout=PIPE)\n    should_yield = False\n    for line in proc.stdout.readlines():\n        line = line.decode().strip()\n\n        if 'Available tasks' in line:\n            should_yield = True\n            continue\n\n        if should_yield and not line:\n            return\n\n        if '  ' in line:\n            yield line.split(' ')[0]\n\n\ndef get_new_command(command):\n    misspelled_task = regex.findall(command.output)[0].split(':')[0]\n    tasks = _get_all_tasks()\n    fixed = get_closest(misspelled_task, tasks)\n    return command.script.replace(' {}'.format(misspelled_task),\n                                  ' {}'.format(fixed))\n"
  },
  {
    "path": "thefuck/rules/gulp_not_task.py",
    "content": "import re\nimport subprocess\nfrom thefuck.utils import replace_command, for_app, cache\n\n\n@for_app('gulp')\ndef match(command):\n    return 'is not in your gulpfile' in command.output\n\n\n@cache('gulpfile.js')\ndef get_gulp_tasks():\n    proc = subprocess.Popen(['gulp', '--tasks-simple'],\n                            stdout=subprocess.PIPE)\n    return [line.decode('utf-8')[:-1]\n            for line in proc.stdout.readlines()]\n\n\ndef get_new_command(command):\n    wrong_task = re.findall(r\"Task '(\\w+)' is not in your gulpfile\",\n                            command.output)[0]\n    return replace_command(command, wrong_task, get_gulp_tasks())\n"
  },
  {
    "path": "thefuck/rules/has_exists_script.py",
    "content": "import os\nfrom thefuck.specific.sudo import sudo_support\n\n\n@sudo_support\ndef match(command):\n    return command.script_parts and os.path.exists(command.script_parts[0]) \\\n        and 'command not found' in command.output\n\n\n@sudo_support\ndef get_new_command(command):\n    return u'./{}'.format(command.script)\n"
  },
  {
    "path": "thefuck/rules/heroku_multiple_apps.py",
    "content": "import re\nfrom thefuck.utils import for_app\n\n\n@for_app('heroku')\ndef match(command):\n    return 'https://devcenter.heroku.com/articles/multiple-environments' in command.output\n\n\ndef get_new_command(command):\n    apps = re.findall('([^ ]*) \\\\([^)]*\\\\)', command.output)\n    return [command.script + ' --app ' + app for app in apps]\n"
  },
  {
    "path": "thefuck/rules/heroku_not_command.py",
    "content": "import re\nfrom thefuck.utils import for_app\n\n\n@for_app('heroku')\ndef match(command):\n    return 'Run heroku _ to run' in command.output\n\n\ndef get_new_command(command):\n    return re.findall('Run heroku _ to run ([^.]*)', command.output)[0]\n"
  },
  {
    "path": "thefuck/rules/history.py",
    "content": "from thefuck.utils import get_close_matches, get_closest, \\\n    get_valid_history_without_current\n\n\ndef match(command):\n    return len(get_close_matches(command.script,\n                                 get_valid_history_without_current(command)))\n\n\ndef get_new_command(command):\n    return get_closest(command.script,\n                       get_valid_history_without_current(command))\n\n\npriority = 9999\n"
  },
  {
    "path": "thefuck/rules/hostscli.py",
    "content": "import re\nfrom thefuck.specific.sudo import sudo_support\nfrom thefuck.utils import replace_command, for_app\n\nno_command = \"Error: No such command\"\nno_website = \"hostscli.errors.WebsiteImportError\"\n\n\n@sudo_support\n@for_app('hostscli')\ndef match(command):\n    errors = [no_command, no_website]\n    for error in errors:\n        if error in command.output:\n            return True\n    return False\n\n\n@sudo_support\ndef get_new_command(command):\n    if no_website in command.output:\n        return ['hostscli websites']\n\n    misspelled_command = re.findall(\n        r'Error: No such command \".*\"', command.output)[0]\n    commands = ['block', 'unblock', 'websites', 'block_all', 'unblock_all']\n    return replace_command(command, misspelled_command, commands)\n"
  },
  {
    "path": "thefuck/rules/ifconfig_device_not_found.py",
    "content": "import subprocess\nfrom thefuck.utils import for_app, replace_command, eager\n\n\n@for_app('ifconfig')\ndef match(command):\n    return 'error fetching interface information: Device not found' \\\n           in command.output\n\n\n@eager\ndef _get_possible_interfaces():\n    proc = subprocess.Popen(['ifconfig', '-a'], stdout=subprocess.PIPE)\n    for line in proc.stdout.readlines():\n        line = line.decode()\n        if line and line != '\\n' and not line.startswith(' '):\n            yield line.split(' ')[0]\n\n\ndef get_new_command(command):\n    interface = command.output.split(' ')[0][:-1]\n    possible_interfaces = _get_possible_interfaces()\n    return replace_command(command, interface, possible_interfaces)\n"
  },
  {
    "path": "thefuck/rules/java.py",
    "content": "\"\"\"Fixes common java command mistake\n\nExample:\n> java foo.java\nError: Could not find or load main class foo.java\n\n\"\"\"\nfrom thefuck.utils import for_app\n\n\n@for_app('java')\ndef match(command):\n    return command.script.endswith('.java')\n\n\ndef get_new_command(command):\n    return command.script[:-5]\n"
  },
  {
    "path": "thefuck/rules/javac.py",
    "content": "\"\"\"Appends .java when compiling java files\n\nExample:\n > javac foo\n error: Class names, 'foo', are only accepted if annotation\n processing is explicitly requested\n\n\"\"\"\nfrom thefuck.utils import for_app\n\n\n@for_app('javac')\ndef match(command):\n    return not command.script.endswith('.java')\n\n\ndef get_new_command(command):\n    return command.script + '.java'\n"
  },
  {
    "path": "thefuck/rules/lein_not_task.py",
    "content": "import re\nfrom thefuck.utils import replace_command, get_all_matched_commands, for_app\nfrom thefuck.specific.sudo import sudo_support\n\n\n@sudo_support\n@for_app('lein')\ndef match(command):\n    return (command.script.startswith('lein')\n            and \"is not a task. See 'lein help'\" in command.output\n            and 'Did you mean this?' in command.output)\n\n\n@sudo_support\ndef get_new_command(command):\n    broken_cmd = re.findall(r\"'([^']*)' is not a task\",\n                            command.output)[0]\n    new_cmds = get_all_matched_commands(command.output, 'Did you mean this?')\n    return replace_command(command, broken_cmd, new_cmds)\n"
  },
  {
    "path": "thefuck/rules/ln_no_hard_link.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"Suggest creating symbolic link if hard link is not allowed.\n\nExample:\n> ln barDir barLink\nln: ‘barDir’: hard link not allowed for directory\n\n--> ln -s barDir barLink\n\"\"\"\n\nimport re\nfrom thefuck.specific.sudo import sudo_support\n\n\n@sudo_support\ndef match(command):\n    return (command.output.endswith(\"hard link not allowed for directory\") and\n            command.script_parts[0] == 'ln')\n\n\n@sudo_support\ndef get_new_command(command):\n    return re.sub(r'^ln ', 'ln -s ', command.script)\n"
  },
  {
    "path": "thefuck/rules/ln_s_order.py",
    "content": "import os\nfrom thefuck.specific.sudo import sudo_support\n\n\ndef _get_destination(script_parts):\n    \"\"\"When arguments order is wrong first argument will be destination.\"\"\"\n    for part in script_parts:\n        if part not in {'ln', '-s', '--symbolic'} and os.path.exists(part):\n            return part\n\n\n@sudo_support\ndef match(command):\n    return (command.script_parts[0] == 'ln'\n            and {'-s', '--symbolic'}.intersection(command.script_parts)\n            and 'File exists' in command.output\n            and _get_destination(command.script_parts))\n\n\n@sudo_support\ndef get_new_command(command):\n    destination = _get_destination(command.script_parts)\n    parts = command.script_parts[:]\n    parts.remove(destination)\n    parts.append(destination)\n    return ' '.join(parts)\n"
  },
  {
    "path": "thefuck/rules/long_form_help.py",
    "content": "from thefuck.utils import replace_argument\nimport re\n\n# regex to match a suggested help command from the tool output\nhelp_regex = r\"(?:Run|Try) '([^']+)'(?: or '[^']+')? for (?:details|more information).\"\n\n\ndef match(command):\n    if re.search(help_regex, command.output, re.I) is not None:\n        return True\n\n    if '--help' in command.output:\n        return True\n\n    return False\n\n\ndef get_new_command(command):\n    if re.search(help_regex, command.output) is not None:\n        match_obj = re.search(help_regex, command.output, re.I)\n        return match_obj.group(1)\n\n    return replace_argument(command.script, '-h', '--help')\n\n\nenabled_by_default = True\npriority = 5000\n"
  },
  {
    "path": "thefuck/rules/ls_all.py",
    "content": "from thefuck.utils import for_app\n\n\n@for_app('ls')\ndef match(command):\n    return command.output.strip() == ''\n\n\ndef get_new_command(command):\n    return ' '.join(['ls', '-A'] + command.script_parts[1:])\n"
  },
  {
    "path": "thefuck/rules/ls_lah.py",
    "content": "from thefuck.utils import for_app\n\n\n@for_app('ls')\ndef match(command):\n    return command.script_parts and 'ls -' not in command.script\n\n\ndef get_new_command(command):\n    command = command.script_parts[:]\n    command[0] = 'ls -lah'\n    return ' '.join(command)\n"
  },
  {
    "path": "thefuck/rules/man.py",
    "content": "from thefuck.utils import for_app\n\n\n@for_app('man', at_least=1)\ndef match(command):\n    return True\n\n\ndef get_new_command(command):\n    if '3' in command.script:\n        return command.script.replace(\"3\", \"2\")\n    if '2' in command.script:\n        return command.script.replace(\"2\", \"3\")\n\n    last_arg = command.script_parts[-1]\n    help_command = last_arg + ' --help'\n\n    # If there are no man pages for last_arg, suggest `last_arg --help` instead.\n    # Otherwise, suggest `--help` after suggesting other man page sections.\n    if command.output.strip() == 'No manual entry for ' + last_arg:\n        return [help_command]\n\n    split_cmd2 = command.script_parts\n    split_cmd3 = split_cmd2[:]\n\n    split_cmd2.insert(1, ' 2 ')\n    split_cmd3.insert(1, ' 3 ')\n\n    return [\n        \"\".join(split_cmd3),\n        \"\".join(split_cmd2),\n        help_command,\n    ]\n"
  },
  {
    "path": "thefuck/rules/man_no_space.py",
    "content": "def match(command):\n    return (command.script.startswith(u'man')\n            and u'command not found' in command.output.lower())\n\n\ndef get_new_command(command):\n    return u'man {}'.format(command.script[3:])\n\n\npriority = 2000\n"
  },
  {
    "path": "thefuck/rules/mercurial.py",
    "content": "import re\nfrom thefuck.utils import get_closest, for_app\n\n\ndef extract_possibilities(command):\n    possib = re.findall(r'\\n\\(did you mean one of ([^\\?]+)\\?\\)', command.output)\n    if possib:\n        return possib[0].split(', ')\n    possib = re.findall(r'\\n    ([^$]+)$', command.output)\n    if possib:\n        return possib[0].split(' ')\n    return possib\n\n\n@for_app('hg')\ndef match(command):\n    return ('hg: unknown command' in command.output\n            and '(did you mean one of ' in command.output\n            or \"hg: command '\" in command.output\n            and \"' is ambiguous:\" in command.output)\n\n\ndef get_new_command(command):\n    script = command.script_parts[:]\n    possibilities = extract_possibilities(command)\n    script[1] = get_closest(script[1], possibilities)\n    return ' '.join(script)\n"
  },
  {
    "path": "thefuck/rules/missing_space_before_subcommand.py",
    "content": "from thefuck.utils import get_all_executables, memoize\n\n\n@memoize\ndef _get_executable(script_part):\n    for executable in get_all_executables():\n        if len(executable) > 1 and script_part.startswith(executable):\n            return executable\n\n\ndef match(command):\n    return (not command.script_parts[0] in get_all_executables()\n            and _get_executable(command.script_parts[0]))\n\n\ndef get_new_command(command):\n    executable = _get_executable(command.script_parts[0])\n    return command.script.replace(executable, u'{} '.format(executable), 1)\n\n\npriority = 4000\n"
  },
  {
    "path": "thefuck/rules/mkdir_p.py",
    "content": "import re\nfrom thefuck.specific.sudo import sudo_support\n\n\n@sudo_support\ndef match(command):\n    return ('mkdir' in command.script\n            and 'No such file or directory' in command.output)\n\n\n@sudo_support\ndef get_new_command(command):\n    return re.sub('\\\\bmkdir (.*)', 'mkdir -p \\\\1', command.script)\n"
  },
  {
    "path": "thefuck/rules/mvn_no_command.py",
    "content": "from thefuck.utils import for_app\n\n\n@for_app('mvn')\ndef match(command):\n    return 'No goals have been specified for this build' in command.output\n\n\ndef get_new_command(command):\n    return [command.script + ' clean package',\n            command.script + ' clean install']\n"
  },
  {
    "path": "thefuck/rules/mvn_unknown_lifecycle_phase.py",
    "content": "from thefuck.utils import for_app, get_close_matches, replace_command\nimport re\n\n\ndef _get_failed_lifecycle(command):\n    return re.search(r'\\[ERROR\\] Unknown lifecycle phase \"(.+)\"',\n                     command.output)\n\n\ndef _getavailable_lifecycles(command):\n    return re.search(\n        r'Available lifecycle phases are: (.+) -> \\[Help 1\\]', command.output)\n\n\n@for_app('mvn')\ndef match(command):\n    failed_lifecycle = _get_failed_lifecycle(command)\n    available_lifecycles = _getavailable_lifecycles(command)\n    return available_lifecycles and failed_lifecycle\n\n\ndef get_new_command(command):\n    failed_lifecycle = _get_failed_lifecycle(command)\n    available_lifecycles = _getavailable_lifecycles(command)\n    if available_lifecycles and failed_lifecycle:\n        selected_lifecycle = get_close_matches(\n            failed_lifecycle.group(1), available_lifecycles.group(1).split(\", \"))\n        return replace_command(command, failed_lifecycle.group(1), selected_lifecycle)\n    else:\n        return []\n"
  },
  {
    "path": "thefuck/rules/nixos_cmd_not_found.py",
    "content": "import re\nfrom thefuck.specific.nix import nix_available\nfrom thefuck.shells import shell\n\nregex = re.compile(r'nix-env -iA ([^\\s]*)')\nenabled_by_default = nix_available\n\n\ndef match(command):\n    return regex.findall(command.output)\n\n\ndef get_new_command(command):\n    name = regex.findall(command.output)[0]\n    return shell.and_('nix-env -iA {}'.format(name), command.script)\n"
  },
  {
    "path": "thefuck/rules/no_command.py",
    "content": "from thefuck.utils import get_all_executables, get_close_matches, \\\n    get_valid_history_without_current, get_closest, which\nfrom thefuck.specific.sudo import sudo_support\n\n\n@sudo_support\ndef match(command):\n    return (not which(command.script_parts[0])\n            and ('not found' in command.output\n                 or 'is not recognized as' in command.output)\n            and bool(get_close_matches(command.script_parts[0],\n                                       get_all_executables())))\n\n\ndef _get_used_executables(command):\n    for script in get_valid_history_without_current(command):\n        yield script.split(' ')[0]\n\n\n@sudo_support\ndef get_new_command(command):\n    old_command = command.script_parts[0]\n\n    # One from history:\n    already_used = get_closest(\n        old_command, _get_used_executables(command),\n        fallback_to_first=False)\n    if already_used:\n        new_cmds = [already_used]\n    else:\n        new_cmds = []\n\n    # Other from all executables:\n    new_cmds += [cmd for cmd in get_close_matches(old_command,\n                                                  get_all_executables())\n                 if cmd not in new_cmds]\n\n    return [command.script.replace(old_command, cmd, 1) for cmd in new_cmds]\n\n\npriority = 3000\n"
  },
  {
    "path": "thefuck/rules/no_such_file.py",
    "content": "import re\nfrom thefuck.shells import shell\n\n\npatterns = (\n    r\"mv: cannot move '[^']*' to '([^']*)': No such file or directory\",\n    r\"mv: cannot move '[^']*' to '([^']*)': Not a directory\",\n    r\"cp: cannot create regular file '([^']*)': No such file or directory\",\n    r\"cp: cannot create regular file '([^']*)': Not a directory\",\n)\n\n\ndef match(command):\n    for pattern in patterns:\n        if re.search(pattern, command.output):\n            return True\n\n    return False\n\n\ndef get_new_command(command):\n    for pattern in patterns:\n        file = re.findall(pattern, command.output)\n\n        if file:\n            file = file[0]\n            dir = file[0:file.rfind('/')]\n\n            formatme = shell.and_('mkdir -p {}', '{}')\n            return formatme.format(dir, command.script)\n"
  },
  {
    "path": "thefuck/rules/npm_missing_script.py",
    "content": "import re\nfrom thefuck.utils import for_app, replace_command\nfrom thefuck.specific.npm import get_scripts, npm_available\n\nenabled_by_default = npm_available\n\n\n@for_app('npm')\ndef match(command):\n    return (any(part.startswith('ru') for part in command.script_parts)\n            and 'npm ERR! missing script: ' in command.output)\n\n\ndef get_new_command(command):\n    misspelled_script = re.findall(\n        r'.*missing script: (.*)\\n', command.output)[0]\n    return replace_command(command, misspelled_script, get_scripts())\n"
  },
  {
    "path": "thefuck/rules/npm_run_script.py",
    "content": "from thefuck.specific.npm import npm_available, get_scripts\nfrom thefuck.utils import for_app\n\nenabled_by_default = npm_available\n\n\n@for_app('npm')\ndef match(command):\n    return ('Usage: npm <command>' in command.output\n            and not any(part.startswith('ru') for part in command.script_parts)\n            and command.script_parts[1] in get_scripts())\n\n\ndef get_new_command(command):\n    parts = command.script_parts[:]\n    parts.insert(1, 'run-script')\n    return ' '.join(parts)\n"
  },
  {
    "path": "thefuck/rules/npm_wrong_command.py",
    "content": "from thefuck.specific.npm import npm_available\nfrom thefuck.utils import replace_argument, for_app, eager, get_closest\nfrom thefuck.specific.sudo import sudo_support\n\nenabled_by_default = npm_available\n\n\ndef _get_wrong_command(script_parts):\n    commands = [part for part in script_parts[1:] if not part.startswith('-')]\n    if commands:\n        return commands[0]\n\n\n@sudo_support\n@for_app('npm')\ndef match(command):\n    return (command.script_parts[0] == 'npm' and\n            'where <command> is one of:' in command.output and\n            _get_wrong_command(command.script_parts))\n\n\n@eager\ndef _get_available_commands(stdout):\n    commands_listing = False\n    for line in stdout.split('\\n'):\n        if line.startswith('where <command> is one of:'):\n            commands_listing = True\n        elif commands_listing:\n            if not line:\n                break\n\n            for command in line.split(', '):\n                stripped = command.strip()\n                if stripped:\n                    yield stripped\n\n\ndef get_new_command(command):\n    npm_commands = _get_available_commands(command.output)\n    wrong_command = _get_wrong_command(command.script_parts)\n    fixed = get_closest(wrong_command, npm_commands)\n    return replace_argument(command.script, wrong_command, fixed)\n"
  },
  {
    "path": "thefuck/rules/omnienv_no_such_command.py",
    "content": "import re\nfrom thefuck.utils import (cache, for_app, replace_argument, replace_command,\n                           which)\nfrom subprocess import PIPE, Popen\n\n\nsupported_apps = 'goenv', 'nodenv', 'pyenv', 'rbenv'\nenabled_by_default = any(which(a) for a in supported_apps)\n\n\nCOMMON_TYPOS = {\n    'list': ['versions', 'install --list'],\n    'remove': ['uninstall'],\n}\n\n\n@for_app(*supported_apps, at_least=1)\ndef match(command):\n    return 'env: no such command ' in command.output\n\n\ndef get_app_commands(app):\n    proc = Popen([app, 'commands'], stdout=PIPE)\n    return [line.decode('utf-8').strip() for line in proc.stdout.readlines()]\n\n\ndef get_new_command(command):\n    broken = re.findall(r\"env: no such command ['`]([^']*)'\", command.output)[0]\n    matched = [replace_argument(command.script, broken, common_typo)\n               for common_typo in COMMON_TYPOS.get(broken, [])]\n\n    app = command.script_parts[0]\n    app_commands = cache(which(app))(get_app_commands)(app)\n    matched.extend(replace_command(command, broken, app_commands))\n    return matched\n"
  },
  {
    "path": "thefuck/rules/open.py",
    "content": "# Opens URL's in the default web browser\n#\n# Example:\n# > open github.com\n# The file ~/github.com does not exist.\n# Perhaps you meant 'http://github.com'?\n#\nfrom thefuck.shells import shell\nfrom thefuck.utils import eager, for_app\n\n\ndef is_arg_url(command):\n    return ('.com' in command.script or\n            '.edu' in command.script or\n            '.info' in command.script or\n            '.io' in command.script or\n            '.ly' in command.script or\n            '.me' in command.script or\n            '.net' in command.script or\n            '.org' in command.script or\n            '.se' in command.script or\n            'www.' in command.script)\n\n\n@for_app('open', 'xdg-open', 'gnome-open', 'kde-open')\ndef match(command):\n    return (is_arg_url(command) or\n            command.output.strip().startswith('The file ') and\n            command.output.strip().endswith(' does not exist.'))\n\n\n@eager\ndef get_new_command(command):\n    output = command.output.strip()\n    if is_arg_url(command):\n        yield command.script.replace('open ', 'open http://')\n    elif output.startswith('The file ') and output.endswith(' does not exist.'):\n        arg = command.script.split(' ', 1)[1]\n        for option in ['touch', 'mkdir']:\n            yield shell.and_(u'{} {}'.format(option, arg), command.script)\n"
  },
  {
    "path": "thefuck/rules/pacman.py",
    "content": "from thefuck.specific.archlinux import get_pkgfile, archlinux_env\nfrom thefuck.shells import shell\n\n\ndef match(command):\n    return 'not found' in command.output and get_pkgfile(command.script)\n\n\ndef get_new_command(command):\n    packages = get_pkgfile(command.script)\n\n    formatme = shell.and_('{} -S {}', '{}')\n    return [formatme.format(pacman, package, command.script)\n            for package in packages]\n\n\nenabled_by_default, pacman = archlinux_env()\n"
  },
  {
    "path": "thefuck/rules/pacman_invalid_option.py",
    "content": "from thefuck.specific.archlinux import archlinux_env\nfrom thefuck.specific.sudo import sudo_support\nfrom thefuck.utils import for_app\nimport re\n\n\n@sudo_support\n@for_app(\"pacman\")\ndef match(command):\n    return command.output.startswith(\"error: invalid option '-\") and any(\n        \" -{}\".format(option) in command.script for option in \"surqfdvt\"\n    )\n\n\ndef get_new_command(command):\n    option = re.findall(r\" -[dfqrstuv]\", command.script)[0]\n    return re.sub(option, option.upper(), command.script)\n\n\nenabled_by_default = archlinux_env()\n"
  },
  {
    "path": "thefuck/rules/pacman_not_found.py",
    "content": "\"\"\" Fixes wrong package names with pacman or yaourt.\n\nFor example the `llc` program is in package `llvm` so this:\n    yay -S llc\nshould be:\n    yay -S llvm\n\"\"\"\n\nfrom thefuck.utils import replace_command\nfrom thefuck.specific.archlinux import get_pkgfile, archlinux_env\n\n\ndef match(command):\n    return (command.script_parts\n            and (command.script_parts[0] in ('pacman', 'yay', 'pikaur', 'yaourt')\n                 or command.script_parts[0:2] == ['sudo', 'pacman'])\n            and 'error: target not found:' in command.output)\n\n\ndef get_new_command(command):\n    pgr = command.script_parts[-1]\n\n    return replace_command(command, pgr, get_pkgfile(pgr))\n\n\nenabled_by_default, _ = archlinux_env()\n"
  },
  {
    "path": "thefuck/rules/path_from_history.py",
    "content": "from collections import Counter\nimport re\nfrom thefuck.system import Path\nfrom thefuck.utils import (get_valid_history_without_current,\n                           memoize, replace_argument)\nfrom thefuck.shells import shell\n\n\npatterns = [r'no such file or directory: (.*)$',\n            r\"cannot access '(.*)': No such file or directory\",\n            r': (.*): No such file or directory',\n            r\"can't cd to (.*)$\"]\n\n\n@memoize\ndef _get_destination(command):\n    for pattern in patterns:\n        found = re.findall(pattern, command.output)\n        if found:\n            if found[0] in command.script_parts:\n                return found[0]\n\n\ndef match(command):\n    return bool(_get_destination(command))\n\n\ndef _get_all_absolute_paths_from_history(command):\n    counter = Counter()\n\n    for line in get_valid_history_without_current(command):\n        splitted = shell.split_command(line)\n\n        for param in splitted[1:]:\n            if param.startswith('/') or param.startswith('~'):\n                if param.endswith('/'):\n                    param = param[:-1]\n\n                counter[param] += 1\n\n    return (path for path, _ in counter.most_common(None))\n\n\ndef get_new_command(command):\n    destination = _get_destination(command)\n    paths = _get_all_absolute_paths_from_history(command)\n\n    return [replace_argument(command.script, destination, path)\n            for path in paths if path.endswith(destination)\n            and Path(path).expanduser().exists()]\n\n\npriority = 800\n"
  },
  {
    "path": "thefuck/rules/php_s.py",
    "content": "from thefuck.utils import replace_argument, for_app\n\n\n@for_app('php', at_least=2)\ndef match(command):\n    return ('-s' in command.script_parts\n            and command.script_parts[-1] != '-s')\n\n\ndef get_new_command(command):\n    return replace_argument(command.script, \"-s\", \"-S\")\n"
  },
  {
    "path": "thefuck/rules/pip_install.py",
    "content": "from thefuck.utils import for_app\nfrom thefuck.specific.sudo import sudo_support\n\n\n@sudo_support\n@for_app('pip')\ndef match(command):\n    return ('pip install' in command.script and 'Permission denied' in command.output)\n\n\ndef get_new_command(command):\n    if '--user' not in command.script:  # add --user (attempt 1)\n        return command.script.replace(' install ', ' install --user ')\n\n    return 'sudo {}'.format(command.script.replace(' --user', ''))  # since --user didn't fix things, let's try sudo (attempt 2)\n"
  },
  {
    "path": "thefuck/rules/pip_unknown_command.py",
    "content": "import re\nfrom thefuck.utils import replace_argument, for_app\nfrom thefuck.specific.sudo import sudo_support\n\n\n@sudo_support\n@for_app('pip', 'pip2', 'pip3')\ndef match(command):\n    return ('pip' in command.script and\n            'unknown command' in command.output and\n            'maybe you meant' in command.output)\n\n\ndef get_new_command(command):\n    broken_cmd = re.findall(r'ERROR: unknown command \"([^\"]+)\"',\n                            command.output)[0]\n    new_cmd = re.findall(r'maybe you meant \"([^\"]+)\"', command.output)[0]\n\n    return replace_argument(command.script, broken_cmd, new_cmd)\n"
  },
  {
    "path": "thefuck/rules/port_already_in_use.py",
    "content": "import re\nfrom subprocess import Popen, PIPE\nfrom thefuck.utils import memoize, which\nfrom thefuck.shells import shell\n\nenabled_by_default = bool(which('lsof'))\n\npatterns = [r\"bind on address \\('.*', (?P<port>\\d+)\\)\",\n            r'Unable to bind [^ ]*:(?P<port>\\d+)',\n            r\"can't listen on port (?P<port>\\d+)\",\n            r'listen EADDRINUSE [^ ]*:(?P<port>\\d+)']\n\n\n@memoize\ndef _get_pid_by_port(port):\n    proc = Popen(['lsof', '-i', ':{}'.format(port)], stdout=PIPE)\n    lines = proc.stdout.read().decode().split('\\n')\n    if len(lines) > 1:\n        return lines[1].split()[1]\n    else:\n        return None\n\n\n@memoize\ndef _get_used_port(command):\n    for pattern in patterns:\n        matched = re.search(pattern, command.output)\n        if matched:\n            return matched.group('port')\n\n\ndef match(command):\n    port = _get_used_port(command)\n    return port and _get_pid_by_port(port)\n\n\ndef get_new_command(command):\n    port = _get_used_port(command)\n    pid = _get_pid_by_port(port)\n    return shell.and_(u'kill {}'.format(pid), command.script)\n"
  },
  {
    "path": "thefuck/rules/prove_recursively.py",
    "content": "import os\nfrom thefuck.utils import for_app\n\n\ndef _is_recursive(part):\n    if part == '--recurse':\n        return True\n    elif not part.startswith('--') and part.startswith('-') and 'r' in part:\n        return True\n\n\ndef _isdir(part):\n    return not part.startswith('-') and os.path.isdir(part)\n\n\n@for_app('prove')\ndef match(command):\n    return (\n        'NOTESTS' in command.output\n        and not any(_is_recursive(part) for part in command.script_parts[1:])\n        and any(_isdir(part) for part in command.script_parts[1:]))\n\n\ndef get_new_command(command):\n    parts = command.script_parts[:]\n    parts.insert(1, '-r')\n    return u' '.join(parts)\n"
  },
  {
    "path": "thefuck/rules/python_command.py",
    "content": "from thefuck.specific.sudo import sudo_support\n# add 'python' suffix to the command if\n#  1) The script does not have execute permission or\n#  2) is interpreted as shell script\n\n\n@sudo_support\ndef match(command):\n    return (command.script_parts\n            and command.script_parts[0].endswith('.py')\n            and ('Permission denied' in command.output or\n                 'command not found' in command.output))\n\n\n@sudo_support\ndef get_new_command(command):\n    return 'python ' + command.script\n"
  },
  {
    "path": "thefuck/rules/python_execute.py",
    "content": "# Appends .py when executing python files\n#\n# Example:\n# > python foo\n# error: python: can't open file 'foo': [Errno 2] No such file or directory\nfrom thefuck.utils import for_app\n\n\n@for_app('python')\ndef match(command):\n    return not command.script.endswith('.py')\n\n\ndef get_new_command(command):\n    return command.script + '.py'\n"
  },
  {
    "path": "thefuck/rules/python_module_error.py",
    "content": "import re\nfrom thefuck.shells import shell\n\nMISSING_MODULE = r\"ModuleNotFoundError: No module named '([^']+)'\"\n\n\ndef match(command):\n    return \"ModuleNotFoundError: No module named '\" in command.output\n\n\ndef get_new_command(command):\n    missing_module = re.findall(MISSING_MODULE, command.output)[0]\n    return shell.and_(\"pip install {}\".format(missing_module), command.script)\n"
  },
  {
    "path": "thefuck/rules/quotation_marks.py",
    "content": "# Fixes careless \" and ' usage\n#\n# Example:\n# > git commit -m 'My Message\"\n\n\ndef match(command):\n    return '\\'' in command.script and '\\\"' in command.script\n\n\ndef get_new_command(command):\n    return command.script.replace('\\'', '\\\"')\n"
  },
  {
    "path": "thefuck/rules/rails_migrations_pending.py",
    "content": "import re\nfrom thefuck.shells import shell\n\n\nSUGGESTION_REGEX = r\"To resolve this issue, run:\\s+(.*?)\\n\"\n\n\ndef match(command):\n    return \"Migrations are pending. To resolve this issue, run:\" in command.output\n\n\ndef get_new_command(command):\n    migration_script = re.search(SUGGESTION_REGEX, command.output).group(1)\n    return shell.and_(migration_script, command.script)\n"
  },
  {
    "path": "thefuck/rules/react_native_command_unrecognized.py",
    "content": "import re\nfrom subprocess import Popen, PIPE\nfrom thefuck.utils import for_app, replace_command, cache, eager\n\n\n@for_app('react-native')\ndef match(command):\n    return re.findall(r\"Unrecognized command '.*'\", command.output)\n\n\n@cache('package.json')\n@eager\ndef _get_commands():\n    proc = Popen(['react-native', '--help'], stdout=PIPE)\n    should_yield = False\n    for line in proc.stdout.readlines():\n        line = line.decode().strip()\n\n        if not line:\n            continue\n\n        if 'Commands:' in line:\n            should_yield = True\n            continue\n\n        if should_yield:\n            yield line.split(' ')[0]\n\n\ndef get_new_command(command):\n    misspelled_command = re.findall(r\"Unrecognized command '(.*)'\",\n                                    command.output)[0]\n    commands = _get_commands()\n    return replace_command(command, misspelled_command, commands)\n"
  },
  {
    "path": "thefuck/rules/remove_shell_prompt_literal.py",
    "content": "\"\"\"Fixes error for commands containing one or more occurrences of the shell\nprompt symbol '$'.\n\nThis usually happens when commands are copied from documentations\nincluding them in their code blocks.\n\nExample:\n> $ git clone https://github.com/nvbn/thefuck.git\nbash: $: command not found...\n\"\"\"\n\nimport re\n\n\ndef match(command):\n    return (\n        \"$: command not found\" in command.output\n        and re.search(r\"^[\\s]*\\$ [\\S]+\", command.script) is not None\n    )\n\n\ndef get_new_command(command):\n    return command.script.lstrip(\"$ \")\n"
  },
  {
    "path": "thefuck/rules/remove_trailing_cedilla.py",
    "content": "# -*- encoding: utf-8 -*-\n\nCEDILLA = u\"ç\"\n\n\ndef match(command):\n    return command.script.endswith(CEDILLA)\n\n\ndef get_new_command(command):\n    return command.script[:-1]\n"
  },
  {
    "path": "thefuck/rules/rm_dir.py",
    "content": "import re\nfrom thefuck.specific.sudo import sudo_support\n\n\n@sudo_support\ndef match(command):\n    return ('rm' in command.script\n            and 'is a directory' in command.output.lower())\n\n\n@sudo_support\ndef get_new_command(command):\n    arguments = '-rf'\n    if 'hdfs' in command.script:\n        arguments = '-r'\n    return re.sub('\\\\brm (.*)', 'rm ' + arguments + ' \\\\1', command.script)\n"
  },
  {
    "path": "thefuck/rules/rm_root.py",
    "content": "from thefuck.specific.sudo import sudo_support\n\nenabled_by_default = False\n\n\n@sudo_support\ndef match(command):\n    return (command.script_parts\n            and {'rm', '/'}.issubset(command.script_parts)\n            and '--no-preserve-root' not in command.script\n            and '--no-preserve-root' in command.output)\n\n\n@sudo_support\ndef get_new_command(command):\n    return u'{} --no-preserve-root'.format(command.script)\n"
  },
  {
    "path": "thefuck/rules/scm_correction.py",
    "content": "from thefuck.utils import for_app, memoize\nfrom thefuck.system import Path\n\npath_to_scm = {\n    '.git': 'git',\n    '.hg': 'hg',\n}\n\nwrong_scm_patterns = {\n    'git': 'fatal: Not a git repository',\n    'hg': 'abort: no repository found',\n}\n\n\n@memoize\ndef _get_actual_scm():\n    for path, scm in path_to_scm.items():\n        if Path(path).is_dir():\n            return scm\n\n\n@for_app(*wrong_scm_patterns.keys())\ndef match(command):\n    scm = command.script_parts[0]\n    pattern = wrong_scm_patterns[scm]\n\n    return pattern in command.output and _get_actual_scm()\n\n\ndef get_new_command(command):\n    scm = _get_actual_scm()\n    return u' '.join([scm] + command.script_parts[1:])\n"
  },
  {
    "path": "thefuck/rules/sed_unterminated_s.py",
    "content": "import shlex\nfrom thefuck.shells import shell\nfrom thefuck.utils import for_app\n\n\n@for_app('sed')\ndef match(command):\n    return \"unterminated `s' command\" in command.output\n\n\ndef get_new_command(command):\n    script = shlex.split(command.script)\n\n    for (i, e) in enumerate(script):\n        if e.startswith(('s/', '-es/')) and e[-1] != '/':\n            script[i] += '/'\n\n    return ' '.join(map(shell.quote, script))\n"
  },
  {
    "path": "thefuck/rules/sl_ls.py",
    "content": "\"\"\"\nThis happens way too often\n\nWhen typing really fast cause I'm a 1337 H4X0R,\nI often fuck up 'ls' and type 'sl'. No more!\n\"\"\"\n\n\ndef match(command):\n    return command.script == 'sl'\n\n\ndef get_new_command(command):\n    return 'ls'\n"
  },
  {
    "path": "thefuck/rules/ssh_known_hosts.py",
    "content": "import re\nfrom thefuck.utils import for_app\n\ncommands = ('ssh', 'scp')\n\n\n@for_app(*commands)\ndef match(command):\n    if not command.script:\n        return False\n    if not command.script.startswith(commands):\n        return False\n\n    patterns = (\n        r'WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!',\n        r'WARNING: POSSIBLE DNS SPOOFING DETECTED!',\n        r\"Warning: the \\S+ host key for '([^']+)' differs from the key for the IP address '([^']+)'\",\n    )\n\n    return any(re.findall(pattern, command.output) for pattern in patterns)\n\n\ndef get_new_command(command):\n    return command.script\n\n\ndef side_effect(old_cmd, command):\n    offending_pattern = re.compile(\n        r'(?:Offending (?:key for IP|\\S+ key)|Matching host key) in ([^:]+):(\\d+)',\n        re.MULTILINE)\n    offending = offending_pattern.findall(old_cmd.output)\n    for filepath, lineno in offending:\n        with open(filepath, 'r') as fh:\n            lines = fh.readlines()\n            del lines[int(lineno) - 1]\n        with open(filepath, 'w') as fh:\n            fh.writelines(lines)\n"
  },
  {
    "path": "thefuck/rules/sudo.py",
    "content": "patterns = ['permission denied',\n            'eacces',\n            'pkg: insufficient privileges',\n            'you cannot perform this operation unless you are root',\n            'non-root users cannot',\n            'operation not permitted',\n            'not super-user',\n            'superuser privilege',\n            'root privilege',\n            'this command has to be run under the root user.',\n            'this operation requires root.',\n            'requested operation requires superuser privilege',\n            'must be run as root',\n            'must run as root',\n            'must be superuser',\n            'must be root',\n            'need to be root',\n            'need root',\n            'needs to be run as root',\n            'only root can ',\n            'you don\\'t have access to the history db.',\n            'authentication is required',\n            'edspermissionerror',\n            'you don\\'t have write permissions',\n            'use `sudo`',\n            'sudorequirederror',\n            'error: insufficient privileges',\n            'updatedb: can not open a temporary file']\n\n\ndef match(command):\n    if command.script_parts and '&&' not in command.script_parts and command.script_parts[0] == 'sudo':\n        return False\n\n    for pattern in patterns:\n        if pattern in command.output.lower():\n            return True\n    return False\n\n\ndef get_new_command(command):\n    if '&&' in command.script:\n        return u'sudo sh -c \"{}\"'.format(\" \".join([part for part in command.script_parts if part != \"sudo\"]))\n    elif '>' in command.script:\n        return u'sudo sh -c \"{}\"'.format(command.script.replace('\"', '\\\\\"'))\n    else:\n        return u'sudo {}'.format(command.script)\n"
  },
  {
    "path": "thefuck/rules/sudo_command_from_user_path.py",
    "content": "import re\nfrom thefuck.utils import for_app, which, replace_argument\n\n\ndef _get_command_name(command):\n    found = re.findall(r'sudo: (.*): command not found', command.output)\n    if found:\n        return found[0]\n\n\n@for_app('sudo')\ndef match(command):\n    if 'command not found' in command.output:\n        command_name = _get_command_name(command)\n        return which(command_name)\n\n\ndef get_new_command(command):\n    command_name = _get_command_name(command)\n    return replace_argument(command.script, command_name,\n                            u'env \"PATH=$PATH\" {}'.format(command_name))\n"
  },
  {
    "path": "thefuck/rules/switch_lang.py",
    "content": "# -*- encoding: utf-8 -*-\nfrom thefuck.utils import memoize, get_alias\n\ntarget_layout = '''qwertyuiop[]asdfghjkl;'zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>?'''\n# any new keyboard layout must be appended\n\ngreek = u''';ςερτυθιοπ[]ασδφγηξκλ΄ζχψωβνμ,./:΅ΕΡΤΥΘΙΟΠ{}ΑΣΔΦΓΗΞΚΛ¨\"ΖΧΨΩΒΝΜ<>?'''\nkorean = u'''ㅂㅈㄷㄱㅅㅛㅕㅑㅐㅔ[]ㅁㄴㅇㄹㅎㅗㅓㅏㅣ;'ㅋㅌㅊㅍㅠㅜㅡ,./ㅃㅉㄸㄲㅆㅛㅕㅑㅒㅖ{}ㅁㄴㅇㄹㅎㅗㅓㅏㅣ:\"ㅋㅌㅊㅍㅠㅜㅡ<>?'''\n\nsource_layouts = [u'''йцукенгшщзхъфывапролджэячсмитьбю.ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,''',\n                  u'''йцукенгшщзхїфівапролджєячсмитьбю.ЙЦУКЕНГШЩЗХЇФІВАПРОЛДЖЄЯЧСМИТЬБЮ,''',\n                  u'''ضصثقفغعهخحجچشسیبلاتنمکگظطزرذدپو./ًٌٍَُِّْ][}{ؤئيإأآة»«:؛كٓژٰ‌ٔء><؟''',\n                  u'''/'קראטוןםפ][שדגכעיחלךף,זסבהנמצתץ.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>?''',\n                  greek,\n                  korean]\n\nsource_to_target = {\n    greek: {u';': \"q\", u'ς': \"w\", u'ε': \"e\", u'ρ': \"r\", u'τ': \"t\", u'υ': \"y\",\n            u'θ': \"u\", u'ι': \"i\", u'ο': \"o\", u'π': \"p\", u'[': \"[\", u']': \"]\",\n            u'α': \"a\", u'σ': \"s\", u'δ': \"d\", u'φ': \"f\", u'γ': \"g\", u'η': \"h\",\n            u'ξ': \"j\", u'κ': \"k\", u'λ': \"l\", u'΄': \"'\", u'ζ': \"z\", u'χ': \"x\",\n            u'ψ': \"c\", u'ω': \"v\", u'β': \"b\", u'ν': \"n\", u'μ': \"m\", u',': \",\",\n            u'.': \".\", u'/': \"/\", u':': \"Q\", u'΅': \"W\", u'Ε': \"E\", u'Ρ': \"R\",\n            u'Τ': \"T\", u'Υ': \"Y\", u'Θ': \"U\", u'Ι': \"I\", u'Ο': \"O\", u'Π': \"P\",\n            u'{': \"{\", u'}': \"}\", u'Α': \"A\", u'Σ': \"S\", u'Δ': \"D\", u'Φ': \"F\",\n            u'Γ': \"G\", u'Η': \"H\", u'Ξ': \"J\", u'Κ': \"K\", u'Λ': \"L\", u'¨': \":\",\n            u'\"': '\"', u'Ζ': \"Z\", u'Χ': \"X\", u'Ψ': \"C\", u'Ω': \"V\", u'Β': \"B\",\n            u'Ν': \"N\", u'Μ': \"M\", u'<': \"<\", u'>': \">\", u'?': \"?\", u'ά': \"a\",\n            u'έ': \"e\", u'ύ': \"y\", u'ί': \"i\", u'ό': \"o\", u'ή': 'h', u'ώ': u\"v\",\n            u'Ά': \"A\", u'Έ': \"E\", u'Ύ': \"Y\", u'Ί': \"I\", u'Ό': \"O\", u'Ή': \"H\",\n            u'Ώ': \"V\"},\n}\n\n'''Lists used for decomposing korean letters.'''\nHEAD_LIST = [u'ㄱ', u'ㄲ', u'ㄴ', u'ㄷ', u'ㄸ', u'ㄹ', u'ㅁ', u'ㅂ', u'ㅃ', u'ㅅ', u'ㅆ',\n             u'ㅇ', u'ㅈ', u'ㅉ', u'ㅊ', u'ㅋ', u'ㅌ', u'ㅍ', u'ㅎ']\nBODY_LIST = [u'ㅏ', u'ㅐ', u'ㅑ', u'ㅒ', u'ㅓ', u'ㅔ', u'ㅕ', u'ㅖ', u'ㅗ', u'ㅘ', u'ㅙ',\n             u'ㅚ', u'ㅛ', u'ㅜ', u'ㅝ', u'ㅞ', u'ㅟ', u'ㅠ', u'ㅡ', u'ㅢ', u'ㅣ']\nTAIL_LIST = [u' ', u'ㄱ', u'ㄲ', u'ㄳ', u'ㄴ', u'ㄵ', u'ㄶ', u'ㄷ', u'ㄹ', u'ㄺ', u'ㄻ',\n             u'ㄼ', u'ㄽ', u'ㄾ', u'ㄿ', u'ㅀ', u'ㅁ', u'ㅂ', u'ㅄ', u'ㅅ', u'ㅆ', u'ㅇ', u'ㅈ',\n             u'ㅊ', u'ㅋ', u'ㅌ', u'ㅍ', u'ㅎ']\nDOUBLE_LIST = [u'ㅘ', u'ㅙ', u'ㅚ', u'ㅝ', u'ㅞ', u'ㅟ', u'ㅢ', u'ㄳ', u'ㄵ', u'ㄶ', u'ㄺ',\n               u'ㄻ', u'ㄼ', u'ㄽ', u'ㄾ', u'ㅀ', u'ㅄ']\nDOUBLE_MOD_LIST = [u'ㅗㅏ', u'ㅗㅐ', u'ㅗㅣ', u'ㅜㅓ', u'ㅜㅔ', u'ㅜㅣ', u'ㅡㅣ', u'ㄱㅅ',\n                   u'ㄴㅈ', u'ㄴㅎ', u'ㄹㄱ', u'ㄹㅁ', u'ㄹㅂ', u'ㄹㅅ', u'ㄹㅌ', u'ㄹㅎ', u'ㅂㅅ']\n\n\n@memoize\ndef _get_matched_layout(command):\n    # don't use command.split_script here because a layout mismatch will likely\n    # result in a non-splitable script as per shlex\n    cmd = command.script.split(' ')\n    for source_layout in source_layouts:\n        is_all_match = True\n        for cmd_part in cmd:\n            if not all([ch in source_layout or ch in '-_' for ch in cmd_part]):\n                is_all_match = False\n                break\n\n        if is_all_match:\n            return source_layout\n\n\ndef _switch(ch, layout):\n    if ch in layout:\n        return target_layout[layout.index(ch)]\n    return ch\n\n\ndef _switch_command(command, layout):\n    # Layouts with different amount of characters than English\n    if layout in source_to_target:\n        return ''.join(source_to_target[layout].get(ch, ch)\n                       for ch in command.script)\n\n    return ''.join(_switch(ch, layout) for ch in command.script)\n\n\ndef _decompose_korean(command):\n    def _change_double(ch):\n        if ch in DOUBLE_LIST:\n            return DOUBLE_MOD_LIST[DOUBLE_LIST.index(ch)]\n        return ch\n\n    hg_str = u''\n    for ch in command.script:\n        if u'가' <= ch <= u'힣':\n            ord_ch = ord(ch) - ord(u'가')\n            hd = ord_ch // 588\n            bd = (ord_ch - 588 * hd) // 28\n            tl = ord_ch - 588 * hd - 28 * bd\n            for ch in [HEAD_LIST[hd], BODY_LIST[bd], TAIL_LIST[tl]]:\n                if ch != ' ':\n                    hg_str += _change_double(ch)\n        else:\n            hg_str += _change_double(ch)\n    return hg_str\n\n\ndef match(command):\n    if 'not found' not in command.output:\n        return False\n    if any(u'ㄱ' <= ch <= u'ㅎ' or u'ㅏ' <= ch <= u'ㅣ' or u'가' <= ch <= u'힣'\n            for ch in command.script):\n        return True\n\n    matched_layout = _get_matched_layout(command)\n    return (matched_layout and\n            _switch_command(command, matched_layout) != get_alias())\n\n\ndef get_new_command(command):\n    if any(u'ㄱ' <= ch <= u'ㅎ' or u'ㅏ' <= ch <= u'ㅣ' or u'가' <= ch <= u'힣'\n            for ch in command.script):\n        command.script = _decompose_korean(command)\n    matched_layout = _get_matched_layout(command)\n    return _switch_command(command, matched_layout)\n"
  },
  {
    "path": "thefuck/rules/systemctl.py",
    "content": "\"\"\"\nThe confusion in systemctl's param order is massive.\n\"\"\"\nfrom thefuck.specific.sudo import sudo_support\nfrom thefuck.utils import for_app\n\n\n@sudo_support\n@for_app('systemctl')\ndef match(command):\n    # Catches \"Unknown operation 'service'.\" when executing systemctl with\n    # misordered arguments\n    cmd = command.script_parts\n    return (cmd and 'Unknown operation \\'' in command.output and\n            len(cmd) - cmd.index('systemctl') == 3)\n\n\n@sudo_support\ndef get_new_command(command):\n    cmd = command.script_parts[:]\n    cmd[-1], cmd[-2] = cmd[-2], cmd[-1]\n    return ' '.join(cmd)\n"
  },
  {
    "path": "thefuck/rules/terraform_init.py",
    "content": "from thefuck.shells import shell\nfrom thefuck.utils import for_app\n\n\n@for_app('terraform')\ndef match(command):\n    return ('this module is not yet installed' in command.output.lower() or\n            'initialization required' in command.output.lower()\n            )\n\n\ndef get_new_command(command):\n    return shell.and_('terraform init', command.script)\n"
  },
  {
    "path": "thefuck/rules/terraform_no_command.py",
    "content": "import re\nfrom thefuck.utils import for_app\n\nMISTAKE = r'(?<=Terraform has no command named \")([^\"]+)(?=\"\\.)'\nFIX = r'(?<=Did you mean \")([^\"]+)(?=\"\\?)'\n\n\n@for_app('terraform')\ndef match(command):\n    return re.search(MISTAKE, command.output) and re.search(FIX, command.output)\n\n\ndef get_new_command(command):\n    mistake = re.search(MISTAKE, command.output).group(0)\n    fix = re.search(FIX, command.output).group(0)\n    return command.script.replace(mistake, fix)\n"
  },
  {
    "path": "thefuck/rules/test.py.py",
    "content": "def match(command):\n    return command.script == 'test.py' and 'not found' in command.output\n\n\ndef get_new_command(command):\n    return 'pytest'\n\n\n# make it come before the python_command rule\npriority = 900\n"
  },
  {
    "path": "thefuck/rules/tmux.py",
    "content": "import re\nfrom thefuck.utils import replace_command, for_app\n\n\n@for_app('tmux')\ndef match(command):\n    return ('ambiguous command:' in command.output\n            and 'could be:' in command.output)\n\n\ndef get_new_command(command):\n    cmd = re.match(r\"ambiguous command: (.*), could be: (.*)\",\n                   command.output)\n\n    old_cmd = cmd.group(1)\n    suggestions = [c.strip() for c in cmd.group(2).split(',')]\n\n    return replace_command(command, old_cmd, suggestions)\n"
  },
  {
    "path": "thefuck/rules/touch.py",
    "content": "import re\nfrom thefuck.shells import shell\nfrom thefuck.utils import for_app\n\n\n@for_app('touch')\ndef match(command):\n    return 'No such file or directory' in command.output\n\n\ndef get_new_command(command):\n    path = re.findall(\n        r\"touch: (?:cannot touch ')?(.+)/.+'?:\", command.output)[0]\n    return shell.and_(u'mkdir -p {}'.format(path), command.script)\n"
  },
  {
    "path": "thefuck/rules/tsuru_login.py",
    "content": "from thefuck.shells import shell\nfrom thefuck.utils import for_app\n\n\n@for_app('tsuru')\ndef match(command):\n    return ('not authenticated' in command.output\n            and 'session has expired' in command.output)\n\n\ndef get_new_command(command):\n    return shell.and_('tsuru login', command.script)\n"
  },
  {
    "path": "thefuck/rules/tsuru_not_command.py",
    "content": "import re\nfrom thefuck.utils import get_all_matched_commands, replace_command, for_app\n\n\n@for_app('tsuru')\ndef match(command):\n    return (' is not a tsuru command. See \"tsuru help\".' in command.output\n            and '\\nDid you mean?\\n\\t' in command.output)\n\n\ndef get_new_command(command):\n    broken_cmd = re.findall(r'tsuru: \"([^\"]*)\" is not a tsuru command',\n                            command.output)[0]\n    return replace_command(command, broken_cmd,\n                           get_all_matched_commands(command.output))\n"
  },
  {
    "path": "thefuck/rules/unknown_command.py",
    "content": "import re\nfrom thefuck.utils import replace_command\n\n\ndef match(command):\n    return (re.search(r\"([^:]*): Unknown command.*\", command.output) is not None\n            and re.search(r\"Did you mean ([^?]*)?\", command.output) is not None)\n\n\ndef get_new_command(command):\n    broken_cmd = re.findall(r\"([^:]*): Unknown command.*\", command.output)[0]\n    matched = re.findall(r\"Did you mean ([^?]*)?\", command.output)\n    return replace_command(command, broken_cmd, matched)\n"
  },
  {
    "path": "thefuck/rules/unsudo.py",
    "content": "patterns = ['you cannot perform this operation as root']\n\n\ndef match(command):\n    if command.script_parts and command.script_parts[0] != 'sudo':\n        return False\n\n    for pattern in patterns:\n        if pattern in command.output.lower():\n            return True\n    return False\n\n\ndef get_new_command(command):\n    return ' '.join(command.script_parts[1:])\n"
  },
  {
    "path": "thefuck/rules/vagrant_up.py",
    "content": "from thefuck.shells import shell\nfrom thefuck.utils import for_app\n\n\n@for_app('vagrant')\ndef match(command):\n    return 'run `vagrant up`' in command.output.lower()\n\n\ndef get_new_command(command):\n    cmds = command.script_parts\n    machine = None\n    if len(cmds) >= 3:\n        machine = cmds[2]\n\n    start_all_instances = shell.and_(u\"vagrant up\", command.script)\n    if machine is None:\n        return start_all_instances\n    else:\n        return [shell.and_(u\"vagrant up {}\".format(machine), command.script),\n                start_all_instances]\n"
  },
  {
    "path": "thefuck/rules/whois.py",
    "content": "# -*- encoding: utf-8 -*-\nfrom six.moves.urllib.parse import urlparse\nfrom thefuck.utils import for_app\n\n\n@for_app('whois', at_least=1)\ndef match(command):\n    \"\"\"\n    What the `whois` command returns depends on the 'Whois server' it contacted\n    and is not consistent through different servers. But there can be only two\n    types of errors I can think of with `whois`:\n        - `whois https://en.wikipedia.org/` → `whois en.wikipedia.org`;\n        - `whois en.wikipedia.org` → `whois wikipedia.org`.\n    So we match any `whois` command and then:\n        - if there is a slash: keep only the FQDN;\n        - if there is no slash but there is a point: removes the left-most\n          subdomain.\n\n    We cannot either remove all subdomains because we cannot know which part is\n    the subdomains and which is the domain, consider:\n        - www.google.fr → subdomain: www, domain: 'google.fr';\n        - google.co.uk → subdomain: None, domain; 'google.co.uk'.\n    \"\"\"\n    return True\n\n\ndef get_new_command(command):\n    url = command.script_parts[1]\n\n    if '/' in command.script:\n        return 'whois ' + urlparse(url).netloc\n    elif '.' in command.script:\n        path = urlparse(url).path.split('.')\n        return ['whois ' + '.'.join(path[n:]) for n in range(1, len(path))]\n"
  },
  {
    "path": "thefuck/rules/workon_doesnt_exists.py",
    "content": "from thefuck.utils import for_app, replace_command, eager, memoize\nfrom thefuck.system import Path\n\n\n@memoize\n@eager\ndef _get_all_environments():\n    root = Path('~/.virtualenvs').expanduser()\n    if not root.is_dir():\n        return\n\n    for child in root.iterdir():\n        if child.is_dir():\n            yield child.name\n\n\n@for_app('workon')\ndef match(command):\n    return (len(command.script_parts) >= 2\n            and command.script_parts[1] not in _get_all_environments())\n\n\ndef get_new_command(command):\n    misspelled_env = command.script_parts[1]\n    create_new = u'mkvirtualenv {}'.format(misspelled_env)\n\n    available = _get_all_environments()\n    if available:\n        return (replace_command(command, misspelled_env, available)\n                + [create_new])\n    else:\n        return create_new\n"
  },
  {
    "path": "thefuck/rules/wrong_hyphen_before_subcommand.py",
    "content": "from thefuck.utils import get_all_executables\nfrom thefuck.specific.sudo import sudo_support\n\n\n@sudo_support\ndef match(command):\n    first_part = command.script_parts[0]\n    if \"-\" not in first_part or first_part in get_all_executables():\n        return False\n    cmd, _ = first_part.split(\"-\", 1)\n    return cmd in get_all_executables()\n\n\n@sudo_support\ndef get_new_command(command):\n    return command.script.replace(\"-\", \" \", 1)\n\n\npriority = 4500\nrequires_output = False\n"
  },
  {
    "path": "thefuck/rules/yarn_alias.py",
    "content": "import re\nfrom thefuck.utils import replace_argument, for_app\n\n\n@for_app('yarn', at_least=1)\ndef match(command):\n    return 'Did you mean' in command.output\n\n\ndef get_new_command(command):\n    broken = command.script_parts[1]\n    fix = re.findall(r'Did you mean [`\"](?:yarn )?([^`\"]*)[`\"]', command.output)[0]\n\n    return replace_argument(command.script, broken, fix)\n"
  },
  {
    "path": "thefuck/rules/yarn_command_not_found.py",
    "content": "import re\nfrom subprocess import Popen, PIPE\nfrom thefuck.utils import (for_app, eager, replace_command, replace_argument,\n                           cache, which)\n\nregex = re.compile(r'error Command \"(.*)\" not found.')\n\n\n@for_app('yarn')\ndef match(command):\n    return regex.findall(command.output)\n\n\nnpm_commands = {'require': 'add'}\n\n\n@eager\ndef _get_all_tasks():\n    proc = Popen(['yarn', '--help'], stdout=PIPE)\n    should_yield = False\n    for line in proc.stdout.readlines():\n        line = line.decode().strip()\n\n        if 'Commands:' in line:\n            should_yield = True\n            continue\n\n        if should_yield and '- ' in line:\n            yield line.split(' ')[-1]\n\n\nif which('yarn'):\n    _get_all_tasks = cache(which('yarn'))(_get_all_tasks)\n\n\ndef get_new_command(command):\n    misspelled_task = regex.findall(command.output)[0]\n    if misspelled_task in npm_commands:\n        yarn_command = npm_commands[misspelled_task]\n        return replace_argument(command.script, misspelled_task, yarn_command)\n    else:\n        tasks = _get_all_tasks()\n        return replace_command(command, misspelled_task, tasks)\n"
  },
  {
    "path": "thefuck/rules/yarn_command_replaced.py",
    "content": "import re\nfrom thefuck.utils import for_app\n\nregex = re.compile(r'Run \"(.*)\" instead')\n\n\n@for_app('yarn', at_least=1)\ndef match(command):\n    return regex.findall(command.output)\n\n\ndef get_new_command(command):\n    return regex.findall(command.output)[0]\n"
  },
  {
    "path": "thefuck/rules/yarn_help.py",
    "content": "import re\nfrom thefuck.utils import for_app\nfrom thefuck.system import open_command\n\n\n@for_app('yarn', at_least=2)\ndef match(command):\n    return (command.script_parts[1] == 'help'\n            and 'for documentation about this command.' in command.output)\n\n\ndef get_new_command(command):\n    url = re.findall(\n        r'Visit ([^ ]*) for documentation about this command.',\n        command.output)[0]\n\n    return open_command(url)\n"
  },
  {
    "path": "thefuck/rules/yum_invalid_operation.py",
    "content": "import subprocess\nfrom itertools import dropwhile, islice, takewhile\n\nfrom thefuck.specific.sudo import sudo_support\nfrom thefuck.specific.yum import yum_available\nfrom thefuck.utils import for_app, replace_command, which, cache\n\nenabled_by_default = yum_available\n\n\n@sudo_support\n@for_app('yum')\ndef match(command):\n    return 'No such command: ' in command.output\n\n\ndef _get_operations():\n    proc = subprocess.Popen('yum', stdout=subprocess.PIPE)\n\n    lines = proc.stdout.readlines()\n    lines = [line.decode('utf-8') for line in lines]\n    lines = dropwhile(lambda line: not line.startswith(\"List of Commands:\"), lines)\n    lines = islice(lines, 2, None)\n    lines = list(takewhile(lambda line: line.strip(), lines))\n    return [line.strip().split(' ')[0] for line in lines]\n\n\nif which('yum'):\n    _get_operations = cache(which('yum'))(_get_operations)\n\n\n@sudo_support\ndef get_new_command(command):\n    invalid_operation = command.script_parts[1]\n\n    if invalid_operation == 'uninstall':\n        return [command.script.replace('uninstall', 'remove')]\n\n    return replace_command(command, invalid_operation, _get_operations())\n"
  },
  {
    "path": "thefuck/shells/__init__.py",
    "content": "\"\"\"Package with shell specific actions, each shell class should\nimplement `from_shell`, `to_shell`, `app_alias`, `put_to_history` and\n`get_aliases` methods.\n\"\"\"\nimport os\nfrom psutil import Process\nfrom .bash import Bash\nfrom .fish import Fish\nfrom .generic import Generic\nfrom .tcsh import Tcsh\nfrom .zsh import Zsh\nfrom .powershell import Powershell\n\nshells = {'bash': Bash,\n          'fish': Fish,\n          'zsh': Zsh,\n          'csh': Tcsh,\n          'tcsh': Tcsh,\n          'powershell': Powershell,\n          'pwsh': Powershell}\n\n\ndef _get_shell_from_env():\n    name = os.environ.get('TF_SHELL')\n\n    if name in shells:\n        return shells[name]()\n\n\ndef _get_shell_from_proc():\n    proc = Process(os.getpid())\n\n    while proc is not None and proc.pid > 0:\n        try:\n            name = proc.name()\n        except TypeError:\n            name = proc.name\n\n        name = os.path.splitext(name)[0]\n\n        if name in shells:\n            return shells[name]()\n\n        try:\n            proc = proc.parent()\n        except TypeError:\n            proc = proc.parent\n\n    return Generic()\n\n\nshell = _get_shell_from_env() or _get_shell_from_proc()\n"
  },
  {
    "path": "thefuck/shells/bash.py",
    "content": "import os\nfrom subprocess import Popen, PIPE\nfrom tempfile import gettempdir\nfrom uuid import uuid4\nfrom ..conf import settings\nfrom ..const import ARGUMENT_PLACEHOLDER, USER_COMMAND_MARK\nfrom ..utils import DEVNULL, memoize\nfrom .generic import Generic\n\n\nclass Bash(Generic):\n    friendly_name = 'Bash'\n\n    def app_alias(self, alias_name):\n        # It is VERY important to have the variables declared WITHIN the function\n        return '''\n            function {name} () {{\n                TF_PYTHONIOENCODING=$PYTHONIOENCODING;\n                export TF_SHELL=bash;\n                export TF_ALIAS={name};\n                export TF_SHELL_ALIASES=$(alias);\n                export TF_HISTORY=$(fc -ln -10);\n                export PYTHONIOENCODING=utf-8;\n                TF_CMD=$(\n                    thefuck {argument_placeholder} \"$@\"\n                ) && eval \"$TF_CMD\";\n                unset TF_HISTORY;\n                export PYTHONIOENCODING=$TF_PYTHONIOENCODING;\n                {alter_history}\n            }}\n        '''.format(\n            name=alias_name,\n            argument_placeholder=ARGUMENT_PLACEHOLDER,\n            alter_history=('history -s $TF_CMD;'\n                           if settings.alter_history else ''))\n\n    def instant_mode_alias(self, alias_name):\n        if os.environ.get('THEFUCK_INSTANT_MODE', '').lower() == 'true':\n            mark = USER_COMMAND_MARK + '\\b' * len(USER_COMMAND_MARK)\n            return '''\n                export PS1=\"{user_command_mark}$PS1\";\n                {app_alias}\n            '''.format(user_command_mark=mark,\n                       app_alias=self.app_alias(alias_name))\n        else:\n            log_path = os.path.join(\n                gettempdir(), 'thefuck-script-log-{}'.format(uuid4().hex))\n            return '''\n                export THEFUCK_INSTANT_MODE=True;\n                export THEFUCK_OUTPUT_LOG={log};\n                thefuck --shell-logger {log};\n                rm {log};\n                exit\n            '''.format(log=log_path)\n\n    def _parse_alias(self, alias):\n        name, value = alias.replace('alias ', '', 1).split('=', 1)\n        if value[0] == value[-1] == '\"' or value[0] == value[-1] == \"'\":\n            value = value[1:-1]\n        return name, value\n\n    @memoize\n    def get_aliases(self):\n        raw_aliases = os.environ.get('TF_SHELL_ALIASES', '').split('\\n')\n        return dict(self._parse_alias(alias)\n                    for alias in raw_aliases if alias and '=' in alias)\n\n    def _get_history_file_name(self):\n        return os.environ.get(\"HISTFILE\",\n                              os.path.expanduser('~/.bash_history'))\n\n    def _get_history_line(self, command_script):\n        return u'{}\\n'.format(command_script)\n\n    def how_to_configure(self):\n        if os.path.join(os.path.expanduser('~'), '.bashrc'):\n            config = '~/.bashrc'\n        elif os.path.join(os.path.expanduser('~'), '.bash_profile'):\n            config = '~/.bash_profile'\n        else:\n            config = 'bash config'\n\n        return self._create_shell_configuration(\n            content=u'eval \"$(thefuck --alias)\"',\n            path=config,\n            reload=u'source {}'.format(config))\n\n    def _get_version(self):\n        \"\"\"Returns the version of the current shell\"\"\"\n        proc = Popen(['bash', '-c', 'echo $BASH_VERSION'],\n                     stdout=PIPE, stderr=DEVNULL)\n        return proc.stdout.read().decode('utf-8').strip()\n"
  },
  {
    "path": "thefuck/shells/fish.py",
    "content": "from subprocess import Popen, PIPE\nfrom time import time\nimport os\nimport sys\nimport six\nfrom .. import logs\nfrom ..conf import settings\nfrom ..const import ARGUMENT_PLACEHOLDER\nfrom ..utils import DEVNULL, cache\nfrom .generic import Generic\n\n\n@cache('~/.config/fish/config.fish', '~/.config/fish/functions')\ndef _get_functions(overridden):\n    proc = Popen(['fish', '-ic', 'functions'], stdout=PIPE, stderr=DEVNULL)\n    functions = proc.stdout.read().decode('utf-8').strip().split('\\n')\n    return {func: func for func in functions if func not in overridden}\n\n\n@cache('~/.config/fish/config.fish')\ndef _get_aliases(overridden):\n    aliases = {}\n    proc = Popen(['fish', '-ic', 'alias'], stdout=PIPE, stderr=DEVNULL)\n    alias_out = proc.stdout.read().decode('utf-8').strip()\n    if not alias_out:\n        return aliases\n    for alias in alias_out.split('\\n'):\n        for separator in (' ', '='):\n            split_alias = alias.replace('alias ', '', 1).split(separator, 1)\n            if len(split_alias) == 2:\n                name, value = split_alias\n                break\n        else:\n            continue\n        if name not in overridden:\n            aliases[name] = value\n    return aliases\n\n\nclass Fish(Generic):\n    friendly_name = 'Fish Shell'\n\n    def _get_overridden_aliases(self):\n        overridden = os.environ.get('THEFUCK_OVERRIDDEN_ALIASES',\n                                    os.environ.get('TF_OVERRIDDEN_ALIASES', ''))\n        default = {'cd', 'grep', 'ls', 'man', 'open'}\n        for alias in overridden.split(','):\n            default.add(alias.strip())\n        return sorted(default)\n\n    def app_alias(self, alias_name):\n        if settings.alter_history:\n            alter_history = ('    builtin history delete --exact'\n                             ' --case-sensitive -- $fucked_up_command\\n'\n                             '    builtin history merge\\n')\n        else:\n            alter_history = ''\n        # It is VERY important to have the variables declared WITHIN the alias\n        return ('function {0} -d \"Correct your previous console command\"\\n'\n                '  set -l fucked_up_command $history[1]\\n'\n                '  env TF_SHELL=fish TF_ALIAS={0} PYTHONIOENCODING=utf-8'\n                ' thefuck $fucked_up_command {2} $argv | read -l unfucked_command\\n'\n                '  if [ \"$unfucked_command\" != \"\" ]\\n'\n                '    eval $unfucked_command\\n{1}'\n                '  end\\n'\n                'end').format(alias_name, alter_history, ARGUMENT_PLACEHOLDER)\n\n    def get_aliases(self):\n        overridden = self._get_overridden_aliases()\n        functions = _get_functions(overridden)\n        raw_aliases = _get_aliases(overridden)\n        functions.update(raw_aliases)\n        return functions\n\n    def _expand_aliases(self, command_script):\n        aliases = self.get_aliases()\n        binary = command_script.split(' ')[0]\n        if binary in aliases and aliases[binary] != binary:\n            return command_script.replace(binary, aliases[binary], 1)\n        elif binary in aliases:\n            return u'fish -ic \"{}\"'.format(command_script.replace('\"', r'\\\"'))\n        else:\n            return command_script\n\n    def _get_history_file_name(self):\n        return os.path.expanduser('~/.config/fish/fish_history')\n\n    def _get_history_line(self, command_script):\n        return u'- cmd: {}\\n   when: {}\\n'.format(command_script, int(time()))\n\n    def _script_from_history(self, line):\n        if '- cmd: ' in line:\n            return line.split('- cmd: ', 1)[1]\n        else:\n            return ''\n\n    def and_(self, *commands):\n        return u'; and '.join(commands)\n\n    def or_(self, *commands):\n        return u'; or '.join(commands)\n\n    def how_to_configure(self):\n        return self._create_shell_configuration(\n            content=u\"thefuck --alias | source\",\n            path='~/.config/fish/config.fish',\n            reload='fish')\n\n    def _get_version(self):\n        \"\"\"Returns the version of the current shell\"\"\"\n        proc = Popen(['fish', '--version'], stdout=PIPE, stderr=DEVNULL)\n        return proc.stdout.read().decode('utf-8').split()[-1]\n\n    def put_to_history(self, command):\n        try:\n            return self._put_to_history(command)\n        except IOError:\n            logs.exception(\"Can't update history\", sys.exc_info())\n\n    def _put_to_history(self, command_script):\n        \"\"\"Puts command script to shell history.\"\"\"\n        history_file_name = self._get_history_file_name()\n        if os.path.isfile(history_file_name):\n            with open(history_file_name, 'a') as history:\n                entry = self._get_history_line(command_script)\n                if six.PY2:\n                    history.write(entry.encode('utf-8'))\n                else:\n                    history.write(entry)\n"
  },
  {
    "path": "thefuck/shells/generic.py",
    "content": "import io\nimport os\nimport shlex\nimport six\nfrom collections import namedtuple\nfrom ..logs import warn\nfrom ..utils import memoize\nfrom ..conf import settings\nfrom ..system import Path\n\n\nShellConfiguration = namedtuple('ShellConfiguration', (\n    'content', 'path', 'reload', 'can_configure_automatically'))\n\n\nclass Generic(object):\n    friendly_name = 'Generic Shell'\n\n    def get_aliases(self):\n        return {}\n\n    def _expand_aliases(self, command_script):\n        aliases = self.get_aliases()\n        binary = command_script.split(' ')[0]\n        if binary in aliases:\n            return command_script.replace(binary, aliases[binary], 1)\n        else:\n            return command_script\n\n    def from_shell(self, command_script):\n        \"\"\"Prepares command before running in app.\"\"\"\n        return self._expand_aliases(command_script)\n\n    def to_shell(self, command_script):\n        \"\"\"Prepares command for running in shell.\"\"\"\n        return command_script\n\n    def app_alias(self, alias_name):\n        return \"\"\"alias {0}='eval \"$(TF_ALIAS={0} PYTHONIOENCODING=utf-8 \"\"\" \\\n               \"\"\"thefuck \"$(fc -ln -1)\")\"'\"\"\".format(alias_name)\n\n    def instant_mode_alias(self, alias_name):\n        warn(\"Instant mode not supported by your shell\")\n        return self.app_alias(alias_name)\n\n    def _get_history_file_name(self):\n        return ''\n\n    def _get_history_line(self, command_script):\n        return ''\n\n    @memoize\n    def get_history(self):\n        return list(self._get_history_lines())\n\n    def _get_history_lines(self):\n        \"\"\"Returns list of history entries.\"\"\"\n        history_file_name = self._get_history_file_name()\n        if os.path.isfile(history_file_name):\n            with io.open(history_file_name, 'r',\n                         encoding='utf-8', errors='ignore') as history_file:\n\n                lines = history_file.readlines()\n                if settings.history_limit:\n                    lines = lines[-settings.history_limit:]\n\n                for line in lines:\n                    prepared = self._script_from_history(line) \\\n                        .strip()\n                    if prepared:\n                        yield prepared\n\n    def and_(self, *commands):\n        return u' && '.join(commands)\n\n    def or_(self, *commands):\n        return u' || '.join(commands)\n\n    def how_to_configure(self):\n        return\n\n    def split_command(self, command):\n        \"\"\"Split the command using shell-like syntax.\"\"\"\n        encoded = self.encode_utf8(command)\n\n        try:\n            splitted = [s.replace(\"??\", \"\\\\ \") for s in shlex.split(encoded.replace('\\\\ ', '??'))]\n        except ValueError:\n            splitted = encoded.split(' ')\n\n        return self.decode_utf8(splitted)\n\n    def encode_utf8(self, command):\n        if six.PY2:\n            return command.encode('utf8')\n        return command\n\n    def decode_utf8(self, command_parts):\n        if six.PY2:\n            return [s.decode('utf8') for s in command_parts]\n        return command_parts\n\n    def quote(self, s):\n        \"\"\"Return a shell-escaped version of the string s.\"\"\"\n\n        if six.PY2:\n            from pipes import quote\n        else:\n            from shlex import quote\n\n        return quote(s)\n\n    def _script_from_history(self, line):\n        return line\n\n    def put_to_history(self, command):\n        \"\"\"Adds fixed command to shell history.\n\n        In most of shells we change history on shell-level, but not\n        all shells support it (Fish).\n\n        \"\"\"\n\n    def get_builtin_commands(self):\n        \"\"\"Returns shells builtin commands.\"\"\"\n        return ['alias', 'bg', 'bind', 'break', 'builtin', 'case', 'cd',\n                'command', 'compgen', 'complete', 'continue', 'declare',\n                'dirs', 'disown', 'echo', 'enable', 'eval', 'exec', 'exit',\n                'export', 'fc', 'fg', 'getopts', 'hash', 'help', 'history',\n                'if', 'jobs', 'kill', 'let', 'local', 'logout', 'popd',\n                'printf', 'pushd', 'pwd', 'read', 'readonly', 'return', 'set',\n                'shift', 'shopt', 'source', 'suspend', 'test', 'times', 'trap',\n                'type', 'typeset', 'ulimit', 'umask', 'unalias', 'unset',\n                'until', 'wait', 'while']\n\n    def _get_version(self):\n        \"\"\"Returns the version of the current shell\"\"\"\n        return ''\n\n    def info(self):\n        \"\"\"Returns the name and version of the current shell\"\"\"\n        try:\n            version = self._get_version()\n        except Exception as e:\n            warn(u'Could not determine shell version: {}'.format(e))\n            version = ''\n        return u'{} {}'.format(self.friendly_name, version).rstrip()\n\n    def _create_shell_configuration(self, content, path, reload):\n        return ShellConfiguration(\n            content=content,\n            path=path,\n            reload=reload,\n            can_configure_automatically=Path(path).expanduser().exists())\n"
  },
  {
    "path": "thefuck/shells/powershell.py",
    "content": "from subprocess import Popen, PIPE\nfrom ..utils import DEVNULL\nfrom .generic import Generic, ShellConfiguration\n\n\nclass Powershell(Generic):\n    friendly_name = 'PowerShell'\n\n    def app_alias(self, alias_name):\n        return 'function ' + alias_name + ' {\\n' \\\n               '    $history = (Get-History -Count 1).CommandLine;\\n' \\\n               '    if (-not [string]::IsNullOrWhiteSpace($history)) {\\n' \\\n               '        $fuck = $(thefuck $args $history);\\n' \\\n               '        if (-not [string]::IsNullOrWhiteSpace($fuck)) {\\n' \\\n               '            if ($fuck.StartsWith(\"echo\")) { $fuck = $fuck.Substring(5); }\\n' \\\n               '            else { iex \"$fuck\"; }\\n' \\\n               '        }\\n' \\\n               '    }\\n' \\\n               '    [Console]::ResetColor() \\n' \\\n               '}\\n'\n\n    def and_(self, *commands):\n        return u' -and '.join('({0})'.format(c) for c in commands)\n\n    def how_to_configure(self):\n        return ShellConfiguration(\n            content=u'iex \"$(thefuck --alias)\"',\n            path='$profile',\n            reload='. $profile',\n            can_configure_automatically=False)\n\n    def _get_version(self):\n        \"\"\"Returns the version of the current shell\"\"\"\n        try:\n            proc = Popen(\n                ['powershell.exe', '$PSVersionTable.PSVersion'],\n                stdout=PIPE,\n                stderr=DEVNULL)\n            version = proc.stdout.read().decode('utf-8').rstrip().split('\\n')\n            return '.'.join(version[-1].split())\n        except IOError:\n            proc = Popen(['pwsh', '--version'], stdout=PIPE, stderr=DEVNULL)\n            return proc.stdout.read().decode('utf-8').split()[-1]\n"
  },
  {
    "path": "thefuck/shells/tcsh.py",
    "content": "from subprocess import Popen, PIPE\nfrom time import time\nimport os\nfrom ..utils import DEVNULL, memoize\nfrom .generic import Generic\n\n\nclass Tcsh(Generic):\n    friendly_name = 'Tcsh'\n\n    def app_alias(self, alias_name):\n        return (\"alias {0} 'setenv TF_SHELL tcsh && setenv TF_ALIAS {0} && \"\n                \"set fucked_cmd=`history -h 2 | head -n 1` && \"\n                \"eval `thefuck ${{fucked_cmd}}`'\").format(alias_name)\n\n    def _parse_alias(self, alias):\n        name, value = alias.split(\"\\t\", 1)\n        return name, value\n\n    @memoize\n    def get_aliases(self):\n        proc = Popen(['tcsh', '-ic', 'alias'], stdout=PIPE, stderr=DEVNULL)\n        return dict(\n            self._parse_alias(alias)\n            for alias in proc.stdout.read().decode('utf-8').split('\\n')\n            if alias and '\\t' in alias)\n\n    def _get_history_file_name(self):\n        return os.environ.get(\"HISTFILE\",\n                              os.path.expanduser('~/.history'))\n\n    def _get_history_line(self, command_script):\n        return u'#+{}\\n{}\\n'.format(int(time()), command_script)\n\n    def how_to_configure(self):\n        return self._create_shell_configuration(\n            content=u'eval `thefuck --alias`',\n            path='~/.tcshrc',\n            reload='tcsh')\n\n    def _get_version(self):\n        \"\"\"Returns the version of the current shell\"\"\"\n        proc = Popen(['tcsh', '--version'], stdout=PIPE, stderr=DEVNULL)\n        return proc.stdout.read().decode('utf-8').split()[1]\n"
  },
  {
    "path": "thefuck/shells/zsh.py",
    "content": "from time import time\nimport os\nfrom subprocess import Popen, PIPE\nfrom tempfile import gettempdir\nfrom uuid import uuid4\nfrom ..conf import settings\nfrom ..const import ARGUMENT_PLACEHOLDER, USER_COMMAND_MARK\nfrom ..utils import DEVNULL, memoize\nfrom .generic import Generic\n\n\nclass Zsh(Generic):\n    friendly_name = 'ZSH'\n\n    def app_alias(self, alias_name):\n        # It is VERY important to have the variables declared WITHIN the function\n        return '''\n            {name} () {{\n                TF_PYTHONIOENCODING=$PYTHONIOENCODING;\n                export TF_SHELL=zsh;\n                export TF_ALIAS={name};\n                TF_SHELL_ALIASES=$(alias);\n                export TF_SHELL_ALIASES;\n                TF_HISTORY=\"$(fc -ln -10)\";\n                export TF_HISTORY;\n                export PYTHONIOENCODING=utf-8;\n                TF_CMD=$(\n                    thefuck {argument_placeholder} $@\n                ) && eval $TF_CMD;\n                unset TF_HISTORY;\n                export PYTHONIOENCODING=$TF_PYTHONIOENCODING;\n                {alter_history}\n            }}\n        '''.format(\n            name=alias_name,\n            argument_placeholder=ARGUMENT_PLACEHOLDER,\n            alter_history=('test -n \"$TF_CMD\" && print -s $TF_CMD'\n                           if settings.alter_history else ''))\n\n    def instant_mode_alias(self, alias_name):\n        if os.environ.get('THEFUCK_INSTANT_MODE', '').lower() == 'true':\n            mark = ('%{' +\n                    USER_COMMAND_MARK + '\\b' * len(USER_COMMAND_MARK)\n                    + '%}')\n            return '''\n                export PS1=\"{user_command_mark}$PS1\";\n                {app_alias}\n            '''.format(user_command_mark=mark,\n                       app_alias=self.app_alias(alias_name))\n        else:\n            log_path = os.path.join(\n                gettempdir(), 'thefuck-script-log-{}'.format(uuid4().hex))\n            return '''\n                export THEFUCK_INSTANT_MODE=True;\n                export THEFUCK_OUTPUT_LOG={log};\n                thefuck --shell-logger {log};\n                rm -f {log};\n                exit\n            '''.format(log=log_path)\n\n    def _parse_alias(self, alias):\n        name, value = alias.split('=', 1)\n        if value[0] == value[-1] == '\"' or value[0] == value[-1] == \"'\":\n            value = value[1:-1]\n        return name, value\n\n    @memoize\n    def get_aliases(self):\n        raw_aliases = os.environ.get('TF_SHELL_ALIASES', '').split('\\n')\n        return dict(self._parse_alias(alias)\n                    for alias in raw_aliases if alias and '=' in alias)\n\n    def _get_history_file_name(self):\n        return os.environ.get(\"HISTFILE\",\n                              os.path.expanduser('~/.zsh_history'))\n\n    def _get_history_line(self, command_script):\n        return u': {}:0;{}\\n'.format(int(time()), command_script)\n\n    def _script_from_history(self, line):\n        if ';' in line:\n            return line.split(';', 1)[1]\n        else:\n            return ''\n\n    def how_to_configure(self):\n        return self._create_shell_configuration(\n            content=u'eval $(thefuck --alias)',\n            path='~/.zshrc',\n            reload='source ~/.zshrc')\n\n    def _get_version(self):\n        \"\"\"Returns the version of the current shell\"\"\"\n        proc = Popen(['zsh', '-c', 'echo $ZSH_VERSION'],\n                     stdout=PIPE, stderr=DEVNULL)\n        return proc.stdout.read().decode('utf-8').strip()\n"
  },
  {
    "path": "thefuck/specific/__init__.py",
    "content": ""
  },
  {
    "path": "thefuck/specific/apt.py",
    "content": "from thefuck.utils import which\n\napt_available = bool(which('apt-get'))\n"
  },
  {
    "path": "thefuck/specific/archlinux.py",
    "content": "\"\"\" This file provide some utility functions for Arch Linux specific rules.\"\"\"\nimport subprocess\nfrom .. import utils\n\n\n@utils.memoize\ndef get_pkgfile(command):\n    \"\"\" Gets the packages that provide the given command using `pkgfile`.\n\n    If the command is of the form `sudo foo`, searches for the `foo` command\n    instead.\n    \"\"\"\n    try:\n        command = command.strip()\n\n        if command.startswith('sudo '):\n            command = command[5:]\n\n        command = command.split(\" \")[0]\n\n        packages = subprocess.check_output(\n            ['pkgfile', '-b', '-v', command],\n            universal_newlines=True, stderr=utils.DEVNULL\n        ).splitlines()\n\n        return [package.split()[0] for package in packages]\n    except subprocess.CalledProcessError as err:\n        if err.returncode == 1 and err.output == \"\":\n            return []\n        else:\n            raise err\n\n\ndef archlinux_env():\n    if utils.which('yay'):\n        pacman = 'yay'\n    elif utils.which('pikaur'):\n        pacman = 'pikaur'\n    elif utils.which('yaourt'):\n        pacman = 'yaourt'\n    elif utils.which('pacman'):\n        pacman = 'sudo pacman'\n    else:\n        return False, None\n\n    enabled_by_default = utils.which('pkgfile')\n\n    return enabled_by_default, pacman\n"
  },
  {
    "path": "thefuck/specific/brew.py",
    "content": "import subprocess\nfrom ..utils import memoize, which\n\n\nbrew_available = bool(which('brew'))\n\n\n@memoize\ndef get_brew_path_prefix():\n    \"\"\"To get brew path\"\"\"\n    try:\n        return subprocess.check_output(['brew', '--prefix'],\n                                       universal_newlines=True).strip()\n    except Exception:\n        return None\n"
  },
  {
    "path": "thefuck/specific/dnf.py",
    "content": "from thefuck.utils import which\n\ndnf_available = bool(which('dnf'))\n"
  },
  {
    "path": "thefuck/specific/git.py",
    "content": "import re\nfrom decorator import decorator\nfrom ..utils import is_app\nfrom ..shells import shell\n\n\n@decorator\ndef git_support(fn, command):\n    \"\"\"Resolves git aliases and supports testing for both git and hub.\"\"\"\n    # supports GitHub's `hub` command\n    # which is recommended to be used with `alias git=hub`\n    # but at this point, shell aliases have already been resolved\n    if not is_app(command, 'git', 'hub'):\n        return False\n\n    # perform git aliases expansion\n    if command.output and 'trace: alias expansion:' in command.output:\n        search = re.search(\"trace: alias expansion: ([^ ]*) => ([^\\n]*)\",\n                           command.output)\n        alias = search.group(1)\n\n        # by default git quotes everything, for example:\n        #     'commit' '--amend'\n        # which is surprising and does not allow to easily test for\n        # eg. 'git commit'\n        expansion = ' '.join(shell.quote(part)\n                             for part in shell.split_command(search.group(2)))\n        new_script = re.sub(r\"\\b{}\\b\".format(alias), expansion, command.script)\n\n        command = command.update(script=new_script)\n\n    return fn(command)\n"
  },
  {
    "path": "thefuck/specific/nix.py",
    "content": "from thefuck.utils import which\n\nnix_available = bool(which('nix'))\n"
  },
  {
    "path": "thefuck/specific/npm.py",
    "content": "import re\nfrom subprocess import Popen, PIPE\nfrom thefuck.utils import memoize, eager, which\n\nnpm_available = bool(which('npm'))\n\n\n@memoize\n@eager\ndef get_scripts():\n    \"\"\"Get custom npm scripts.\"\"\"\n    proc = Popen(['npm', 'run-script'], stdout=PIPE)\n    should_yeild = False\n    for line in proc.stdout.readlines():\n        line = line.decode()\n        if 'available via `npm run-script`:' in line:\n            should_yeild = True\n            continue\n\n        if should_yeild and re.match(r'^  [^ ]+', line):\n            yield line.strip().split(' ')[0]\n"
  },
  {
    "path": "thefuck/specific/sudo.py",
    "content": "import six\nfrom decorator import decorator\n\n\n@decorator\ndef sudo_support(fn, command):\n    \"\"\"Removes sudo before calling fn and adds it after.\"\"\"\n    if not command.script.startswith('sudo '):\n        return fn(command)\n\n    result = fn(command.update(script=command.script[5:]))\n\n    if result and isinstance(result, six.string_types):\n        return u'sudo {}'.format(result)\n    elif isinstance(result, list):\n        return [u'sudo {}'.format(x) for x in result]\n    else:\n        return result\n"
  },
  {
    "path": "thefuck/specific/yum.py",
    "content": "from thefuck.utils import which\n\nyum_available = bool(which('yum'))\n"
  },
  {
    "path": "thefuck/system/__init__.py",
    "content": "import sys\n\n\nif sys.platform == 'win32':\n    from .win32 import *  # noqa: F401,F403\nelse:\n    from .unix import *  # noqa: F401,F403\n"
  },
  {
    "path": "thefuck/system/unix.py",
    "content": "import os\nimport sys\nimport tty\nimport termios\nimport colorama\nfrom distutils.spawn import find_executable\nfrom .. import const\n\ninit_output = colorama.init\n\n\ndef getch():\n    fd = sys.stdin.fileno()\n    old = termios.tcgetattr(fd)\n    try:\n        tty.setraw(fd)\n        return sys.stdin.read(1)\n    finally:\n        termios.tcsetattr(fd, termios.TCSADRAIN, old)\n\n\ndef get_key():\n    ch = getch()\n\n    if ch in const.KEY_MAPPING:\n        return const.KEY_MAPPING[ch]\n    elif ch == '\\x1b':\n        next_ch = getch()\n        if next_ch == '[':\n            last_ch = getch()\n\n            if last_ch == 'A':\n                return const.KEY_UP\n            elif last_ch == 'B':\n                return const.KEY_DOWN\n\n    return ch\n\n\ndef open_command(arg):\n    if find_executable('xdg-open'):\n        return 'xdg-open ' + arg\n    return 'open ' + arg\n\n\ntry:\n    from pathlib import Path\nexcept ImportError:\n    from pathlib2 import Path\n\n\ndef _expanduser(self):\n    return self.__class__(os.path.expanduser(str(self)))\n\n\nif not hasattr(Path, 'expanduser'):\n    Path.expanduser = _expanduser\n"
  },
  {
    "path": "thefuck/system/win32.py",
    "content": "import os\nimport msvcrt\nimport win_unicode_console\nfrom .. import const\n\n\ndef init_output():\n    import colorama\n    win_unicode_console.enable()\n    colorama.init()\n\n\ndef get_key():\n    ch = msvcrt.getwch()\n    if ch in ('\\x00', '\\xe0'):  # arrow or function key prefix?\n        ch = msvcrt.getwch()  # second call returns the actual key code\n\n    if ch in const.KEY_MAPPING:\n        return const.KEY_MAPPING[ch]\n    if ch == 'H':\n        return const.KEY_UP\n    if ch == 'P':\n        return const.KEY_DOWN\n\n    return ch\n\n\ndef open_command(arg):\n    return 'cmd /c start ' + arg\n\n\ntry:\n    from pathlib import Path\nexcept ImportError:\n    from pathlib2 import Path\n\n\ndef _expanduser(self):\n    return self.__class__(os.path.expanduser(str(self)))\n\n\n# pathlib's expanduser fails on windows, see http://bugs.python.org/issue19776\nPath.expanduser = _expanduser\n"
  },
  {
    "path": "thefuck/types.py",
    "content": "import os\nimport sys\nfrom . import logs\nfrom .shells import shell\nfrom .conf import settings, load_source\nfrom .const import DEFAULT_PRIORITY, ALL_ENABLED\nfrom .exceptions import EmptyCommand\nfrom .utils import get_alias, format_raw_script\nfrom .output_readers import get_output\n\n\nclass Command(object):\n    \"\"\"Command that should be fixed.\"\"\"\n\n    def __init__(self, script, output):\n        \"\"\"Initializes command with given values.\n\n        :type script: basestring\n        :type output: basestring\n\n        \"\"\"\n        self.script = script\n        self.output = output\n\n    @property\n    def stdout(self):\n        logs.warn('`stdout` is deprecated, please use `output` instead')\n        return self.output\n\n    @property\n    def stderr(self):\n        logs.warn('`stderr` is deprecated, please use `output` instead')\n        return self.output\n\n    @property\n    def script_parts(self):\n        if not hasattr(self, '_script_parts'):\n            try:\n                self._script_parts = shell.split_command(self.script)\n            except Exception:\n                logs.debug(u\"Can't split command script {} because:\\n {}\".format(\n                    self, sys.exc_info()))\n                self._script_parts = []\n\n        return self._script_parts\n\n    def __eq__(self, other):\n        if isinstance(other, Command):\n            return (self.script, self.output) == (other.script, other.output)\n        else:\n            return False\n\n    def __repr__(self):\n        return u'Command(script={}, output={})'.format(\n            self.script, self.output)\n\n    def update(self, **kwargs):\n        \"\"\"Returns new command with replaced fields.\n\n        :rtype: Command\n\n        \"\"\"\n        kwargs.setdefault('script', self.script)\n        kwargs.setdefault('output', self.output)\n        return Command(**kwargs)\n\n    @classmethod\n    def from_raw_script(cls, raw_script):\n        \"\"\"Creates instance of `Command` from a list of script parts.\n\n        :type raw_script: [basestring]\n        :rtype: Command\n        :raises: EmptyCommand\n\n        \"\"\"\n        script = format_raw_script(raw_script)\n        if not script:\n            raise EmptyCommand\n\n        expanded = shell.from_shell(script)\n        output = get_output(script, expanded)\n        return cls(expanded, output)\n\n\nclass Rule(object):\n    \"\"\"Rule for fixing commands.\"\"\"\n\n    def __init__(self, name, match, get_new_command,\n                 enabled_by_default, side_effect,\n                 priority, requires_output):\n        \"\"\"Initializes rule with given fields.\n\n        :type name: basestring\n        :type match: (Command) -> bool\n        :type get_new_command: (Command) -> (basestring | [basestring])\n        :type enabled_by_default: boolean\n        :type side_effect: (Command, basestring) -> None\n        :type priority: int\n        :type requires_output: bool\n\n        \"\"\"\n        self.name = name\n        self.match = match\n        self.get_new_command = get_new_command\n        self.enabled_by_default = enabled_by_default\n        self.side_effect = side_effect\n        self.priority = priority\n        self.requires_output = requires_output\n\n    def __eq__(self, other):\n        if isinstance(other, Rule):\n            return ((self.name, self.match, self.get_new_command,\n                     self.enabled_by_default, self.side_effect,\n                     self.priority, self.requires_output)\n                    == (other.name, other.match, other.get_new_command,\n                        other.enabled_by_default, other.side_effect,\n                        other.priority, other.requires_output))\n        else:\n            return False\n\n    def __repr__(self):\n        return 'Rule(name={}, match={}, get_new_command={}, ' \\\n               'enabled_by_default={}, side_effect={}, ' \\\n               'priority={}, requires_output={})'.format(\n                   self.name, self.match, self.get_new_command,\n                   self.enabled_by_default, self.side_effect,\n                   self.priority, self.requires_output)\n\n    @classmethod\n    def from_path(cls, path):\n        \"\"\"Creates rule instance from path.\n\n        :type path: pathlib.Path\n        :rtype: Rule\n\n        \"\"\"\n        name = path.name[:-3]\n        if name in settings.exclude_rules:\n            logs.debug(u'Ignoring excluded rule: {}'.format(name))\n            return\n        with logs.debug_time(u'Importing rule: {};'.format(name)):\n            try:\n                rule_module = load_source(name, str(path))\n            except Exception:\n                logs.exception(u\"Rule {} failed to load\".format(name), sys.exc_info())\n                return\n        priority = getattr(rule_module, 'priority', DEFAULT_PRIORITY)\n        return cls(name, rule_module.match,\n                   rule_module.get_new_command,\n                   getattr(rule_module, 'enabled_by_default', True),\n                   getattr(rule_module, 'side_effect', None),\n                   settings.priority.get(name, priority),\n                   getattr(rule_module, 'requires_output', True))\n\n    @property\n    def is_enabled(self):\n        \"\"\"Returns `True` when rule enabled.\n\n        :rtype: bool\n\n        \"\"\"\n        return (\n            self.name in settings.rules\n            or self.enabled_by_default\n            and ALL_ENABLED in settings.rules\n        )\n\n    def is_match(self, command):\n        \"\"\"Returns `True` if rule matches the command.\n\n        :type command: Command\n        :rtype: bool\n\n        \"\"\"\n        if command.output is None and self.requires_output:\n            return False\n\n        try:\n            with logs.debug_time(u'Trying rule: {};'.format(self.name)):\n                if self.match(command):\n                    return True\n        except Exception:\n            logs.rule_failed(self, sys.exc_info())\n\n    def get_corrected_commands(self, command):\n        \"\"\"Returns generator with corrected commands.\n\n        :type command: Command\n        :rtype: Iterable[CorrectedCommand]\n\n        \"\"\"\n        new_commands = self.get_new_command(command)\n        if not isinstance(new_commands, list):\n            new_commands = (new_commands,)\n        for n, new_command in enumerate(new_commands):\n            yield CorrectedCommand(script=new_command,\n                                   side_effect=self.side_effect,\n                                   priority=(n + 1) * self.priority)\n\n\nclass CorrectedCommand(object):\n    \"\"\"Corrected by rule command.\"\"\"\n\n    def __init__(self, script, side_effect, priority):\n        \"\"\"Initializes instance with given fields.\n\n        :type script: basestring\n        :type side_effect: (Command, basestring) -> None\n        :type priority: int\n\n        \"\"\"\n        self.script = script\n        self.side_effect = side_effect\n        self.priority = priority\n\n    def __eq__(self, other):\n        \"\"\"Ignores `priority` field.\"\"\"\n        if isinstance(other, CorrectedCommand):\n            return (other.script, other.side_effect) == \\\n                   (self.script, self.side_effect)\n        else:\n            return False\n\n    def __hash__(self):\n        return (self.script, self.side_effect).__hash__()\n\n    def __repr__(self):\n        return u'CorrectedCommand(script={}, side_effect={}, priority={})'.format(\n            self.script, self.side_effect, self.priority)\n\n    def _get_script(self):\n        \"\"\"Returns fixed commands script.\n\n        If `settings.repeat` is `True`, appends command with second attempt\n        of running fuck in case fixed command fails again.\n\n        \"\"\"\n        if settings.repeat:\n            repeat_fuck = '{} --repeat {}--force-command {}'.format(\n                get_alias(),\n                '--debug ' if settings.debug else '',\n                shell.quote(self.script))\n            return shell.or_(self.script, repeat_fuck)\n        else:\n            return self.script\n\n    def run(self, old_cmd):\n        \"\"\"Runs command from rule for passed command.\n\n        :type old_cmd: Command\n\n        \"\"\"\n        if self.side_effect:\n            self.side_effect(old_cmd, self.script)\n        if settings.alter_history:\n            shell.put_to_history(self.script)\n        # This depends on correct setting of PYTHONIOENCODING by the alias:\n        logs.debug(u'PYTHONIOENCODING: {}'.format(\n            os.environ.get('PYTHONIOENCODING', '!!not-set!!')))\n\n        sys.stdout.write(self._get_script())\n"
  },
  {
    "path": "thefuck/ui.py",
    "content": "# -*- encoding: utf-8 -*-\n\nimport sys\nfrom .conf import settings\nfrom .exceptions import NoRuleMatched\nfrom .system import get_key\nfrom .utils import get_alias\nfrom . import logs, const\n\n\ndef read_actions():\n    \"\"\"Yields actions for pressed keys.\"\"\"\n    while True:\n        key = get_key()\n\n        # Handle arrows, j/k (qwerty), and n/e (colemak)\n        if key in (const.KEY_UP, const.KEY_CTRL_N, 'k', 'e'):\n            yield const.ACTION_PREVIOUS\n        elif key in (const.KEY_DOWN, const.KEY_CTRL_P, 'j', 'n'):\n            yield const.ACTION_NEXT\n        elif key in (const.KEY_CTRL_C, 'q'):\n            yield const.ACTION_ABORT\n        elif key in ('\\n', '\\r'):\n            yield const.ACTION_SELECT\n\n\nclass CommandSelector(object):\n    \"\"\"Helper for selecting rule from rules list.\"\"\"\n\n    def __init__(self, commands):\n        \"\"\":type commands: Iterable[thefuck.types.CorrectedCommand]\"\"\"\n        self._commands_gen = commands\n        try:\n            self._commands = [next(self._commands_gen)]\n        except StopIteration:\n            raise NoRuleMatched\n        self._realised = False\n        self._index = 0\n\n    def _realise(self):\n        if not self._realised:\n            self._commands += list(self._commands_gen)\n            self._realised = True\n\n    def next(self):\n        self._realise()\n        self._index = (self._index + 1) % len(self._commands)\n\n    def previous(self):\n        self._realise()\n        self._index = (self._index - 1) % len(self._commands)\n\n    @property\n    def value(self):\n        \"\"\":rtype thefuck.types.CorrectedCommand\"\"\"\n        return self._commands[self._index]\n\n\ndef select_command(corrected_commands):\n    \"\"\"Returns:\n\n     - the first command when confirmation disabled;\n     - None when ctrl+c pressed;\n     - selected command.\n\n    :type corrected_commands: Iterable[thefuck.types.CorrectedCommand]\n    :rtype: thefuck.types.CorrectedCommand | None\n\n    \"\"\"\n    try:\n        selector = CommandSelector(corrected_commands)\n    except NoRuleMatched:\n        logs.failed('No fucks given' if get_alias() == 'fuck'\n                    else 'Nothing found')\n        return\n\n    if not settings.require_confirmation:\n        logs.show_corrected_command(selector.value)\n        return selector.value\n\n    logs.confirm_text(selector.value)\n\n    for action in read_actions():\n        if action == const.ACTION_SELECT:\n            sys.stderr.write('\\n')\n            return selector.value\n        elif action == const.ACTION_ABORT:\n            logs.failed('\\nAborted')\n            return\n        elif action == const.ACTION_PREVIOUS:\n            selector.previous()\n            logs.confirm_text(selector.value)\n        elif action == const.ACTION_NEXT:\n            selector.next()\n            logs.confirm_text(selector.value)\n"
  },
  {
    "path": "thefuck/utils.py",
    "content": "import atexit\nimport os\nimport pickle\nimport re\nimport shelve\nimport sys\nimport six\nfrom decorator import decorator\nfrom difflib import get_close_matches as difflib_get_close_matches\nfrom functools import wraps\nfrom .logs import warn, exception\nfrom .conf import settings\nfrom .system import Path\n\nDEVNULL = open(os.devnull, 'w')\n\nif six.PY2:\n    import anydbm\n    shelve_open_error = anydbm.error\nelse:\n    import dbm\n    shelve_open_error = dbm.error\n\n\ndef memoize(fn):\n    \"\"\"Caches previous calls to the function.\"\"\"\n    memo = {}\n\n    @wraps(fn)\n    def wrapper(*args, **kwargs):\n        if not memoize.disabled:\n            key = pickle.dumps((args, kwargs))\n            if key not in memo:\n                memo[key] = fn(*args, **kwargs)\n            value = memo[key]\n        else:\n            # Memoize is disabled, call the function\n            value = fn(*args, **kwargs)\n\n        return value\n\n    return wrapper\n\n\nmemoize.disabled = False\n\n\n@memoize\ndef which(program):\n    \"\"\"Returns `program` path or `None`.\"\"\"\n    try:\n        from shutil import which\n\n        return which(program)\n    except ImportError:\n        def is_exe(fpath):\n            return os.path.isfile(fpath) and os.access(fpath, os.X_OK)\n\n        fpath, fname = os.path.split(program)\n        if fpath:\n            if is_exe(program):\n                return program\n        else:\n            for path in os.environ[\"PATH\"].split(os.pathsep):\n                path = path.strip('\"')\n                exe_file = os.path.join(path, program)\n                if is_exe(exe_file):\n                    return exe_file\n\n        return None\n\n\ndef default_settings(params):\n    \"\"\"Adds default values to settings if it not presented.\n\n    Usage:\n\n        @default_settings({'apt': '/usr/bin/apt'})\n        def match(command):\n            print(settings.apt)\n\n    \"\"\"\n    def _default_settings(fn, command):\n        for k, w in params.items():\n            settings.setdefault(k, w)\n        return fn(command)\n    return decorator(_default_settings)\n\n\ndef get_closest(word, possibilities, cutoff=0.6, fallback_to_first=True):\n    \"\"\"Returns closest match or just first from possibilities.\"\"\"\n    possibilities = list(possibilities)\n    try:\n        return difflib_get_close_matches(word, possibilities, 1, cutoff)[0]\n    except IndexError:\n        if fallback_to_first:\n            return possibilities[0]\n\n\ndef get_close_matches(word, possibilities, n=None, cutoff=0.6):\n    \"\"\"Overrides `difflib.get_close_match` to control argument `n`.\"\"\"\n    if n is None:\n        n = settings.num_close_matches\n    return difflib_get_close_matches(word, possibilities, n, cutoff)\n\n\ndef include_path_in_search(path):\n    return not any(path.startswith(x) for x in settings.excluded_search_path_prefixes)\n\n\n@memoize\ndef get_all_executables():\n    from thefuck.shells import shell\n\n    def _safe(fn, fallback):\n        try:\n            return fn()\n        except OSError:\n            return fallback\n\n    tf_alias = get_alias()\n    tf_entry_points = ['thefuck', 'fuck']\n\n    bins = [exe.name.decode('utf8') if six.PY2 else exe.name\n            for path in os.environ.get('PATH', '').split(os.pathsep)\n            if include_path_in_search(path)\n            for exe in _safe(lambda: list(Path(path).iterdir()), [])\n            if not _safe(exe.is_dir, True)\n            and exe.name not in tf_entry_points]\n    aliases = [alias.decode('utf8') if six.PY2 else alias\n               for alias in shell.get_aliases() if alias != tf_alias]\n\n    return bins + aliases\n\n\ndef replace_argument(script, from_, to):\n    \"\"\"Replaces command line argument.\"\"\"\n    replaced_in_the_end = re.sub(u' {}$'.format(re.escape(from_)), u' {}'.format(to),\n                                 script, count=1)\n    if replaced_in_the_end != script:\n        return replaced_in_the_end\n    else:\n        return script.replace(\n            u' {} '.format(from_), u' {} '.format(to), 1)\n\n\n@decorator\ndef eager(fn, *args, **kwargs):\n    return list(fn(*args, **kwargs))\n\n\n@eager\ndef get_all_matched_commands(stderr, separator='Did you mean'):\n    if not isinstance(separator, list):\n        separator = [separator]\n    should_yield = False\n    for line in stderr.split('\\n'):\n        for sep in separator:\n            if sep in line:\n                should_yield = True\n                break\n        else:\n            if should_yield and line:\n                yield line.strip()\n\n\ndef replace_command(command, broken, matched):\n    \"\"\"Helper for *_no_command rules.\"\"\"\n    new_cmds = get_close_matches(broken, matched, cutoff=0.1)\n    return [replace_argument(command.script, broken, new_cmd.strip())\n            for new_cmd in new_cmds]\n\n\n@memoize\ndef is_app(command, *app_names, **kwargs):\n    \"\"\"Returns `True` if command is call to one of passed app names.\"\"\"\n\n    at_least = kwargs.pop('at_least', 0)\n    if kwargs:\n        raise TypeError(\"got an unexpected keyword argument '{}'\".format(kwargs.keys()))\n\n    if len(command.script_parts) > at_least:\n        return os.path.basename(command.script_parts[0]) in app_names\n\n    return False\n\n\ndef for_app(*app_names, **kwargs):\n    \"\"\"Specifies that matching script is for one of app names.\"\"\"\n    def _for_app(fn, command):\n        if is_app(command, *app_names, **kwargs):\n            return fn(command)\n        else:\n            return False\n\n    return decorator(_for_app)\n\n\nclass Cache(object):\n    \"\"\"Lazy read cache and save changes at exit.\"\"\"\n\n    def __init__(self):\n        self._db = None\n\n    def _init_db(self):\n        try:\n            self._setup_db()\n        except Exception:\n            exception(\"Unable to init cache\", sys.exc_info())\n            self._db = {}\n\n    def _setup_db(self):\n        cache_dir = self._get_cache_dir()\n        cache_path = Path(cache_dir).joinpath('thefuck').as_posix()\n\n        try:\n            self._db = shelve.open(cache_path)\n        except shelve_open_error + (ImportError,):\n            # Caused when switching between Python versions\n            warn(\"Removing possibly out-dated cache\")\n            os.remove(cache_path)\n            self._db = shelve.open(cache_path)\n\n        atexit.register(self._db.close)\n\n    def _get_cache_dir(self):\n        default_xdg_cache_dir = os.path.expanduser(\"~/.cache\")\n        cache_dir = os.getenv(\"XDG_CACHE_HOME\", default_xdg_cache_dir)\n\n        # Ensure the cache_path exists, Python 2 does not have the exist_ok\n        # parameter\n        try:\n            os.makedirs(cache_dir)\n        except OSError:\n            if not os.path.isdir(cache_dir):\n                raise\n\n        return cache_dir\n\n    def _get_mtime(self, path):\n        try:\n            return str(os.path.getmtime(path))\n        except OSError:\n            return '0'\n\n    def _get_key(self, fn, depends_on, args, kwargs):\n        parts = (fn.__module__, repr(fn).split('at')[0],\n                 depends_on, args, kwargs)\n        return str(pickle.dumps(parts))\n\n    def get_value(self, fn, depends_on, args, kwargs):\n        if self._db is None:\n            self._init_db()\n\n        depends_on = [Path(name).expanduser().absolute().as_posix()\n                      for name in depends_on]\n        key = self._get_key(fn, depends_on, args, kwargs)\n        etag = '.'.join(self._get_mtime(path) for path in depends_on)\n\n        if self._db.get(key, {}).get('etag') == etag:\n            return self._db[key]['value']\n        else:\n            value = fn(*args, **kwargs)\n            self._db[key] = {'etag': etag, 'value': value}\n            return value\n\n\n_cache = Cache()\n\n\ndef cache(*depends_on):\n    \"\"\"Caches function result in temporary file.\n\n    Cache will be expired when modification date of files from `depends_on`\n    will be changed.\n\n    Only functions should be wrapped in `cache`, not methods.\n\n    \"\"\"\n    def cache_decorator(fn):\n        @memoize\n        @wraps(fn)\n        def wrapper(*args, **kwargs):\n            if cache.disabled:\n                return fn(*args, **kwargs)\n            else:\n                return _cache.get_value(fn, depends_on, args, kwargs)\n\n        return wrapper\n\n    return cache_decorator\n\n\ncache.disabled = False\n\n\ndef get_installation_version():\n    try:\n        from importlib.metadata import version\n\n        return version('thefuck')\n    except ImportError:\n        import pkg_resources\n\n        return pkg_resources.require('thefuck')[0].version\n\n\ndef get_alias():\n    return os.environ.get('TF_ALIAS', 'fuck')\n\n\n@memoize\ndef get_valid_history_without_current(command):\n    def _not_corrected(history, tf_alias):\n        \"\"\"Returns all lines from history except that comes before `fuck`.\"\"\"\n        previous = None\n        for line in history:\n            if previous is not None and line != tf_alias:\n                yield previous\n            previous = line\n        if history:\n            yield history[-1]\n\n    from thefuck.shells import shell\n    history = shell.get_history()\n    tf_alias = get_alias()\n    executables = set(get_all_executables())\\\n        .union(shell.get_builtin_commands())\n\n    return [line for line in _not_corrected(history, tf_alias)\n            if not line.startswith(tf_alias) and not line == command.script\n            and line.split(' ')[0] in executables]\n\n\ndef format_raw_script(raw_script):\n    \"\"\"Creates single script from a list of script parts.\n\n    :type raw_script: [basestring]\n    :rtype: basestring\n\n    \"\"\"\n    if six.PY2:\n        script = ' '.join(arg.decode('utf-8') for arg in raw_script)\n    else:\n        script = ' '.join(raw_script)\n\n    return script.lstrip()\n"
  },
  {
    "path": "tox.ini",
    "content": "[tox]\nenvlist = py{27,35,36,37,38,39,310,311}\n\n[testenv]\ndeps = -rrequirements.txt\ncommands = pytest -v --capture=sys\n\n[flake8]\nignore = E501,W503,W504\nexclude = venv,build,.tox,setup.py,fastentrypoints.py\n"
  }
]