Full Code of railsware/upterm for AI

master 6db8d5b89625 cached
157 files
582.8 KB
170.0k tokens
651 symbols
1 requests
Download .txt
Showing preview only (622K chars total). Download the full file or copy to clipboard to get everything.
Repository: railsware/upterm
Branch: master
Commit: 6db8d5b89625
Files: 157
Total size: 582.8 KB

Directory structure:
gitextract_wntplryt/

├── .dockerignore
├── .gitignore
├── .node-version
├── .npmrc
├── .nvmrc
├── .travis.yml
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── build/
│   └── icon.icns
├── docs/
│   └── vscodedebugging.md
├── package.json
├── src/
│   ├── Autocompletion.ts
│   ├── Char.ts
│   ├── Decorators.ts
│   ├── EmitterWithUniqueID.ts
│   ├── Enums.ts
│   ├── Interfaces.ts
│   ├── Output.ts
│   ├── PTY.ts
│   ├── PluginManager.ts
│   ├── main/
│   │   └── Main.ts
│   ├── monaco/
│   │   ├── Loader.ts
│   │   ├── PromptTheme.ts
│   │   ├── ShellHistoryLanguage.ts
│   │   └── ShellLanguage.ts
│   ├── plugins/
│   │   ├── AliasSuggestions.ts
│   │   ├── DotEnvLoader.ts
│   │   ├── GitGrep.tsx
│   │   ├── JSON.tsx
│   │   ├── JobFinishedNotifications.ts
│   │   ├── NVM.ts
│   │   ├── PWDOperatingSystemIntegrator.ts
│   │   ├── RVM.ts
│   │   ├── SaveHistory.ts
│   │   ├── SaveWindowBounds.ts
│   │   ├── Show.tsx
│   │   ├── UpdateLastPresentWorkingDirectory.ts
│   │   ├── completion/
│   │   │   ├── Brew.ts
│   │   │   ├── Cat.ts
│   │   │   ├── Cd.ts
│   │   │   ├── Cp.ts
│   │   │   ├── Df.ts
│   │   │   ├── Executable.ts
│   │   │   ├── Find.ts
│   │   │   ├── Git.ts
│   │   │   ├── Grep.ts
│   │   │   ├── History.ts
│   │   │   ├── Ln.ts
│   │   │   ├── Locate.ts
│   │   │   ├── Ls.ts
│   │   │   ├── Mkdir.ts
│   │   │   ├── Mv.ts
│   │   │   ├── NPM.ts
│   │   │   ├── Ps.ts
│   │   │   ├── Pwd.ts
│   │   │   ├── Rails.ts
│   │   │   ├── Rake.ts
│   │   │   ├── Rm.ts
│   │   │   ├── Scp.ts
│   │   │   ├── Shutdown.ts
│   │   │   ├── Tail.ts
│   │   │   ├── Top.ts
│   │   │   └── Vagrant.ts
│   │   └── completion_utils/
│   │       ├── Button.tsx
│   │       ├── Combine.ts
│   │       ├── Common.ts
│   │       └── Descriptions.ts
│   ├── references.d.ts
│   ├── services/
│   │   ├── FontService.ts
│   │   ├── GitService.ts
│   │   ├── HistoryService.ts
│   │   ├── JobsService.ts
│   │   ├── SessionsService.ts
│   │   ├── UpdatesService.ts
│   │   ├── WindowService.ts
│   │   └── index.ts
│   ├── shell/
│   │   ├── Aliases.ts
│   │   ├── BuiltInCommands.ts
│   │   ├── CommandExecutor.ts
│   │   ├── Environment.ts
│   │   ├── Job.ts
│   │   ├── Parser.ts
│   │   ├── Prompt.ts
│   │   ├── Scanner.ts
│   │   └── Session.ts
│   ├── utils/
│   │   ├── Common.ts
│   │   ├── Git.ts
│   │   ├── HistoryTrie.ts
│   │   ├── JSONTree.tsx
│   │   ├── Link.tsx
│   │   ├── ManPageParsingUtils.ts
│   │   ├── ManPages.ts
│   │   ├── OrderedSet.ts
│   │   ├── Process.ts
│   │   └── Shell.ts
│   └── views/
│       ├── ApplicationComponent.tsx
│       ├── JobComponent.tsx
│       ├── JobHeaderComponent.tsx
│       ├── Main.tsx
│       ├── OutputComponent.tsx
│       ├── PrettifyToggleComponent.tsx
│       ├── PromptComponent.tsx
│       ├── SearchComponent.tsx
│       ├── SessionComponent.tsx
│       ├── TabComponent.tsx
│       ├── TabHeaderComponent.tsx
│       ├── ViewUtils.ts
│       ├── css/
│       │   ├── FontAwesome.ts
│       │   ├── colors.ts
│       │   ├── functions.ts
│       │   └── styles.ts
│       ├── index.html
│       ├── keyevents/
│       │   └── Keybindings.ts
│       ├── menu/
│       │   └── Menu.ts
│       └── mouseevents/
│           └── MouseEvents.ts
├── test/
│   ├── e2e.ts
│   ├── environment_spec.ts
│   ├── output_spec.ts
│   ├── pty_spec.ts
│   ├── references.d.ts
│   ├── shell/
│   │   └── scanner_spec.ts
│   ├── test_files/
│   │   ├── file_names_test/
│   │   │   └── file with brackets()
│   │   └── vttest/
│   │       ├── 1-1
│   │       ├── 1-2
│   │       ├── 1-3
│   │       ├── 1-4
│   │       ├── 1-5
│   │       ├── 1-6
│   │       ├── 2-1
│   │       ├── 2-10
│   │       ├── 2-11
│   │       ├── 2-12
│   │       ├── 2-13
│   │       ├── 2-14
│   │       ├── 2-15
│   │       ├── 2-2
│   │       ├── 2-3
│   │       ├── 2-4
│   │       ├── 2-5
│   │       ├── 2-6
│   │       ├── 2-7
│   │       ├── 2-8
│   │       └── 2-9
│   └── utils/
│       ├── ManPages_spec.ts
│       ├── common_spec.ts
│       ├── history_trie_spec.ts
│       └── ordered_set_spec.ts
├── tsconfig.json
├── tslint.json
└── typings/
    ├── Interfaces.d.ts
    ├── Overrides.d.ts
    ├── child-process-promise.d.ts
    ├── dirStat.d.ts
    ├── mode-to-permissions.d.ts
    └── uuid.d.ts

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
node_modules/
dist/
compiled/
test/


================================================
FILE: .gitignore
================================================
/node_modules/
/compiled/src/*
/tmp/*
/npm-debug.log
/dist/*

# Created by https://www.gitignore.io/api/osx

### OSX ###
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

# Directory created by Visual Studio Code
.vscode

# Directory created by IDEA
.idea


================================================
FILE: .node-version
================================================
8.11.0


================================================
FILE: .npmrc
================================================
save-exact = true
registry = https://registry.npmjs.org


================================================
FILE: .nvmrc
================================================
v8.11.0


================================================
FILE: .travis.yml
================================================
language: node_js

before_script:
  - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export DISPLAY=:99.0; sh -e /etc/init.d/xvfb start; fi

matrix:
  include:
    - os: linux
      sudo: required
      dist: trusty
#    - os: osx
#      osx_image: xcode7.3

cache:
  directories:
    - node_modules

deploy:
  skip_cleanup: true
  provider: script
  script: npm run pack
  on:
    tags: true

env:
  global:
    # GH_TOKEN
    secure: LkI4RAc08x0XsiMlK0cIKFy381qJ8v8WKepjhAGdwbNgPqDcMqLXSznTTaGTcN1hKonHBPJVL9l0G02oRjj/ulh/yeGV1Q/JRPBm2XLoG0EX6hcuDj/skaLO24fuYf/miYejZbJcRBj2F/OP7sR1SfQPl6dfzEnLj96IHCUxzEBbB6PPJdGRL35117HqD0Y/LGLPkHgdh53n/FEtsEbl6DwvkPr8+yDZxUCqTJW53ZoBJzf9znZE5gMZg6btkStWTUuM5n5doe446ipRouGtomOXkgsCtQbsd66cRzdlIlEGKUEDaEL/c4KDMIUUDw2MpxoUm2fDJ98krxRLhvANgN/rqQVBoYY45OT7SzK9TYcvqS36E6a9pdmFpt0M3w532f5E6simgJp1a6gBoSBBYoZL8hRscF2VgAvjJV0QVQzos6Ec01nGjAbpC/i2B6IR6tnI1L5C3YHR4xDvSqW3iDo3hpc+Y4INOMysMt3cK+oWx3bEsbH8G3JRbU6Edz5vUVQ5aeoyVgfr/vxhIohWq8NpGd8zqdyyfKq59DYugkDNpvKr07w+FQZLtexILKw6FzNEjm3gI9prz5a7+WzFLQcdgy6xFM7z3GN5e1kbX39BSMcmkueWk96kCYSpKOflAX5h+WOs3VjwVxoIaB5uYeQD10L+6703eSyXy3Ni3Sg=


================================================
FILE: CONTRIBUTING.md
================================================
I have found a bug!
-------------------

Awesome, but before you [report it to us](issues/new), make sure to [check whether this has already been reported](issues?q=is%3Aissue).
If not, before reporting the issue you'll need to gather some information by following these instructions:

1. Make sure you are using the latest version of the application:

  ```bash
  git pull
  rm -r "/Applications/Upterm"*
  npm run pack
  ```
2. If the bug is still present, [open an issue](issues/new).
3. Write steps to reproduce the bug.
4. Take some screenshots.
5. Gather debug logs.

 5.1. Open developer tools (View -> Toggle Developer Tools).

 5.2. Find Console.

 5.3. Copy the output and paste it into the issue.

Developing
----------

Clone the repo, then `npm start`. This will install dependencies, build,
and run Electron. You may need additional packages, such as `libgconf2`
([reference](https://github.com/railsware/upterm/issues/1320)).

I have some important changes!
------------------------------

1. [Clone the repo](https://help.github.com/articles/importing-a-git-repository-using-the-command-line/).
2. [Create a separate branch](https://github.com/Kunena/Kunena-Forum/wiki/Create-a-new-branch-with-git-and-manage-branches) (to prevent unrelated updates).
3. Apply your changes.
4. [Create a pull request](https://help.github.com/articles/creating-a-pull-request/).
5. Describe what has been done.

Test
----

* Install [selenium-standalone](https://github.com/vvo/selenium-standalone)
* `selenium-standalone start`
* `npm run test`


================================================
FILE: Dockerfile
================================================
FROM node:8.11.0

RUN mkdir /upterm
WORKDIR /upterm

COPY package.json .
COPY .npmrc .

RUN npm install
COPY . /upterm
RUN npm run pack

VOLUME /dist
CMD cp /upterm/dist/*.AppImage /dist


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2015 Volodymyr Shatsky

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.



================================================
FILE: README.md
================================================
[![Join the chat at https://gitter.im/railsware/upterm](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/upterm/Lobby)
[![Build Status](https://travis-ci.org/railsware/upterm.svg?branch=master)](https://travis-ci.org/railsware/upterm)

# Deprecated

Upterm is deprecated. Project had [lost maintainer](https://github.com/railsware/upterm/issues/1301#issue-327003344) and have zero activity to support it from community (only issues was created in repo).

I am no longer accepting pull requests and issues.

I recomended to check [Hyper](https://hyper.is/) instead.

What Is It?
-----------

**[Upterm is looking for maintainers](https://github.com/railsware/upterm/issues/1301)**

Upterm (formerly Black Screen) is an IDE in the world of terminals. Strictly speaking, it's both a
terminal emulator and an *interactive* shell based on [Electron](http://electron.atom.io/).

![](README/main.png)

###### Autocompletion

Upterm shows the autocompletion box as you type and tries to be smart about what to suggest.
Often you can find useful additional information on the right side of the autocompletion, e.g. expanded alias value,
command descriptions, value of the previous directory (`cd -`), etc.

###### Compatibility

All command-line programs (including emacs, ssh and vim) should work as expected. If you experience any glitches, please [create an issue](https://github.com/railsware/upterm/issues/new).

Install
------------

###### MacOS

```bash
brew cask install upterm
```

Beware that the version in Homebrew might be outdated. Visit the [releases](https://github.com/railsware/upterm/releases) page to download the latest version.

###### Linux *(Arch Linux)*
```bash
yaourt -S upterm
```

As with macOS's `brew` install, the AUR may also be outdated. To install the latest version, refer to the [install guide for Linux (Others)](#linux-others).

###### Linux *(Others)*

* Download and open the AppImage file from the [releases](https://github.com/railsware/upterm/releases) page.

###### Windows

Windows is not officially supported at the moment. The [Windows Support](https://github.com/railsware/upterm/issues/800) Issue explains potential experimental support.

Technologies
------------

* [Electron](http://electron.atom.io/)
* [TypeScript](http://www.typescriptlang.org/)
* [ReactJS](https://facebook.github.io/react/)


More Screenshots
----------------

![](README/npm_autocompletion.png)
![](README/error.png)
![](README/top_autocompletion.png)
![](README/json_prettyfier.png)
![](README/vim.png)
![](README/emacs.png)
![](README/htop.png)
![](README/cd.png)

Development Setup
------------

```bash
git clone https://github.com/railsware/upterm.git && cd upterm
npm start
```
Instructions are available for [debugging the application in Visual Studio Code](docs/vscodedebugging.md).

To create a standalone application, execute `npm run pack` in the project directory.

Contributing
------------

See [Contributing Guide](CONTRIBUTING.md).

License
-------

[The MIT License](LICENSE).


================================================
FILE: docs/vscodedebugging.md
================================================
# Debugging Upterm in Visual Studio Code

Microsoft's open source Visual Studio Code (vscode) provides debugging for Typescript based applications.

The recommended steps for debugging Upterm in vscode are described in the steps below.

## Step 1. Install the Debugger for Chrome Extension

To debug Electron based applications the vscode "Debugger for Chrome" extension is required.

To install this extension choose the <b>Extensions</b> icon on the left hand side. Then search for and select the <b>Debugger for Chrome</b>. The extension should take about a minute to install after which you will be prompted to reload vscode.

![chrome debugger](images/install_chrome_debug_ext.png "chrome debugger")

## Step 2. Setup vscode project build and debug configuration

Under the `.vscode` folder create the `launch.json` and `tasks.json` files.

![.vscode folder](images/dot-vscode-folder.png ".vscode folder")

The contents of these files should be as follows.

<b>a. launch.json</b>
```
{
    // Use IntelliSense to learn about possible Node.js debug attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [

        {
            "type": "node",
            "request": "launch",
            "name": "Electron Main",
            // Mac OS & Linux process runtime executable
            "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
            "windows": {
                // Windows process runtime executable
                "runtimeExecutable": "${workspaceRoot}\\node_modules\\.bin\\electron.cmd"
            },
            "program": "${workspaceRoot}/compiled/src/main/Main.js",
            "protocol": "inspector",
            "stopOnEntry": false,
            "args": [],
            "cwd": "${workspaceRoot}/",
            "runtimeArgs": [
                "--enable-logging"
            ],
            "env": {},
            "sourceMaps": true,
            "outFiles": [
                "${workspaceRoot}/compiled/src"
            ],
            "internalConsoleOptions": "openOnSessionStart",
            "console": "integratedTerminal"
        },
        {
            "name": "Debug renderer process",
            "type": "chrome",
            "request": "launch",
            // Mac OS & Linux process runtime executable
            "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
            "windows": {
                // Windows process runtime executable
                "runtimeExecutable": "${workspaceRoot}\\node_modules\\.bin\\electron.cmd"
            },
            "runtimeArgs": [
                "${workspaceRoot}/",
                "--enable-logging",
                "--remote-debugging-port=9222"
            ],
            "webRoot": "${workspaceRoot}/",
            "sourceMaps": true,
            "internalConsoleOptions": "openOnSessionStart"
        }
    ]
}
```

<b>b. tasks.json</b>
```
{
    "version": "2.0.0",
    "presentation": {
        "echo": true,
        "reveal": "always",
        "focus": false,
        "panel": "new"
    },
    "tasks": [
        {
            // Custom prestart task i.e. npm run prestart.
            "taskName": "prestart",
            "command": "npm",
            "args": [
                "run",
                "prestart"
            ],
            "type": "shell",
            "group": "build",
            // Specify tsc problem matcher.
            "problemMatcher": ["$tsc-watch"]
        },
        {
            // Default compile task from package.json i.e. npm run compile.
            "type": "npm",
            "script": "compile",
            "group": "build",
            // Specify tsc problem matcher.
            "problemMatcher": ["$tsc-watch"]
        }
    ]
}
```

## Step 3. Build the project

After first install of Upterm and after each time Upterm is modified the project needs to be re-built before launching a debug session.

To build the project in vscode open the activity search box by selecting the `⌘ + p` keys on Mac OS (or `Ctrl + p` on Linux and Windows), and then enter `task prestart`. Or alternatively from the command line run `npn run prestart`.

![prestart task launch](images/launch_task_prestart.png "prestart task launch")

If the code has been modified and no updates to dependent node modules were made you can compile the project by entering `task compile` into the search box. Or from the command line run `npn run compile`.

Note. The compile task is a npm script defined in `package.json` which vscode detects and displays as `npm: compile` in the search box.

## Step 4. Debug the project

Source maps are enabled for the Upterm project which allows the Typescript code to be debugged. Source maps map the Typescript code to the generated (transpiled) Javascript code, with the Javascript code being what's executed by node.js.

To enter debugging mode select the <b>Debug</b> icon on the left hand side menu. Or alternatively, select the `Shift + ⌘ + d` (or `Shift + Ctrl + d`) keys.

![debug process](images/debug_renderer_process.png "debug process")

To launch a debug session, from the top left hand side of the <b>Debug</b> window select `Debug rendered process` and press the Play button.
Note. A breakpoint needs to be placed in the code prior to launching a debug session, to allow stepping through code.

These instructions were tested on vscode version 1.16.0.


================================================
FILE: package.json
================================================
{
  "name": "upterm",
  "productName": "Upterm",
  "description": "A terminal emulator for the 21st century.",
  "version": "0.4.4",
  "main": "compiled/src/main/Main.js",
  "author": "Volodymyr Shatskyi <shockone89@gmail.com>",
  "repository": {
    "type": "git",
    "url": "https://github.com/railsware/upterm.git"
  },
  "bugs": {
    "url": "https://github.com/railsware/upterm/issues"
  },
  "engines": {
    "node": ">=8.0.0 || >=10.0.0"
  },
  "keywords": [
    "terminal",
    "emulator",
    "shell",
    "console"
  ],
  "dependencies": {
    "child-process-promise": "2.2.1",
    "chokidar": "2.0.3",
    "classnames": "2.2.5",
    "csv-parse": "2.2.0",
    "csv-stringify": "3.0.0",
    "dirStat": "0.0.2",
    "font-awesome": "4.7.0",
    "fs-extra": "5.0.0",
    "immutable": "3.8.2",
    "klaw": "2.1.1",
    "lodash": "4.17.11",
    "mode-to-permissions": "0.0.2",
    "monaco-editor": "vlad-shatskyi/monaco-editor",
    "node-ansiparser": "2.2.0",
    "node-pty": "0.7.4",
    "react": "16.2.0",
    "react-dom": "16.2.0",
    "rxjs": "5.5.8",
    "tinycolor2": "1.4.1"
  },
  "devDependencies": {
    "@types/chai": "4.1.3",
    "@types/chokidar": "1.7.5",
    "@types/classnames": "2.2.3",
    "@types/csv-parse": "1.1.11",
    "@types/csv-stringify": "1.4.2",
    "@types/enzyme": "3.1.10",
    "@types/fs-extra": "5.0.2",
    "@types/klaw": "2.1.1",
    "@types/lodash": "4.14.116",
    "@types/mocha": "5.2.0",
    "@types/node": "9.6.1",
    "@types/react": "16.1.0",
    "@types/webdriverio": "4.10.1",
    "chai": "4.1.2",
    "concurrently": "3.5.1",
    "cpx": "1.5.0",
    "cross-env": "5.1.4",
    "devtron": "1.4.0",
    "electron": "2.0.10",
    "electron-builder": "20.28.4",
    "electron-mocha": "6.0.4",
    "enzyme": "3.3.0",
    "mkdirp": "0.5.1",
    "mocha": "5.2.0",
    "npm-check-updates": "2.14.2",
    "react-addons-test-utils": "15.6.2",
    "rimraf": "2.6.2",
    "spectron": "3.8.0",
    "ts-node": "5.0.1",
    "tslint": "5.9.1",
    "typescript": "2.8.1"
  },
  "scripts": {
    "preinstall": "npm prune",
    "postinstall": "electron-builder install-app-deps",
    "pack": "build",
    "electron": "electron .",
    "prestart": "npm install && npm run compile",
    "start": "concurrently --kill-others -s first \"tsc --watch\" \"cross-env NODE_ENV=development npm run electron\"",
    "test": "npm run lint && npm run compile && npm run unit-tests && npm run ui-tests && npm run integration-tests",
    "unit-tests": "NODE_ENV=test electron-mocha --require ts-node/register $(find test -name '*_spec.ts')",
    "ui-tests": "NODE_ENV=test electron-mocha --require ts-node/register $(find test -name '*_spec.tsx')",
    "integration-tests": "NODE_ENV=test electron-mocha --require ts-node/register test/e2e.ts",
    "update-dependencies": "ncu -u",
    "lint": "tslint `find src -name '*.ts*'` `find test -name '*.ts*'`",
    "cleanup": "rimraf compiled/src",
    "copy-html": "mkdirp compiled/src/views && cpx src/views/index.html compiled/src/views",
    "compile": "npm run cleanup && npm run tsc && npm run copy-html",
    "tsc": "tsc"
  },
  "license": "MIT",
  "build": {
    "appId": "com.github.railsware.upterm",
    "linux": {
      "icon": "icons"
    }
  }
}


================================================
FILE: src/Autocompletion.ts
================================================
import {leafNodeAt, ASTNode} from "./shell/Parser";
import * as _ from "lodash";
import {Environment} from "./shell/Environment";
import {OrderedSet} from "./utils/OrderedSet";
import {Aliases} from "./shell/Aliases";

type GetSuggestionsOptions = {
    currentText: string;
    currentCaretPosition: number;
    ast: ASTNode;
    environment: Environment;
    historicalPresentDirectoriesStack: OrderedSet<string>;
    aliases: Aliases;
};

export async function getSuggestions({
    currentCaretPosition,
    ast,
    environment,
    historicalPresentDirectoriesStack,
    aliases,
}: GetSuggestionsOptions): Promise<monaco.languages.CompletionList> {
    const node = leafNodeAt(currentCaretPosition, ast);
    const suggestions = await node.suggestions({
        environment: environment,
        historicalPresentDirectoriesStack: historicalPresentDirectoriesStack,
        aliases: aliases,
    });

    const uniqueSuggestions = _.uniqBy(suggestions, suggestion => suggestion.label);

    return {
        isIncomplete: false,
        items: uniqueSuggestions.map(suggestion => ({
            ...suggestion,
            kind: monaco.languages.CompletionItemKind.Interface,
        })),
    };
}


================================================
FILE: src/Char.ts
================================================
import {Attributes} from "./Interfaces";
import {Brightness, Weight, Color} from "./Enums";

export const defaultAttributes = Object.freeze({
    inverse: false,
    color: Color.White,
    backgroundColor: Color.Black,
    brightness: Brightness.Normal,
    weight: Weight.Normal,
    underline: false,
    crossedOut: false,
    blinking: false,
    cursor: false,
});

export interface Char {
    value: string;
    attributes: Attributes;
}

export function createChar(char: string, attributes: Attributes): Char {
    if (char.length !== 1) {
        throw(`Char can be created only from a single character; passed ${char.length}: ${char}`);
    }

    return {
        value: char,
        attributes: attributes,
    };
}


================================================
FILE: src/Decorators.ts
================================================
import * as _ from "lodash";

export function memoize(resolver: ((...args: any[]) => any) | undefined = undefined) {
    if (typeof resolver !== "function") {
        resolver = (...args: any[]) => JSON.stringify(args);
    }

    return (_target: any, _name: string, descriptor: TypedPropertyDescriptor<any>) => {
        descriptor.value = _.memoize(descriptor.value, resolver);

        return descriptor;
    };
}

export const memoizeAccessor = <T>(_target: Object, name: string | symbol, descriptor: TypedPropertyDescriptor<T>) => {
    const memoizedPropertyName = `__memoized_${name}`;
    const originalGetter = descriptor.get;

    descriptor.get = function (this: any) {
        if (!this[memoizedPropertyName]) {
            this[memoizedPropertyName] = originalGetter!.call(this);
        }

        return this[memoizedPropertyName];
    };

    return descriptor;
};

export function debounce(wait: number = 0) {
    return (_target: any, _name: string, descriptor: PropertyDescriptor) => {
        descriptor.value = _.debounce(descriptor.value, wait);

        return descriptor;
    };
}


================================================
FILE: src/EmitterWithUniqueID.ts
================================================
import * as events from "events";

export class EmitterWithUniqueID extends events.EventEmitter {
    public id: number;

    constructor() {
        super();
        this.id = Date.now();
    }
}


================================================
FILE: src/Enums.ts
================================================
/**
 * @link https://css-tricks.com/snippets/javascript/javascript-keycodes/
 * @link https://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html
 */
export enum KeyCode {
    Bell = 7,
    Backspace = 8,
    Tab = 9,
    NewLine = 10,
    VerticalTab = 11,
    CarriageReturn = 13,
    ShiftOut = 14,
    ShiftIn = 15,
    Shift = 16,
    Ctrl = 17,
    Alt = 18,
    CapsLock = 20,
    Escape = 27,
    Space = 32,
    Left = 37,
    Up = 38,
    Right = 39,
    Down = 40,
    One = 49,
    Nine = 57,
    A = 65,
    B = 66,
    C = 67,
    D = 68,
    E = 69,
    F = 70,
    G = 71,
    H = 72,
    I = 73,
    J = 74,
    K = 75,
    L = 76,
    M = 77,
    N = 78,
    O = 79,
    P = 80,
    Q = 81,
    R = 82,
    S = 83,
    T = 84,
    U = 85,
    V = 86,
    W = 87,
    X = 88,
    Y = 89,
    Z = 90,
    Meta = 91,
    Delete = 127,
    Underscore = 189,
    Period = 190,
    VerticalBar = 220,
    AltGraph = 225,
}

export enum Color {
    Black,
    Red,
    Green,
    Yellow,
    Blue,
    Magenta,
    Cyan,
    White,
}

export enum Status {
    InProgress = "in-progress",
    Failed = "failed",
    Success = "success",
}
export enum ScreenMode {
    Light = "light",
    Dark = "dark",
}

export enum BufferType {
    Normal = "normal",
    Alternate = "alternate",
}

export enum Weight {
    Normal = "normal",
    Bold = "bold",
    Faint = "faint",
}

export enum Brightness {
    Normal = "normal",
    Bright = "bright",
}

export enum LogLevel {
    Info = "info",
    Log = "log",
    Error = "error",
}

export enum KeyboardAction {
    // CLI commands
    cliClearJobs,
    cliClearText,
    cliAppendLastArgumentOfPreviousCommand,
    cliHistoryPrevious,
    cliHistoryNext,
    // autocomplete commands
    autocompleteInsertCompletion,
    autocompletePreviousSuggestion,
    autocompleteNextSuggestion,
    // tab commands
    tabNew,
    tabFocus,
    tabPrevious,
    tabNext,
    // session commands
    otherSession,
    sessionClose,
    // edit/clipboard commands
    clipboardCopy,
    clipboardPaste,
    editFind,
    editFindClose,
    increaseFontSize,
    decreaseFontSize,
    resetFontSize,
    // view commands
    viewToggleFullScreen,
    // Upterm commands
    uptermQuit,
    // developer
    toggleDeveloperTools,
}


================================================
FILE: src/Interfaces.ts
================================================
import {Weight, Brightness} from "./Enums";
import {Stats} from "fs";
import {ReactElement} from "react";
import {Job} from "./shell/Job";
import {Session} from "./shell/Session";
import {Suggestion} from "./plugins/completion_utils/Common";
import {Output} from "./Output";
import {Environment} from "./shell/Environment";
import {OrderedSet} from "./utils/OrderedSet";
import {Argument} from "./shell/Parser";
import {Aliases} from "./shell/Aliases";

export type ColorCode = number | number[];

export interface Attributes {
    readonly inverse: boolean;
    readonly color: ColorCode;
    readonly backgroundColor: ColorCode;
    readonly brightness: Brightness;
    readonly weight: Weight;
    readonly underline: boolean;
    readonly crossedOut: boolean;
    readonly blinking: boolean;
    readonly cursor: boolean;
}

export interface PreliminaryAutocompletionContext {
    readonly environment: Environment;
    readonly historicalPresentDirectoriesStack: OrderedSet<string>;
    readonly aliases: Aliases;
}

export interface AutocompletionContext extends PreliminaryAutocompletionContext {
    readonly argument: Argument;
}

export type AutocompletionProvider = (context: AutocompletionContext) => Promise<Suggestion[]>;

export interface FileInfo {
    name: string;
    stat: Stats;
}

export interface Prettyfier {
    isApplicable: (job: Job) => boolean;
    prettify: (job: Job) => ReactElement<any>;
}

export interface EnvironmentObserverPlugin {
    presentWorkingDirectoryWillChange: (session: Session, directory: string) => void;
    presentWorkingDirectoryDidChange: (session: Session, directory: string) => void;
}

export interface TerminalLikeDevice {
    output: Output;
    write: (input: string | KeyboardEvent) => void;
}

export type UserEvent = KeyboardEvent | ClipboardEvent;

export type MouseEvent = DragEvent;


================================================
FILE: src/Output.ts
================================================
import * as events from "events";
import {defaultAttributes, createChar, Char} from "./Char";
import * as i from "./Interfaces";
import * as e from "./Enums";
import {List} from "immutable";
import {Color, Weight, Brightness, KeyCode, LogLevel, BufferType, ScreenMode} from "./Enums";
import {Attributes, TerminalLikeDevice, ColorCode} from "./Interfaces";
import {print, error, info, csi, times} from "./utils/Common";
import * as _ from "lodash";

const ansiParserConstructor: typeof AnsiParser = require("node-ansiparser");

interface HandlerResult {
    status: string;
    description: string;
    longDescription?: string;
    url: string;
}

interface SavedState {
    cursorRowIndex: number;
    cursorColumnIndex: number;
    attributes: i.Attributes;
    designatedCharacterSets: DesignatedCharacterSets;
    selectedCharacterSet: SelectedCharacterSet;
}

/**
 * @link http://vt100.net/docs/vt220-rm/chapter4.html
 */
enum CharacterSets {
    ASCIIGraphics,
    SupplementalGraphics,
}

interface DesignatedCharacterSets {
    G0: CharacterSets;
    G1: CharacterSets;
    G2: CharacterSets;
    G3: CharacterSets;
}

type SelectedCharacterSet = keyof DesignatedCharacterSets;

function or1(value: number | undefined) {
    if (value === undefined) {
        return 1;
    } else {
        return value;
    }
}


function logPosition(buffer: Buffer) {
    const position = {rowIndex: buffer.cursorRowIndex, columnIndex: buffer.cursorColumnIndex};
    const char = buffer.at(position);
    const value = char ? char.value : "NULL";
    info(`%crow: ${position.rowIndex + 1}\tcolumn: ${buffer.cursorColumnIndex + 1}\t value: ${value}, rows: ${buffer.size}`, "color: grey");
}

/**
 * Copied from xterm.js
 * @link https://github.com/sourcelair/xterm.js/blob/master/src/Charsets.ts
 */
const graphicCharset: Dictionary<string> = {
    "`": "\u25c6", // "◆"
    "a": "\u2592", // "▒"
    "b": "\u0009", // "\t"
    "c": "\u000c", // "\f"
    "d": "\u000d", // "\r"
    "e": "\u000a", // "\n"
    "f": "\u00b0", // "°"
    "g": "\u00b1", // "±"
    "h": "\u2424", // "\u2424" (NL)
    "i": "\u000b", // "\v"
    "j": "\u2518", // "┘"
    "k": "\u2510", // "┐"
    "l": "\u250c", // "┌"
    "m": "\u2514", // "└"
    "n": "\u253c", // "┼"
    "o": "\u23ba", // "⎺"
    "p": "\u23bb", // "⎻"
    "q": "\u2500", // "─"
    "r": "\u23bc", // "⎼"
    "s": "\u23bd", // "⎽"
    "t": "\u251c", // "├"
    "u": "\u2524", // "┤"
    "v": "\u2534", // "┴"
    "w": "\u252c", // "┬"
    "x": "\u2502", // "│"
    "y": "\u2264", // "≤"
    "z": "\u2265", // "≥"
    "{": "\u03c0", // "π"
    "|": "\u2260", // "≠"
    "}": "\u00a3", // "£"
    "~": "\u00b7", // "·"
};

const SGR: { [indexer: string]: (attributes: Attributes) => Attributes } = {
    0: (_attributes: Attributes) => defaultAttributes,
    1: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright}),
    2: (attributes: Attributes) => ({...attributes, weight: Weight.Faint}),
    4: (attributes: Attributes) => ({...attributes, underline: true}),
    7: (attributes: Attributes) => ({...attributes, inverse: true}),
    22: (attributes: Attributes) => ({...attributes, weight: Weight.Normal}),
    24: (attributes: Attributes) => ({...attributes, underline: false}),
    27: (attributes: Attributes) => ({...attributes, inverse: false}),
    30: (attributes: Attributes) => ({...attributes, color: <ColorCode>Color.Black}),
    31: (attributes: Attributes) => ({...attributes, color: <ColorCode>Color.Red}),
    32: (attributes: Attributes) => ({...attributes, color: <ColorCode>Color.Green}),
    33: (attributes: Attributes) => ({...attributes, color: <ColorCode>Color.Yellow}),
    34: (attributes: Attributes) => ({...attributes, color: <ColorCode>Color.Blue}),
    35: (attributes: Attributes) => ({...attributes, color: <ColorCode>Color.Magenta}),
    36: (attributes: Attributes) => ({...attributes, color: <ColorCode>Color.Cyan}),
    37: (attributes: Attributes) => ({...attributes, color: <ColorCode>Color.White}),
    39: (attributes: Attributes) => ({...attributes, color: <ColorCode>Color.White}),
    40: (attributes: Attributes) => ({...attributes, backgroundColor: <ColorCode>Color.Black}),
    41: (attributes: Attributes) => ({...attributes, backgroundColor: <ColorCode>Color.Red}),
    42: (attributes: Attributes) => ({...attributes, backgroundColor: <ColorCode>Color.Green}),
    43: (attributes: Attributes) => ({...attributes, backgroundColor: <ColorCode>Color.Yellow}),
    44: (attributes: Attributes) => ({...attributes, backgroundColor: <ColorCode>Color.Blue}),
    45: (attributes: Attributes) => ({...attributes, backgroundColor: <ColorCode>Color.Magenta}),
    46: (attributes: Attributes) => ({...attributes, backgroundColor: <ColorCode>Color.Cyan}),
    47: (attributes: Attributes) => ({...attributes, backgroundColor: <ColorCode>Color.White}),
    49: (attributes: Attributes) => ({...attributes, backgroundColor: <ColorCode>Color.Black}),
    90: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, color: <ColorCode>Color.Black}),
    91: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, color: <ColorCode>Color.Red}),
    92: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, color: <ColorCode>Color.Green}),
    93: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, color: <ColorCode>Color.Yellow}),
    94: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, color: <ColorCode>Color.Blue}),
    95: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, color: <ColorCode>Color.Magenta}),
    96: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, color: <ColorCode>Color.Cyan}),
    97: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, color: <ColorCode>Color.White}),
    100: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, backgroundColor: <ColorCode>Color.Black}),
    101: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, backgroundColor: <ColorCode>Color.Red}),
    102: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, backgroundColor: <ColorCode>Color.Green}),
    103: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, backgroundColor: <ColorCode>Color.Yellow}),
    104: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, backgroundColor: <ColorCode>Color.Blue}),
    105: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, backgroundColor: <ColorCode>Color.Magenta}),
    106: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, backgroundColor: <ColorCode>Color.Cyan}),
    107: (attributes: Attributes) => ({...attributes, brightness: Brightness.Bright, backgroundColor: <ColorCode>Color.White}),
};

const CSI = {
    erase: {
        toEnd: 0,
        toBeginning: 1,
        entire: 2,
        entireSsh: 3,
    },
};

const colorFormatCodes = {
    format8bit: 5,
    formatTrueColor: 2,
};

export class Output extends events.EventEmitter {
    public activeBufferType = e.BufferType.Normal;
    public isCursorKeysModeSet = false;
    public screenMode = ScreenMode.Dark;
    private normalBuffer: Buffer;
    private alternateBuffer: Buffer;
    private parser: AnsiParser;

    constructor(private terminalDevice: TerminalLikeDevice, public dimensions: Dimensions) {
        super();

        this.normalBuffer = new Buffer(this, 200);
        this.alternateBuffer = new Buffer(this, 0);

        this.parser = new ansiParserConstructor({
            inst_p: (text: string) => {
                info("text", text, text.split("").map(letter => letter.charCodeAt(0)));

                for (let i = 0; i !== text.length; ++i) {
                    this.activeBuffer.writeOne(text.charAt(i));
                }

                logPosition(this.activeBuffer);
            },
            inst_o: function (s: any) {
                error("osc", s);
            },
            inst_x: (flag: string) => {
                this.activeBuffer.writeOne(flag);

                print((KeyCode[flag.charCodeAt(0)] ? LogLevel.Log : LogLevel.Error), ["char", flag.split("").map((_, index) => flag.charCodeAt(index))]);
                logPosition(this.activeBuffer);
            },
            /**
             * CSI handler.
             */
            inst_c: (collected: any, params: Array<number>, flag: string) => {
                let handlerResult: HandlerResult;
                if (collected === "?") {
                    if (params.length !== 1) {
                        return error(`CSI private mode has ${params.length} parameters: ${params}`);
                    }
                    if (flag !== "h" && flag !== "l") {
                        return error(`CSI private mode has an incorrect flag: ${flag}`);
                    }
                    const mode = params[0];
                    handlerResult = this.decPrivateModeHandler(mode, flag);

                    if (handlerResult.status === "handled") {
                        info(`%cCSI ? ${mode} ${flag}`, "color: blue", handlerResult.description, handlerResult.url);
                    } else {
                        error(`%cCSI ? ${mode} ${flag}`, "color: blue", handlerResult.description, handlerResult.url);
                    }
                } else {
                    handlerResult = this.csiHandler(collected, params, flag);

                    if (handlerResult.status === "handled") {
                        info(`%cCSI ${params} ${flag}`, "color: blue", handlerResult.description, handlerResult.url);
                    } else {
                        error(`%cCSI ${params} ${flag}`, "color: blue", handlerResult.description, handlerResult.url);
                    }
                }

                logPosition(this.activeBuffer);
            },
            /**
             * ESC handler.
             */
            inst_e: (collected: any, flag: string) => {
                const handlerResult = this.escapeHandler(collected, flag);

                if (handlerResult.status === "handled") {
                    info(`%cESC ${collected} ${flag}`, "color: blue", handlerResult.description, handlerResult.url);
                } else {
                    error(`%cESC ${collected} ${flag}`, "color: blue", handlerResult.description, handlerResult.url);
                }

                logPosition(this.activeBuffer);
            },
        });
    }

    write(ansiString: string) {
        this.parser.parse(ansiString);
        this.emit("data");
    }

    toLines() {
        return this.activeBuffer.toLines();
    }

    toString(): string {
        return this.toLines().join("\n");
    }

    isEmpty(): boolean {
        return this.activeBuffer.size === 0;
    }

    get activeBuffer() {
        if (this.activeBufferType === e.BufferType.Normal) {
            return this.normalBuffer;
        } else {
            return this.alternateBuffer;
        }
    }

    private escapeHandler(collected: any, flag: string) {
        let short = "";
        let long = "";
        let url = "";
        let status = "handled";

        if (collected) {
            if (collected === "#" && flag === "8") {
                short = "DEC Screen Alignment Test (DECALN).";
                url = "http://www.vt100.net/docs/vt510-rm/DECALN";

                const dimensions = this.activeBuffer.dimensions;

                for (let i = 0; i !== dimensions.rows; ++i) {
                    this.activeBuffer.moveCursorAbsolute({rowIndex: i, columnIndex: 0});
                    this.write(Array(dimensions.columns).join("E"));
                }

                this.activeBuffer.moveCursorAbsolute({rowIndex: 0, columnIndex: 0});
            } else if (collected === "(" && flag === "0") {
                short = "Designate Graphic Charset to G0";
                this.activeBuffer.designatedCharacterSets.G0 = CharacterSets.SupplementalGraphics;
            } else if (collected === "(" && flag === "B") {
                short = "Designate ASCII Charset to G0";
                this.activeBuffer.designatedCharacterSets.G0 = CharacterSets.ASCIIGraphics;
            } else if (collected === ")" && flag === "0") {
                short = "Designate Graphic Charset to G1";
                this.activeBuffer.designatedCharacterSets.G1 = CharacterSets.SupplementalGraphics;
            } else if (collected === ")" && flag === "B") {
                short = "Designate ASCII Charset to G1";
                this.activeBuffer.designatedCharacterSets.G1 = CharacterSets.ASCIIGraphics;
            } else {
                status = "unhandled";
            }
        } else {
            switch (flag) {
                case "A":
                    short = "Cursor up.";

                    this.activeBuffer.moveCursorRelative({vertical: -1});
                    break;
                case "B":
                    short = "Cursor down.";

                    this.activeBuffer.moveCursorRelative({vertical: 1});
                    break;
                case "C":
                    short = "Cursor right.";

                    this.activeBuffer.moveCursorRelative({horizontal: 1});
                    break;
                case "D":
                    short = "Index (IND).";
                    url = "http://www.vt100.net/docs/vt510-rm/IND";

                    this.activeBuffer.moveCursorRelative({vertical: 1});
                    break;
                case "H":
                    short = "Horizontal Tab Set (HTS).";
                    url = "http://www.vt100.net/docs/vt510-rm/HTS";

                    this.activeBuffer.setTabStop();
                    break;
                case "M":
                    short = "Reverse Index (RI).";
                    /* tslint:disable:max-line-length */
                    long = "Move the active position to the same horizontal position on the preceding line if the active position is at the top margin, a scroll down is performed.";

                    if (this.activeBuffer.cursorRowIndex === this.activeBuffer.marginTop) {
                        this.activeBuffer.scrollDown(1);
                    } else {
                        this.activeBuffer.moveCursorRelative({vertical: -1});
                    }
                    break;
                case "E":
                    short = "Next Line (NEL).";
                    /* tslint:disable:max-line-length */
                    long = "This sequence causes the active position to move to the first position on the next line downward. If the active position is at the bottom margin, a scroll up is performed.";

                    this.activeBuffer.moveCursorRelative({vertical: 1});
                    this.activeBuffer.moveCursorAbsolute({columnIndex: 0});
                    break;
                case "7":
                    long = "Save current state (cursor coordinates, attributes, character sets pointed at by G0, G1).";
                    this.activeBuffer.saveCurrentState();
                    break;
                case "8":
                    long = "Restore state most recently saved by ESC 7.";
                    this.activeBuffer.restoreCurrentState();
                    break;
                default:
                    status = "unhandled";
            }
        }

        return {
            status: status,
            description: short,
            longDescription: long,
            url: url,
        };
    }

    private decPrivateModeHandler(ps: number, flag: "h" | "l"): HandlerResult {
        let description = "";
        let url = "";
        let status: "handled" | "unhandled" = "handled";
        let shouldSet = flag === "h";

        // noinspection FallThroughInSwitchStatementJS
        switch (ps) {
            case 1:
                description = "Cursor Keys Mode.";
                url = "http://www.vt100.net/docs/vt510-rm/DECCKM";

                this.isCursorKeysModeSet = shouldSet;
                break;
            case 3:
                url = "http://www.vt100.net/docs/vt510-rm/DECCOLM";

                if (shouldSet) {
                    description = "132 Column Mode (DECCOLM).";

                    this.dimensions = {columns: 132, rows: this.activeBuffer.dimensions.rows};
                } else {
                    description = "80 Column Mode (DECCOLM).";

                    this.dimensions = {columns: 80, rows: this.activeBuffer.dimensions.rows};
                }
                this.activeBuffer.clear();
                // TODO
                // If you change the DECCOLM setting, the terminal:
                //      Sets the left, right, top and bottom scrolling margins to their default positions.
                //      Erases all data in page memory.
                // DECCOLM resets vertical split screen mode (DECLRMM) to unavailabl
                // DECCOLM clears data from the status line if the status line is set to host-writabl
                break;
            case 5:
                description = "Reverse Video (DECSCNM).";
                url = "http://www.vt100.net/docs/vt510-rm/DECSCNM";

                this.screenMode = (shouldSet ? ScreenMode.Light : ScreenMode.Dark);
                break;
            case 6:
                description = "Origin Mode (DECOM).";
                url = "http://www.vt100.net/docs/vt510-rm/DECOM";

                this.activeBuffer.isOriginModeSet = shouldSet;
                break;
            case 7:
                description = "Wraparound Mode (DECAWM).";
                url = "http://www.vt100.net/docs/vt510-rm/DECAWM";

                this.activeBuffer.isAutowrapModeSet = shouldSet;
                break;
            case 12:
                if (shouldSet) {
                    description = "Start Blinking Cursor (att610).";

                    this.activeBuffer.blinkCursor(true);
                } else {
                    description = "Stop Blinking Cursor (att610).";

                    this.activeBuffer.blinkCursor(false);
                }

                break;
            case 25:
                url = "http://www.vt100.net/docs/vt510-rm/DECTCEM";

                if (shouldSet) {
                    description = "Show Cursor (DECTCEM).";

                    this.activeBuffer.showCursor(true);
                } else {
                    description = "Hide Cursor (DECTCEM).";

                    this.activeBuffer.showCursor(false);
                }
                break;
            case 1049:
                if (shouldSet) {
                    /* tslint:disable:max-line-length */
                    description = "Save cursor as in DECSC and use Alternate Screen Buffer, clearing it first.  (This may be disabled by the titeInhibit resource).  This combines the effects of the 1047  and 1048  modes.  Use this with terminfo-based applications rather than the 47  mod";

                    this.activeBufferType = BufferType.Alternate;
                } else {
                    // TODO: Add Implementation
                    status = "unhandled";
                }
                break;
            case 2004:
                if (shouldSet) {
                    description = "Set bracketed paste mod";
                } else {
                    // TODO: Add Implementation
                    status = "unhandled";
                }
                break;
            default:
                status = "unhandled";
        }

        return {
            status: status,
            description: description,
            url: url,
        };
    }

    private csiHandler(_collected: any, rawParams: number[] | number, flag: string): HandlerResult {
        let short = "";
        let long = "";
        let url = "";
        let status = "handled";

        let params: number[] = Array.isArray(rawParams) ? rawParams : [];
        const param: number = params[0] || 0;

        switch (flag) {
            case "A":
                short = "Cursor Up Ps Times (default = 1) (CUU).";

                this.activeBuffer.moveCursorRelative({vertical: -(param || 1)});
                break;
            case "B":
                short = "Cursor Down Ps Times (default = 1) (CUD).";
                this.activeBuffer.moveCursorRelative({vertical: (param || 1)});
                break;
            case "C":
                short = "Cursor Forward Ps Times (default = 1) (CUF).";

                this.activeBuffer.moveCursorRelative({horizontal: (param || 1)});
                break;
            case "D":
                short = "Cursor Backward Ps Times (default = 1) (CUB).";

                this.activeBuffer.moveCursorRelative({horizontal: -(param || 1)});
                break;
            // CSI Ps E  Cursor Next Line Ps Times (default = 1) (CNL).
            // CSI Ps F  Cursor Preceding Line Ps Times (default = 1) (CPL).
            case "G":
                short = "Cursor Character Absolute [column] (default = [row,1]) (CHA)";
                url = "http://www.vt100.net/docs/vt510-rm/CHA";

                this.activeBuffer.moveCursorAbsolute({columnIndex: or1(param || 1) - 1});
                break;
            case "H":
                short = "Cursor Position [row;column] (default = [1,1]) (CUP).";
                url = "http://www.vt100.net/docs/vt510-rm/CUP";

                this.activeBuffer.moveCursorAbsolute({rowIndex: or1(params[0]) - 1, columnIndex: or1(params[1]) - 1});
                break;
            case "J":
                url = "http://www.vt100.net/docs/vt510-rm/ED";
                switch (param) {
                    case CSI.erase.entire:
                    case CSI.erase.entireSsh:
                        short = "Erase Entire Display (ED).";

                        this.activeBuffer.clear();
                        break;
                    case CSI.erase.toEnd:
                        short = "Erase Display Below (ED).";

                        this.activeBuffer.clearToEnd();
                        break;
                    case CSI.erase.toBeginning:
                        short = "Erase Display Above (ED).";

                        this.activeBuffer.clearToBeginning();
                        break;
                    default:
                        throw `Unknown CSI erase: "${param}".`;
                }
                break;
            case "K":
                url = "http://www.vt100.net/docs/vt510-rm/DECSEL";
                switch (param) {
                    case CSI.erase.entire:
                        short = "Erase the Line (DECSEL).";

                        this.activeBuffer.clearRow();
                        break;
                    case CSI.erase.toEnd:
                        short = "Erase Line to Right (DECSEL).";
                        this.activeBuffer.clearRowToEnd();
                        break;
                    case CSI.erase.toBeginning:
                        short = "Erase Line to Left (DECSEL).";
                        this.activeBuffer.clearRowToBeginning();
                        break;
                    default:
                        throw `Unknown CSI erase: "${param}".`;
                }
                break;
            case "L":
                url = "http://www.vt100.net/docs/vt510-rm/IL";
                short = "Inserts one or more blank lines, starting at the cursor. (DL)";

                this.activeBuffer.scrollDown(param || 1);
                break;
            case "M":
                url = "http://www.vt100.net/docs/vt510-rm/DL";
                short = "Deletes one or more lines in the scrolling region, starting with the line that has the cursor. (DL)";

                this.activeBuffer.scrollUp(param || 1, this.activeBuffer.cursorRowIndex);
                break;
            case "P":
                url = "http://www.vt100.net/docs/vt510-rm/DCH.html";
                short = "Deletes one or more characters from the cursor position to the right.";

                this.activeBuffer.deleteRight(param);
                break;
            case "X":
                short = "Erase P s Character(s) (default = 1) (ECH)";
                url = "http://www.vt100.net/docs/vt510-rm/ECH";

                this.activeBuffer.eraseRight(param || 1);
                break;
            case "c":
                short = "Send Device Attributes (Primary DA)";
                this.terminalDevice.write("\x1b>1;2;");
                break;
            case "d":
                short = "Line Position Absolute [row] (default = [1,column]) (VPA).";
                url = "http://www.vt100.net/docs/vt510-rm/VPA";

                this.activeBuffer.moveCursorAbsolute({rowIndex: or1(param || 1) - 1});
                break;
            case "f":
                short = "Horizontal and Vertical Position [row;column] (default = [1,1]) (HVP).";
                url = "http://www.vt100.net/docs/vt510-rm/HVP";

                this.activeBuffer.moveCursorAbsolute({rowIndex: or1(params[0]) - 1, columnIndex: or1(params[1]) - 1});
                break;
            case "g":
                url = "http://www.vt100.net/docs/vt510-rm/TBC";

                switch (param) {
                    case 0:
                        short = "Clear Tab Stop At Current Column (TBC).";

                        this.activeBuffer.clearTabStop();
                        break;
                    case 3:
                        short = "Clear All Tab Stops (TBC).";

                        this.activeBuffer.clearAllTabStops();
                        break;
                    default:
                        error(`Unknown tab clear parameter "${param}", ignoring.`);
                }
                break;
            case "m":
                short = `SGR: ${params}`;

                if (params.length === 0) {
                    short = "Reset SGR";
                    this.activeBuffer.resetAttributes();
                    break;
                }

                while (params.length !== 0) {
                    const sgr = params.shift()!;

                    if (sgr === 38 || sgr === 48) {
                        const colorFormat = params.shift();

                        if (colorFormat === colorFormatCodes.format8bit) {
                            const color = params.shift();

                            if (color) {
                                this.setColor(sgr, color);
                            } else {
                                error("sgr", sgr, colorFormat, params);
                            }
                        } else if (colorFormat === colorFormatCodes.formatTrueColor) {
                            this.setColor(sgr, params);
                            params = [];
                        } else {
                            error("sgr", sgr, colorFormat, params);
                        }
                    } else {
                        const attributesUpdater = SGR[sgr];

                        if (attributesUpdater) {
                            this.activeBuffer.setAttributes(attributesUpdater(this.activeBuffer.attributes));
                        } else {
                            error("sgr", sgr, params);
                        }
                    }
                }

                break;
            case "n":
                if (param === 6) {
                    url = "http://www.vt100.net/docs/vt510-rm/CPR";
                    short = "Report Cursor Position (CPR) [row;column] as CSI r ; c R";
                    this.terminalDevice.write(csi(`${this.activeBuffer.cursorRowIndex + 1};${this.activeBuffer.cursorColumnIndex + 1}R`));
                } else {
                    status = "unhandled";
                }

                break;
            case "r":
                url = "http://www.vt100.net/docs/vt510-rm/DECSTBM";
                short = "Set Scrolling Region [top;bottom] (default = full size of window) (DECSTBM).";

                const top = <number>(params[0] ? params[0] - 1 : undefined);
                const bottom = <number>(params[1] ? params[1] - 1 : undefined);

                this.activeBuffer.margins = {top: top, bottom: bottom};
                this.activeBuffer.moveCursorAbsolute({rowIndex: 0, columnIndex: 0});
                break;
            case "@":
                url = "http://www.vt100.net/docs/vt510-rm/ICH.html";
                short = "Inserts one or more space (SP) characters starting at the cursor position.";

                this.activeBuffer.insertSpaceRight(param);
                break;
            default:
                status = "unhandled";
        }

        return {
            status: status,
            description: short,
            longDescription: long,
            url: url,
        };
    }

    private setColor(sgr: number, color: ColorCode): void {
        if (sgr === 38) {
            this.activeBuffer.setAttributes({...this.activeBuffer.attributes, color: color});
        } else {
            this.activeBuffer.setAttributes({...this.activeBuffer.attributes, backgroundColor: color});
        }
    }
}


class Buffer {
    public cursorRowIndex = 0;
    public cursorColumnIndex = 0;
    public _showCursor = true;
    public _blinkCursor = true;
    public designatedCharacterSets: DesignatedCharacterSets = {
        G0: CharacterSets.ASCIIGraphics,
        G1: CharacterSets.ASCIIGraphics,
        G2: CharacterSets.ASCIIGraphics,
        G3: CharacterSets.ASCIIGraphics,
    };
    public selectedCharacterSet: SelectedCharacterSet = "G0";
    public isOriginModeSet = false;
    public isAutowrapModeSet = true;
    private scrollback = List<List<Char>>();
    private page = List<List<Char>>();
    private _attributes: i.Attributes = {...defaultAttributes, color: e.Color.White, weight: e.Weight.Normal};
    private _margins: Margins = {top: 0, left: 0};
    private savedState: SavedState | undefined;
    private tabStopIndices = _.range(8, 300, 8);

    constructor(private output: Output, private maxScrollbackSize: number) {
        this.ensureCursorRowExists();
    }

    map<T>(callback: (row: List<Char>, index: number) => T): T[] {
        const result: T[] = [];
        let index = 0;

        this.scrollback.forEach(row => {
            result.push(callback(row!, index));
            ++index;
        });
        this.page.forEach(row => {
            result.push(callback(row!, index));
            ++index;
        });

        return result;
    }

    writeOne(char: string): void {
        const charCode = char.charCodeAt(0);

        /**
         * Is a special symbol.
         * TODO: take into account C1 and DELETE.
         * @link http://www.asciitable.com/index/asciifull.gif
         */
        if (charCode < 32) {
            switch (charCode) {
                case e.KeyCode.Bell:
                    break;
                case e.KeyCode.Backspace:
                    this.moveCursorRelative({horizontal: -1});
                    break;
                case e.KeyCode.Tab:
                    this.moveCursorAbsolute({columnIndex: this.nextTabStopIndex});
                    break;
                case e.KeyCode.NewLine:
                case e.KeyCode.VerticalTab:
                    if (this.cursorRowIndex === this._margins.bottom) {
                        this.scrollUp(1);
                    } else {
                        this.moveCursorRelative({vertical: 1});
                    }

                    break;
                case e.KeyCode.CarriageReturn:
                    this.moveCursorAbsolute({columnIndex: 0});
                    break;
                case e.KeyCode.ShiftIn:
                    this.selectedCharacterSet = "G0";
                    break;
                case e.KeyCode.ShiftOut:
                    this.selectedCharacterSet = "G1";
                    break;
                default:
                    error(`Couldn't write a special char with code ${charCode}.`);
            }
        } else {

            const charFromCharset = this.charFromCharset(char);
            const charObject = createChar(charFromCharset, this.attributes);

            if (this.cursorColumnIndex === this.dimensions.columns) {
                if (this.isAutowrapModeSet) {
                    this.moveCursorAbsolute({columnIndex: 0});
                    this.moveCursorRelative({vertical: 1});
                } else {
                    this.moveCursorRelative({horizontal: -1});
                }
            }

            this.set(charObject);
            this.moveCursorRelative({horizontal: 1});
        }
    }

    scrollDown(count: number) {
        times(count, () => this.page = this.page.delete(this.marginBottom));
        times(count, () => this.page = this.page.insert(this.cursorRowIndex, this.emptyLine));
    }

    scrollUp(count: number, deletedLine = this._margins.top) {
        times(count, () => this.page = this.page.splice((this._margins.bottom || 0) + 1, 0, this.emptyLine).toList());
        this.page = this.page.splice(deletedLine, count).toList();
    }

    get attributes(): i.Attributes {
        return this._attributes;
    }

    resetAttributes(): void {
        this._attributes = defaultAttributes;
    }

    setAttributes(attributes: i.Attributes): void {
        this._attributes = {...this._attributes, ...attributes};
    }

    toLines(): string[] {
        return this.map(row => row.map(char => char!.value).join(""));
    }

    showCursor(state: boolean): void {
        this._showCursor = state;
    }

    blinkCursor(state: boolean): void {
        this._blinkCursor = state;
    }

    moveCursorRelative(advancement: Advancement): this {
        const unboundRowIndex = this.cursorRowIndex + (advancement.vertical || 0);
        const boundRowIndex = this._margins.bottom ? Math.min(this.marginBottom, unboundRowIndex) : unboundRowIndex;

        // Cursor might be hanging after the last column.
        const boundColumnIndex = Math.min(this.lastColumnIndex, this.cursorColumnIndex);


        this.cursorRowIndex = Math.max(0, boundRowIndex);
        this.cursorColumnIndex = Math.min(this.dimensions.columns, Math.max(0, boundColumnIndex + (advancement.horizontal || 0)));

        this.ensureCursorRowExists();
        return this;
    }

    moveCursorAbsolute(position: Partial<RowColumn>): this {
        if (typeof position.columnIndex === "number") {
            this.cursorColumnIndex = Math.max(position.columnIndex, 0) + this.homePosition.columnIndex;
        }

        if (typeof position.rowIndex === "number") {

            this.cursorRowIndex = Math.max(position.rowIndex, 0) + this.homePosition.rowIndex;
        }

        this.ensureCursorRowExists();
        return this;
    }

    deleteRight(n: number) {
        this.page = this.page.update(
            this.cursorRowIndex,
            row => row.splice(this.cursorColumnIndex, n).concat(this.spaces(n)).toList(),
        );
    }

    insertSpaceRight(n: number) {
        this.page = this.page.update(
            this.cursorRowIndex,
            row => row.splice(this.cursorColumnIndex, 0, this.spaces(n)).toList(),
        );
    }

    eraseRight(n: number) {
        this.page = this.page.update(
            this.cursorRowIndex,
            row => row.take(this.cursorColumnIndex)
                .concat(this.spaces(n), row.skip(this.cursorColumnIndex + n))
                .toList(),
        );
    }

    clearRow() {
        this.page = this.page.set(this.cursorRowIndex, this.emptyLine);
    }

    clearRowToEnd() {
        const oldRow = this.page.get(this.cursorRowIndex);
        const charsToDeleteCount = this.dimensions.columns - this.cursorColumnIndex;
        const newHead = oldRow.splice(this.cursorColumnIndex, charsToDeleteCount);
        const newTail = this.spaces(charsToDeleteCount);
        const newRow = newHead.concat(newTail).toList();

        this.page = this.page.set(this.cursorRowIndex, newRow);
    }

    clearRowToBeginning() {
        const count = this.cursorColumnIndex + 1;
        this.page = this.page.update(
            this.cursorRowIndex,
            row => this.spaces(count).concat(row.skip(count)).toList());
    }

    clear() {
        this.page = List<List<Char>>();
        this.moveCursorAbsolute({rowIndex: 0, columnIndex: 0});
    }

    clearToBeginning() {
        this.clearRowToBeginning();
        const replacement = Array(this.cursorRowIndex).fill(this.emptyLine);

        this.page = this.page.splice(0, this.cursorRowIndex, ...replacement).toList();
    }

    clearToEnd() {
        this.clearRowToEnd();
        this.page = this.page.splice(this.cursorRowIndex + 1, this.size - this.cursorRowIndex).toList();
    }

    get scrollbackSize(): number {
        return this.scrollback.size;
    }

    get size(): number {
        return this.page.size;
    }

    set margins(margins: Partial<Margins>) {
        this._margins = {...this._margins, ...margins};
    }

    get marginTop(): number {
        return this._margins.top;
    }

    get marginBottom(): number {
        if (this._margins.bottom) {
            return this._margins.bottom;
        } else {
            return this.dimensions.rows - 1;
        }
    }

    at(position: RowColumn): Char {
        return this.page.getIn([position.rowIndex, position.columnIndex]);
    }

    saveCurrentState() {
        this.savedState = {
            cursorRowIndex: this.cursorRowIndex,
            cursorColumnIndex: this.cursorColumnIndex,
            attributes: {...this.attributes},
            designatedCharacterSets: {...this.designatedCharacterSets},
            selectedCharacterSet: this.selectedCharacterSet,
        };
    }

    restoreCurrentState() {
        if (this.savedState) {
            this.moveCursorAbsolute({rowIndex: this.savedState.cursorRowIndex, columnIndex: this.savedState.cursorColumnIndex});
            this.setAttributes(this.savedState.attributes);
            this.selectedCharacterSet = this.savedState.selectedCharacterSet;
            this.designatedCharacterSets = this.savedState.designatedCharacterSets;
        } else {
            console.error("No state to restore.");
        }
    }

    setTabStop() {
        this.tabStopIndices = _.sortBy(_.union(this.tabStopIndices, [this.cursorColumnIndex]));
    }

    clearTabStop() {
        this.tabStopIndices = _.without(this.tabStopIndices, this.cursorColumnIndex);
    }

    clearAllTabStops() {
        this.tabStopIndices = [];
    }

    get nextTabStopIndex() {
        const unboundTabStopIndex = this.tabStopIndices.find(index => index > this.cursorColumnIndex) || this.cursorColumnIndex;
        return Math.min(unboundTabStopIndex, this.lastColumnIndex);
    }

    private get homePosition(): RowColumn {
        if (this.isOriginModeSet) {
            return {rowIndex: this._margins.top || 0, columnIndex: this._margins.left || 0};
        } else {
            return {rowIndex: 0, columnIndex: 0};
        }
    }

    private set(char: Char): void {
        this.ensureCursorRowExists();
        this.page = this.page.setIn([this.cursorRowIndex, this.cursorColumnIndex], char);
    }

    private ensureCursorRowExists(): void {
        for (let index = this.cursorRowIndex; index >= 0; --index) {
            if (!this.page.get(index)) {
                this.page = this.page.set(index, this.spaces(this.dimensions.columns, defaultAttributes));
            } else {
                break;
            }
        }

        if (this.size > this.dimensions.rows) {
            const newStorage = this.page.takeLast(this.dimensions.rows).toList();
            const rowsToMoveToScrollback = this.page.skipLast(this.dimensions.rows).toList();
            this.scrollback = this.scrollback.concat(rowsToMoveToScrollback).takeLast(this.maxScrollbackSize).toList();

            this.page = newStorage;
            this.cursorRowIndex = this.size - 1;
        }
    }

    private charFromCharset(char: string) {
        if (this.designatedCharacterSets[this.selectedCharacterSet] === CharacterSets.ASCIIGraphics) {
            return char;
        } else {
            return graphicCharset[char] || char;
        }
    }

    private get lastColumnIndex() {
        return this.dimensions.columns - 1;
    }

    private get emptyLine() {
        return this.spaces(this.dimensions.columns);
    }

    private spaces(n: number, attributes = this.attributes) {
        return List.of(...Array(n).fill(createChar(" ", attributes)));
    }

    get dimensions() {
        return this.output.dimensions;
    }
}


================================================
FILE: src/PTY.ts
================================================
import * as ChildProcess from "child_process";
import * as OS from "os";
import * as _ from "lodash";
import * as pty from "node-pty";
import {loginShell} from "./utils/Shell";
import {homeDirectory, info} from "./utils/Common";

interface ITerminal {
    write(data: string): void;
    resize(cols: number, rows: number): void;
    kill(signal?: string): void;
    on(type: string, listener: (...args: any[]) => any): void;
}

export class PTY {
    private terminal: ITerminal;

    // TODO: write proper signatures.
    // TODO: use generators.
    // TODO: terminate. https://github.com/atom/atom/blob/v1.0.15/src/task.coffee#L151
    constructor(words: EscapedShellWord[], env: ProcessEnvironment, dimensions: Dimensions, dataHandler: (d: string) => void, exitHandler: (c: number) => void) {
        const shellArguments = [...loginShell.noConfigSwitches, ...loginShell.interactiveCommandSwitches, words.join(" ")];

        info(`PTY: ${loginShell.executableName} ${JSON.stringify(shellArguments)}`);
        info(`Dimensions: ${JSON.stringify(dimensions)}}`);

        this.terminal = <any> pty.fork(loginShell.executableName, shellArguments, {
            cols: dimensions.columns,
            rows: dimensions.rows,
            cwd: env.PWD,
            env: env,
        });

        this.terminal.on("data", (data: string) => dataHandler(data));
        this.terminal.on("exit", (code: number) => exitHandler(code));
    }

    write(data: string): void {
        this.terminal.write(data);
    }

    resize(dimensions: Dimensions) {
        this.terminal.resize(dimensions.columns, dimensions.rows);
    }

    kill(signal: string): void {
        /**
         *  The if branch is necessary because pty.js doesn't handle SIGINT correctly.
         *  You can test whether it works by executing
         *     ruby -e "loop { puts 'yes'; sleep 1 }"
         *  and trying to kill it with SIGINT.
         *
         *  {@link https://github.com/chjj/pty.js/issues/58}
         */
        if (signal === "SIGINT") {
            this.terminal.kill("SIGTERM");
        } else {
            this.terminal.kill(signal);
        }
    }
}

export function executeCommand(
    command: string,
    args: string[] = [],
    directory: string,
    execOptions?: any,
): Promise<string> {
    return new Promise((resolve, reject) => {
        const options = {
            ...execOptions,
            env: _.extend({PWD: directory, SHLVL: 1}, process.env),
            cwd: directory,
            shell: loginShell.commandExecutorPath,
        };

        ChildProcess.exec(`${command} ${args.join(" ")}`, options, (error, output) => {
            if (error) {
                reject(error);
            } else {
                resolve(output.toString());
            }
        });
    });
}

export async function linedOutputOf(command: string, args: string[], directory: string): Promise<string[]> {
    let output = await executeCommand(command, args, directory);
    return output.split("\\" + OS.EOL).join(" ").split(OS.EOL).filter(path => path.length > 0);
}

export async function executeCommandWithShellConfig(command: string): Promise<string[]> {
    const sourceCommands = (await loginShell.existingConfigFiles()).map(fileName => `source ${fileName} &> /dev/null`);

    return await linedOutputOf(loginShell.executableName, [...loginShell.executeCommandSwitches, loginShell.combineCommands([...sourceCommands, command])], homeDirectory);
}


================================================
FILE: src/PluginManager.ts
================================================
import {Prettyfier, EnvironmentObserverPlugin, AutocompletionProvider} from "./Interfaces";
import * as Path from "path";
import {io} from "./utils/Common";
import { defaultAutocompletionProvider } from "./plugins/completion_utils/Common";

// FIXME: Technical debt: register all the plugin types via single method.
export class PluginManager {
    private static _prettyfiers: Prettyfier[] = [];
    private static _environmentObservers: EnvironmentObserverPlugin[] = [];
    private static _autocompletionProviders: Dictionary<AutocompletionProvider> = {};

    static registerPrettyfier(prettyfier: Prettyfier): void {
        this._prettyfiers.push(prettyfier);
    }

    static get prettyfiers(): Prettyfier[] {
        return this._prettyfiers;
    }

    static registerEnvironmentObserver(plugin: EnvironmentObserverPlugin): void {
        this._environmentObservers.push(plugin);
    }

    static get environmentObservers(): EnvironmentObserverPlugin[] {
        return this._environmentObservers;
    }

    static registerAutocompletionProvider(commandName: string, provider: AutocompletionProvider): void {
        this._autocompletionProviders[commandName] = provider;
    }

    static autocompletionProviderFor(commandName: string): AutocompletionProvider {
        return this._autocompletionProviders[commandName] || defaultAutocompletionProvider;
    }
}


export async function loadAllPlugins(): Promise<void> {
    const pluginsDirectory = Path.join(__dirname, "plugins");
    const filePaths = await io.recursiveFilesIn(pluginsDirectory);

    filePaths.map(require).map((module: any) => module.default);
}


================================================
FILE: src/main/Main.ts
================================================
import {app, ipcMain, nativeImage, BrowserWindow, screen} from "electron";
import {readFileSync} from "fs";
import {windowBoundsFilePath} from "../utils/Common";

app.on("ready", () => {
    const bounds = windowBounds();

    let options: Electron.BrowserWindowConstructorOptions = {
        webPreferences: {
            experimentalFeatures: true,
            experimentalCanvasFeatures: true,
        },
        titleBarStyle: "hidden",
        resizable: true,
        minWidth: 500,
        minHeight: 300,
        width: bounds.width,
        height: bounds.height,
        x: bounds.x,
        y: bounds.y,
        show: false,
    };
    const browserWindow = new BrowserWindow(options);

    if (app.dock) {
        app.dock.setIcon(nativeImage.createFromPath("build/icon.png"));
    } else {
        browserWindow.setIcon(nativeImage.createFromPath("build/icon.png"));
    }

    browserWindow.loadURL("file://" + __dirname + "/../views/index.html");

    browserWindow.webContents.on("did-finish-load", () => {
        browserWindow.show();
        browserWindow.focus();
    });

    app.on("open-file", (_event, file) => browserWindow.webContents.send("change-working-directory", file));
});

app.on("window-all-closed", () => app.quit());

ipcMain.on("quit", app.quit);

function windowBounds(): Electron.Rectangle {
    try {
        return JSON.parse(readFileSync(windowBoundsFilePath).toString());
    } catch (error) {
        const workAreaSize = screen.getPrimaryDisplay().workAreaSize;

        return {
            width: workAreaSize.width,
            height: workAreaSize.height,
            x: 0,
            y: 0,
        };
    }
}


================================================
FILE: src/monaco/Loader.ts
================================================
export function requireMonaco(callback: () => void) {
    const g = (global as any);
    const nodeRequire = g.require;

    const loaderScript = document.createElement("script");
    loaderScript.type = "text/javascript";
    loaderScript.src = "../../../node_modules/monaco-editor/min/vs/loader.js";

    loaderScript.addEventListener("load", () => {
        const amdRequire = g.require;
        g.require = nodeRequire;
        // require node modules before loader.js comes in
        const path = require("path");

        function uriFromPath(_path: string) {
            let pathName = path.resolve(_path).replace(/\\/g, "/");
            if (pathName.length > 0 && pathName.charAt(0) !== "/") {
                pathName = "/" + pathName;
            }
            return encodeURI("file://" + pathName);
        }

        amdRequire.config({
            baseUrl: uriFromPath(path.join(__dirname, "../../../node_modules/monaco-editor/dev")),
        });
        // workaround monaco-css not understanding the environment
        (self as any).module = undefined;
        // workaround monaco-typescript not understanding the environment
        (self as any).process.browser = true;
        amdRequire(["vs/editor/editor.main"], callback);

        // window.require(["vs/editor/editor.main"], () => require("./Main"));
    });
    document.body.appendChild(loaderScript);
}


================================================
FILE: src/monaco/PromptTheme.ts
================================================
import {backgroundColor, colors, textColor} from "../views/css/colors";

monaco.editor.defineTheme("upterm-prompt-theme", {
    base: "vs-dark",
    inherit: true,
    rules: [
        {token: "string", foreground: colors.green.slice(1)},
        {token: "string.invalid", foreground: colors.red.slice(1)},
        {token: "variable-name", foreground: colors.yellow.slice(1)},
        {token: "variable-value", foreground: textColor.slice(1)},
        {token: "command-name", foreground: colors.blue.slice(1), fontStyle: "bold"},
        {token: "argument", foreground: textColor.slice(1)},
        {token: "redirect-path", foreground: colors.yellow.slice(1)},
        {token: "pipe", foreground: colors.yellow.slice(1)},
        {token: "semicolon", foreground: colors.yellow.slice(1)},
        {token: "and", foreground: colors.yellow.slice(1)},
        {token: "or", foreground: colors.yellow.slice(1)},
        {token: "appending-output-redirection-symbol", foreground: colors.yellow.slice(1)},
        {token: "input-redirection-symbol", foreground: colors.yellow.slice(1)},
        {token: "output-redirection-symbol", foreground: colors.yellow.slice(1)},
    ],
    colors: {
        "editor.foreground": textColor,
        "editor.background": backgroundColor,
        "editor.lineHighlightBackground": backgroundColor,
        "editorSuggestWidget.background": backgroundColor,
        "editorSuggestWidget.highlightForeground": colors.blue,
    },
});


================================================
FILE: src/monaco/ShellHistoryLanguage.ts
================================================
import {services} from "../services/index";
import * as _ from "lodash";

monaco.languages.setMonarchTokensProvider("shell-history", {
    tokenizer: {
        root: [
            {
                regex: /.+/,
                action: {token: "history-item"},
            },
        ],
    },
    defaultToken: "invalid",
    tokenPostfix: ".shell-history",
});

monaco.languages.register({
    id: "shell-history",
});

monaco.languages.registerCompletionItemProvider("shell-history", {
    triggerCharacters: [" ", "/"],
    provideCompletionItems: () => {
        return {
            isIncomplete: false,
            items: _.uniqBy(services.history.all, record => record.command).map(record => ({
                label: record.command,
                kind: monaco.languages.CompletionItemKind.Text,
            })),
        };
    },
});

monaco.languages.setLanguageConfiguration("shell-history", {
    wordPattern: /.*/g,
});


================================================
FILE: src/monaco/ShellLanguage.ts
================================================
import {SessionID} from "../shell/Session";
import {getSuggestions} from "../Autocompletion";
import {services} from "../services/index";
import {scan} from "../shell/Scanner";
import {CompleteCommand} from "../shell/Parser";
import {io} from "../utils/Common";

monaco.languages.setMonarchTokensProvider("shell", {
    variableName: /[a-zA-Z][a-zA-Z0-9_]*/,
    word: /[a-zA-Z0-9\u0080-\uFFFF+~!@#%^*_,.:/?\\-]+/,
    escapes: /\\(?:[btnfr\\"']|[0-7][0-7]?|[0-3][0-7]{2})/,
    defaultToken: "invalid",
    tokenizer: {
        root: [
            {
                regex: /\s+/,
                action: {token: "spaces"},
            },
            {
                regex: /@variableName=/,
                action: {token: "variable-name", next: "@variableValue"},
            },
            {
                regex: /@word/,
                action: {token: "command-name", next: "@arguments"},
            },
        ],
        arguments: [
            [/\s+/, "spaces"],
            [/\$@variableName/, "variable-name"],
            [/@word/, "argument"],
            [/[=[\]]/, "argument"],
            {
                regex: /\|\|/,
                action: {token: "or", next: "@pop"},
            },
            {
                regex: /\|/,
                action: {token: "pipe", next: "@pop"},
            },
            {
                regex: /;/,
                action: {token: "semicolon", next: "@pop"},
            },
            {
                regex: /&&/,
                action: {token: "and", next: "@pop"},
            },
            {
                regex: />>/,
                action: {token: "appending-output-redirection-symbol", next: "@redirect"},
            },
            {
                regex: /</,
                action: {token: "input-redirection-symbol", next: "@redirect"},
            },
            {
                regex: />/,
                action: {token: "output-redirection-symbol", next: "@redirect"},
            },
            { include: "@allowStringLiterals" },
        ],
        redirect: [
            {
                regex: /\s+/,
                action: {token: "spaces"},
            },
            {
                regex: /@word/,
                action: {token: "redirect-path", next: "@pop"},
            },
        ],
        variableValue: [
            {
                regex: /@word/,
                action: {token: "variable-value", next: "@pop"},
            },
            {include: "@checkInvalidStringLiteral"},
            {
                regex: /"/,
                action: {token: "string", switchTo: "@doubleQuotedString"},
            },
            {
                regex: /'/,
                action: {token: "string", switchTo: "@singleQuotedString"},
            },
            {
                regex: /.*/,
                action: {token: "invalid"},
            },
        ],
        checkInvalidStringLiteral: [
            // strings: recover on non-terminated strings
            [/"([^"\\]|\\.)*$/, "string.invalid"],  // non-teminated string
            [/'([^'\\]|\\.)*$/, "string.invalid"],  // non-teminated string
        ],
        allowStringLiterals: [
            {include: "@checkInvalidStringLiteral"},
            [/"/, "string", "@doubleQuotedString"],
            [/'/, "string", "@singleQuotedString"],
        ],
        singleQuotedString: [
            [/[^\\']+/, "string"],
            [/@escapes/, "string.escape"],
            [/\\./,      "string.escape.invalid"],
            [/'/, "string", "@pop"],
        ],
        doubleQuotedString: [
            [/\$@variableName/, "variable-name"],
            [/\${@variableName}/, "variable-name"],
            [/[^\\"$]+/, "string"],
            [/@escapes/, "string.escape"],
            [/\\./,      "string.escape.invalid"],
            [/"/, "string", "@pop"],
        ],

    },
    tokenPostfix: ".shell",
} as any);

monaco.languages.register({
    id: "shell",
});

monaco.languages.setLanguageConfiguration("shell", {
    brackets: [
        ["'", "'"],
        ['"', '"'],
        ["`", "`"],
        ["(", ")"],
        ["[", "]"],
        ["{", "}"],
    ],
    wordPattern: /(\d*\.\d\w*\$)|([^`~!#%^&*()=+\[{\]}\\|;:'",<>\/?\s]+)/g,
});

monaco.editor.onDidCreateModel(model => {
    if (model.uri.scheme !== "shell") {
        return;
    }

    model.onDidChangeContent(async () => {
        const value = model.getValue();

        const sessionID: SessionID = <SessionID>Number.parseInt(model.uri.authority, 10);
        const session = services.sessions.get(sessionID);
        const executables = await io.executablesInPaths(session.environment.path);
        const markers: monaco.editor.IMarkerData[] = [];

        monaco.editor.tokenize(value, "shell").forEach((lineTokens, lineIndex) => {
            lineTokens.forEach((token, tokenIndex) => {
                if (token.type !== "command-name.shell") {
                    return;
                }

                const nextToken = lineTokens[tokenIndex + 1];

                // Possibly still writing command name.
                if (!nextToken) {
                    return;
                }

                const tokenRange = {
                    startLineNumber: lineIndex + 1,
                    endLineNumber: lineIndex + 1,
                    startColumn: token.offset + 1,
                    endColumn: nextToken ? (nextToken.offset + 1) : Infinity,
                };
                const commandName = model.getValueInRange(tokenRange);

                if (!executables.includes(commandName) && !session.aliases.has(commandName)) {
                    markers.push({
                        severity: monaco.Severity.Error,
                        message: `Executable ${commandName} doesn't exist in $PATH.`,
                        ...tokenRange,
                    });
                }
            });
        });

        monaco.editor.setModelMarkers(model, "upterm", markers);
    });
});

monaco.languages.registerCompletionItemProvider("shell", {
    triggerCharacters: [" ", "/", "$", "-", "."],
    provideCompletionItems: async function (model, position): Promise<monaco.languages.CompletionList> {
        model.getValue();
        const sessionID: SessionID = <SessionID>Number.parseInt(model.uri.authority, 10);
        const session = services.sessions.get(sessionID);
        const text = model.getValue();

        const ast = new CompleteCommand(scan(text));

        return getSuggestions({
            currentText: text,
            currentCaretPosition: position.column - 1,
            ast: ast,
            environment: session.environment,
            historicalPresentDirectoriesStack: session.historicalPresentDirectoriesStack,
            aliases: session.aliases,
        });
    },
});

// https://github.com/Microsoft/monaco-editor/issues/346#issuecomment-277215371
export function getTokensAtLine(model: any, lineNumber: number) {
    // Force line's state to be accurate
    model.getLineTokens(lineNumber, /*inaccurateTokensAcceptable*/false);
    // Get the tokenization state at the beginning of this line
    const freshState = model._lines[lineNumber - 1].getState().clone();
    // Get the human readable tokens on this line
    return model._tokenizationSupport.tokenize(model.getLineContent(lineNumber), freshState, 0).tokens;
}


================================================
FILE: src/plugins/AliasSuggestions.ts
================================================
import {services} from "../services/index";

services.jobs.onStart.subscribe(job => {
    const input = job.prompt.value;
    const alias = job.session.aliases.getNameByValue(input);

    if (alias && alias.length < input.length) {
        /* tslint:disable:no-unused-expression */
        new Notification("Alias Reminder", { body: `You have an alias "${alias}" for "${input}".` });
    }
});


================================================
FILE: src/plugins/DotEnvLoader.ts
================================================
import {Session} from "../shell/Session";
import {PluginManager} from "../PluginManager";
import * as Path from "path";
import {io} from "../utils/Common";
import {sourceFile} from "../shell/BuiltInCommands";

PluginManager.registerEnvironmentObserver({
    presentWorkingDirectoryWillChange: () => void 0,
    presentWorkingDirectoryDidChange: async(session: Session, directory: string) => {
        if (await io.fileExists(Path.join(directory, ".env"))) {
            sourceFile(session, ".env");
        }
    },
});


================================================
FILE: src/plugins/GitGrep.tsx
================================================
import * as React from "react";
import {PluginManager} from "../PluginManager";
import {Job} from "../shell/Job";
import {Link} from "../utils/Link";
import {join} from "path";
import {colors} from "../views/css/colors";

PluginManager.registerPrettyfier({
  prettify: (job: Job): React.ReactElement<any> => {
    return <div style={{
      padding: "10px",
      lineHeight: "18px",
    }}>{job.output.toLines().map((line, index) => {
      const match = line.match(/^(.*?):(\d+):(.*)$/);
      if (match) {
        const [, path, lineNum, rest] = match;
        if (path && lineNum && rest) {
          const absolutePath = join(job.environment.pwd, path);
          return <div key={index.toString()}>
            <Link absolutePath={absolutePath}>{path}</Link>
            <span style={{color: colors.cyan}}>:</span>
            {lineNum}
            <span style={{color: colors.cyan}}>:</span>
            <span style={{whiteSpace: "pre"}}>{rest}</span>
          </div>;
        }
      }
      return <div key={index.toString()}>{line}</div>;
    })}</div>;
  },

  isApplicable: (job: Job): boolean => {
    try {
      const promptWords = job.prompt.expandedTokens.map(t => t.escapedValue);
      return promptWords.length === 3 && promptWords[0] === "git" && promptWords[1] === "grep";
    } catch (e) {
      return false;
    }
  },
});


================================================
FILE: src/plugins/JSON.tsx
================================================
import * as React from "react";
import {Job} from "../shell/Job";
import {PluginManager} from "../PluginManager";
import {JSONTree} from "../utils/JSONTree";

PluginManager.registerPrettyfier({
    prettify: (job: Job): React.ReactElement<any> => {
        return <JSONTree data={JSON.parse(job.output.toString())}/>;
    },

    isApplicable: (job: Job): boolean => {
        try {
            const parseResult = JSON.parse(job.output.toString());
            return parseResult && typeof parseResult === "object";
        } catch (exception) {
            return false;
        }
    },
});


================================================
FILE: src/plugins/JobFinishedNotifications.ts
================================================
import {services} from "../services/index";
import {remote} from "electron";
import {Status} from "../Enums";

services.jobs.onFinish.subscribe(job => {
    const electronWindow = remote.BrowserWindow.getAllWindows()[0];

    if (remote.app.dock && !electronWindow.isFocused()) {
        remote.app.dock.bounce("informational");
        remote.app.dock.setBadge(job.status === Status.Success ? "1" : "✕");

        const title = job.status === Status.Success ? "Completed" : "Failed";

        /* tslint:disable:no-unused-expression */
        new Notification(title, {body: job.prompt.value});
    }
});

const electronWindow = remote.BrowserWindow.getAllWindows()[0];
electronWindow.on("focus", () => remote.app.dock && remote.app.dock.setBadge(""));


================================================
FILE: src/plugins/NVM.ts
================================================
import {Session} from "../shell/Session";
import {PluginManager} from "../PluginManager";
import * as Path from "path";
import {homeDirectory, io} from "../utils/Common";

async function withNvmPath(directory: string, callback: (path: string) => void) {
    const rcPath = Path.join(directory, ".nvmrc");

    if (await io.fileExists(rcPath)) {
        const version = (await io.readFile(rcPath)).trim();
        callback(Path.join(homeDirectory, ".nvm", "versions", "node", version, "bin"));
    }
}

PluginManager.registerEnvironmentObserver({
    presentWorkingDirectoryWillChange: async(session: Session) => {
        withNvmPath(session.directory, path => session.environment.path.remove(path));
    },
    presentWorkingDirectoryDidChange: async(session: Session, directory: string) => {
        withNvmPath(directory, path => session.environment.path.prepend(path));
    },
});


================================================
FILE: src/plugins/PWDOperatingSystemIntegrator.ts
================================================
import {Session} from "../shell/Session";
import {PluginManager} from "../PluginManager";
import {remote} from "electron";

PluginManager.registerEnvironmentObserver({
    presentWorkingDirectoryWillChange: () => { /* do nothing */ },

    presentWorkingDirectoryDidChange: (_session: Session, directory: string) => {
        remote.app.addRecentDocument(directory);
    },
});


================================================
FILE: src/plugins/RVM.ts
================================================
import {Session} from "../shell/Session";
import {PluginManager} from "../PluginManager";
import * as Path from "path";
import {homeDirectory, io} from "../utils/Common";

const rvmDirectory = Path.join(homeDirectory, ".rvm");
const rubyVersionFileName = ".ruby-version";
const gemSetNameFileName = ".ruby-gemset";

async function getRubyVersion(directory: string): Promise<string> {
    if (await io.fileExists(Path.join(directory, rubyVersionFileName))) {
        return (await io.readFile(Path.join(directory, rubyVersionFileName))).trim();
    } else {
        const resolvedPath = await io.realPath(Path.join(rvmDirectory, "rubies", "default"));
        return resolvedPath.split("-")[1];
    }
}

async function getGemSetName(directory: string): Promise<string> {
    const gemSetNameFilePath = Path.join(directory, gemSetNameFileName);

    if (await io.fileExists(gemSetNameFilePath)) {
        return (await io.readFile(gemSetNameFilePath)).trim();
    } else {
        return "global";
    }
}

/**
 * Contract: the non-global path should be first.
 */
function getGemSetPaths(rubyVersion: string, gemSetName: string): string[] {
    const suffixes = gemSetName === "global" ? ["", "@global"] : [`@${gemSetName}`, "@global"];
    return suffixes.map(suffix => Path.join(rvmDirectory, "gems", `ruby-${rubyVersion}${suffix}`));
}

function binPaths(rubyVersion: string, gemSetName: string): string[] {
    return [
        Path.join(rvmDirectory, "bin"),
        Path.join(rvmDirectory, "rubies", `ruby-${rubyVersion}`, "bin"),
        ...getGemSetPaths(rubyVersion, gemSetName).map(path => Path.join(path, "bin")),
    ];
}

async function withRvmData(directory: string, callback: (binPaths: string[], gemPaths: string[]) => void) {
    try {
        const rubyVersion = await getRubyVersion(directory);
        const gemSetName = await getGemSetName(directory);
        const gemPaths = getGemSetPaths(rubyVersion, gemSetName);

        callback(binPaths(rubyVersion, gemSetName), gemPaths);
    } catch (e) {
        if (e.code === "ENOENT") {
            // No RVM installed. Ignore exception.
        } else {
            throw e;
        }
    }
}

PluginManager.registerEnvironmentObserver({
    presentWorkingDirectoryWillChange: () => async(session: Session, directory: string) => {
        withRvmData(directory, binPaths => {
            binPaths.forEach(path => session.environment.path.remove(path));

            session.environment.setMany({
                GEM_PATH: "",
                GEM_HOME: "",
            });
        });
    },
    presentWorkingDirectoryDidChange: async(session: Session, directory: string) => {
        withRvmData(directory, (binPaths, gemPaths) => {
            binPaths.forEach(path => session.environment.path.prepend(path));

            session.environment.setMany({
                GEM_PATH: gemPaths.join(Path.delimiter),
                GEM_HOME: gemPaths[0],
            });
        });
    },
});


================================================
FILE: src/plugins/SaveHistory.ts
================================================
import {appendFileSync} from "fs";
import {historyFilePath} from "../utils/Common";
import * as csvStringify from "csv-stringify";
import {services} from "../services/index";

services.jobs.onFinish.subscribe(job => services.history.add({
    command: job.prompt.value,
    expandedCommand: job.prompt.expandedTokens.map(t => t.escapedValue).join(" "),
    timestamp: job.startTime,
    directory: job.environment.pwd,
    sessionID: job.session.id,
}));

services.history.onNewRecord.subscribe(record => csvStringify(
    [Object.values(record)],
    (_error, output) => appendFileSync(historyFilePath, output),
));


================================================
FILE: src/plugins/SaveWindowBounds.ts
================================================
import {services} from "../services/index";
import {windowBoundsFilePath} from "../utils/Common";
import {outputJSON} from "fs-extra";

services.window.onBoundsChange.subscribe(bounds => outputJSON(windowBoundsFilePath, bounds));


================================================
FILE: src/plugins/Show.tsx
================================================
import * as React from "react";
import {PluginManager} from "../PluginManager";
import {Job} from "../shell/Job";

PluginManager.registerPrettyfier({
    prettify: (job: Job): React.ReactElement<any> => {
        const rows = job.output.toLines().map(path => <img style={{maxHeight: "90vh", maxWidth: "100vh"}} src={path}/>);

        return <div>{rows}</div>;
    },

    isApplicable: (job: Job): boolean => {
        return job.hasOutput() && (job.prompt.commandName === "show");
    },
});


================================================
FILE: src/plugins/UpdateLastPresentWorkingDirectory.ts
================================================
import {services} from "../services/index";
import {outputJSON} from "fs-extra";
import {presentWorkingDirectoryFilePath} from "../utils/Common";

services.jobs.onFinish.subscribe(job =>
    outputJSON(presentWorkingDirectoryFilePath, job.session.directory),
);


================================================
FILE: src/plugins/completion/Brew.ts
================================================
import {
    emptyProvider,
    longFlag,
    provide,
    shortFlag,
    staticSuggestionsProvider,
    Suggestion,
} from "../completion_utils/Common";
import {combine} from "../completion_utils/Combine";
import {PluginManager} from "../../PluginManager";
import {AutocompletionContext, AutocompletionProvider} from "../../Interfaces";
import {executeCommand} from "../../PTY";
import {concat, find, memoize, sortBy} from "lodash";
import {homeDirectory} from "../../utils/Common";

interface FormulaAttributes {
    name: string;
    path: string;
}

const getFormulae = memoize(
    async(brewArgs: string[]): Promise<FormulaAttributes[]> => {
        const text = await executeCommand("brew", brewArgs, homeDirectory);

        const matches = text.match(/^([\-a-zA-Z0-9]+\/)*([\-a-zA-Z0-9]+)$/gm);
        if (matches) {
            return matches.map((match: string) => {
                const matchParts = match.split("/");
                return {
                    name: matchParts[matchParts.length - 1],
                    path: matchParts.length > 1 ? match.trim() : "",
                };
            });
        }
        return [];
    },
    (brewArgs: string[]) => brewArgs.join(" "),
);

const getAllFormulae = (cask: boolean) => getFormulae(cask ? ["cask", "search"] : ["search"]);
const getInstalledFormulae = (cask: boolean) => getFormulae(cask ? ["cask", "list"] : ["list"]);

const formulaSuggestions = async(formulae: FormulaAttributes[],
                                 query: string): Promise<Suggestion[]> => {
    if (!formulae) {
        return [];
    }
    return formulae
        .filter(formula =>  !query ||
        formula.name.startsWith(query) ||
        formula.path.startsWith(query))
        .map(formula => ({
            label: formula.name,
        }));
};

const availableFormulae = provide(async context => {
    const argument = context.argument.command.nthArgument(2);
    const query = argument ? argument.value : "";
    return formulaSuggestions(await getAllFormulae(false), query);
});

const installedFormulae = provide(async context => {
    const argument = context.argument.command.nthArgument(2);
    const query = argument ? argument.value : "";
    return formulaSuggestions(await getInstalledFormulae(false), query);
});

const caskAvailableFormulae = provide(async context => {
    const argument = context.argument.command.nthArgument(3);
    const query = argument ? argument.value : "";
    return formulaSuggestions(await getAllFormulae(true), query);
});

const caskInstalledFormulae = provide(async context => {
    const argument = context.argument.command.nthArgument(3);
    const query = argument ? argument.value : "";
    return formulaSuggestions(await getInstalledFormulae(true), query);
});

interface BrewCommandData {
    name: string;
    description: string;
    provider?: AutocompletionProvider;
    commands?: BrewCommandData[];
}

const commonCommands: BrewCommandData[] = [
    {
        name: "search",
        description: "Perform a substring search of formula names",
        provider: combine([
            longFlag("desc"),
        ]),
    },
    {
        name: "update",
        description: "Fetch the newest version of Homebrew",
        provider: combine([
            longFlag("merge"),
            longFlag("force"),
        ]),
    },
    {
        name: "list",
        description: "List all installed formulae",
        provider: combine([
            longFlag("versions"),
            longFlag("pinned"),
        ]),
    },
    {
        name: "doctor",
        description: "Check your system for potential problems",
        provider: emptyProvider,
    },
    {
        name: "create",
        description: "Generate a formula for a downloadable file",
        provider: combine([
            longFlag("autotools"),
            longFlag("cmake"),
            longFlag("no-fetch"),
            longFlag("set-name"),
            longFlag("tap"),
        ]),
    },
];

const caskCommands: BrewCommandData[] = [
    {
        name: "install",
        description: "Install a Cask formula",
        provider: combine([
            caskAvailableFormulae,
            longFlag("force"),
            longFlag("skip-cask-deps"),
            longFlag("require-sha"),
        ]),
    },
    {
        name: "fetch",
        description: "Download a Cask formula",
        provider: combine([
            caskAvailableFormulae,
            longFlag("force"),
        ]),
    },
    {
        name: "remove",
        description: "Uninstall a Cask formula",
        provider: combine([
            caskInstalledFormulae,
            longFlag("force"),
        ]),
    },
    {
        name: "uninstall",
        description: "Uninstall a Cask formula",
        provider: combine([
            caskInstalledFormulae,
            longFlag("force"),
        ]),
    },
    {
        name: "cat",
        description: "Display the source to a Cask formula",
        provider: caskInstalledFormulae,
    },
    {
        name: "cleanup",
        description: "Remove old version and download files for formula",
        provider: combine([
            caskInstalledFormulae,
            longFlag("outdated"),
        ]),
    },
    {
        name: "info",
        description: "Display information about a Cask formula",
        provider: caskAvailableFormulae,
    },
    {
        name: "home",
        description: "Open a Cask formula homepage in the browser",
        provider: caskAvailableFormulae,
    },
    {
        name: "edit",
        description: "Edit a Cask formula",
        provider: caskInstalledFormulae,
    },
];

const brewCommands: BrewCommandData[] = [
    {
        name: "install",
        description: "Install a formula",
        provider: combine([
            availableFormulae,
            longFlag("debug"),
            longFlag("env"),
            longFlag("ignore-dependencies"),
            longFlag("only-dependencies"),
            longFlag("build-from-source"),
            longFlag("devel"),
            longFlag("keep-temp"),
            longFlag("cc"),
        ]),
    },
    {
        name: "cask",
        description: "Install a cask formula",
        commands: concat(caskCommands, commonCommands),
    },
    {
        name: "fetch",
        description: "Install a formula",
        provider: combine([
            availableFormulae,
            longFlag("force"),
            longFlag("retry"),
            longFlag("deps"),
            longFlag("build-from-source"),
            longFlag("force-bottle"),
        ]),
    },
    {
        name: "remove",
        description: "Uninstall a formula",
        provider: combine([
            installedFormulae,
            longFlag("force"),
        ]),
    },
    {
        name: "uninstall",
        description: "Uninstall a formula",
        provider: combine([
            installedFormulae,
            longFlag("force"),
        ]),
    },
    {
        name: "upgrade",
        description: "Upgrade a formula",
        provider: combine([
            installedFormulae,
            longFlag("upgrade"),
            longFlag("fetch-HEAD"),
        ]),
    },
    {
        name: "cat",
        description: "Display the source to a formula",
        provider: installedFormulae,
    },
    {
        name: "cleanup",
        description: "Remove old version and download files for formula",
        provider: combine([
            installedFormulae,
            longFlag("prune"),
            longFlag("dry-run"),
            shortFlag("s"),
        ]),
    },
    {
        name: "deps",
        description: "Show dependencies for a formula",
        provider: combine([
            availableFormulae,
            longFlag("1"),
            shortFlag("n"),
            longFlag("union"),
            longFlag("installed"),
            longFlag("include-build"),
            longFlag("include-optional"),
            longFlag("skip-recommended"),
            longFlag("tree"),
        ]),
    },
    {
        name: "info",
        description: "Display information about a formula",
        provider: combine([
            availableFormulae,
            longFlag("github"),
            longFlag("json"),
            longFlag("installed"),
            longFlag("all"),
        ]),
    },
    {
        name: "home",
        description: "Open a formula homepage in the browser",
        provider: availableFormulae,
    },
    {
        name: "options",
        description: "Display install options for a formula",
        provider: availableFormulae,
    },
    {
        name: "edit",
        description: "Edit a formula",
        provider: installedFormulae,
    },
];

const fromData = (commandsData: BrewCommandData[]) => {
    const suggestions = sortBy(
        commandsData.map(command => ({label: command.name, detail: command.description || ""})),
        suggestion => !suggestion.detail,
    );
    return staticSuggestionsProvider(suggestions);
};

let getProvider = (context: AutocompletionContext,
                   commandData: BrewCommandData[],
                   argIndex: number): AutocompletionProvider => {
    if (context.argument.position === argIndex) {
        return fromData(commandData);
    }

    const argument = context.argument.command.nthArgument(argIndex);
    if (!argument) {
        return emptyProvider;
    }

    const name = argument.value;
    const data = find(commandData, {name});

    if (data && data.commands) {
        return getProvider(context, data.commands, argIndex + 1);
    } else if (data && data.provider) {
        return data.provider;
    }

    return emptyProvider;
};

PluginManager.registerAutocompletionProvider("brew", async context => {
    const provider = getProvider(context, concat(brewCommands, commonCommands), 1);
    return provider(context);
});


================================================
FILE: src/plugins/completion/Cat.ts
================================================
import {PluginManager} from "../../PluginManager";
import {anyFilesSuggestionsProvider} from "../completion_utils/Common";
import {combine} from "../completion_utils/Combine";
import {manPageOptions} from "../../utils/ManPages";

PluginManager.registerAutocompletionProvider("cat", combine([anyFilesSuggestionsProvider, manPageOptions("cat")]));


================================================
FILE: src/plugins/completion/Cd.ts
================================================
import {directoriesSuggestionsProvider, Suggestion} from "../completion_utils/Common";
import * as _ from "lodash";
import {PluginManager} from "../../PluginManager";
import {join} from "path";
import {userFriendlyPath} from "../../utils/Common";

PluginManager.registerAutocompletionProvider("cd", async(context) => {
    let suggestions: Suggestion[] = await directoriesSuggestionsProvider(context);

    if (context.argument.value.length === 0) {
        const cdpathDirectories = _.flatten(await Promise.all(context.environment.cdpath.filter(path => path !== "." && path !== context.environment.pwd)
            .map(async(directory) => (await directoriesSuggestionsProvider(context, directory)).map(suggestion => ({...suggestion, label: userFriendlyPath(join(directory, suggestion.label))})))));

        suggestions.push(...cdpathDirectories);
    }

    return suggestions;
});


================================================
FILE: src/plugins/completion/Cp.ts
================================================
import {PluginManager} from "../../PluginManager";
import {anyFilesSuggestionsProvider} from "../completion_utils/Common";
import {combine} from "../completion_utils/Combine";
import {manPageOptions} from "../../utils/ManPages";

PluginManager.registerAutocompletionProvider("cp", combine([anyFilesSuggestionsProvider, manPageOptions("cp")]));


================================================
FILE: src/plugins/completion/Df.ts
================================================
import {PluginManager} from "../../PluginManager";
import {manPageOptions} from "../../utils/ManPages";

PluginManager.registerAutocompletionProvider("df", manPageOptions("df"));


================================================
FILE: src/plugins/completion/Executable.ts
================================================
export const commandDescriptions: Dictionary<string> = {
    admin: "Create and administer SCCS files",
    alias: "Define or display aliases",
    ar: "Create and maintain library archives",
    asa: "Interpret carriage-control characters",
    at: "Execute commands at a later time",
    awk: "Pattern scanning and processing language",
    basename: "Return non-directory portion of a pathname; see also dirname",
    batch: "Schedule commands to be executed in a batch queue",
    bc: "Arbitrary-precision arithmetic language",
    bg: "Run jobs in the background",
    cc: "Compile standard C programs",
    cal: "Print a calendar",
    cat: "Concatenate and print files",
    cflow: "Generate a C-language flowgraph",
    chgrp: "Change the file group ownership",
    chmod: "Change the file modes/attributes/permissions",
    chown: "Change the file ownership",
    cksum: "Write file checksums and sizes",
    cmp: "Compare two files; see also diff",
    comm: "Select or reject lines common to two files",
    command: "Execute a simple command",
    compress: "Compress data",
    cp: "Copy files",
    crontab: "Schedule periodic background work",
    csplit: "Split files based on context",
    ctags: "Create a tags file",
    cut: "Cut out selected fields of each line of a file",
    cxref: "Generate a C-language program cross-reference table",
    date: "Display the date and time",
    dd: "Convert and copy a file",
    delta: "Make a delta (change) to an SCCS file",
    df: "Report free disk space",
    diff: "Compare two files; see also cmp",
    dirname: "Return the directory portion of a pathname; see also basename",
    du: "Estimate file space usage",
    echo: "Write arguments to standard output",
    ed: "The standard text editor",
    env: "Set the environment for command job",
    ex: "Text editor",
    expand: "Convert tabs to spaces",
    expr: "Evaluate arguments as an expression",
    FALSE: "Return false value",
    fc: "Process the command history list",
    fg: "Run jobs in the foreground",
    file: "Determine file type",
    find: "Find files",
    fold: "Filter for folding lines",
    fort77: "FORTRAN compiler",
    fuser: "List process IDs of all processes that have one or more files open",
    gencat: "Generate a formatted message catalog",
    get: "Get a version of an SCCS file",
    getconf: "Get configuration values",
    getopts: "Parse utility options",
    grep: "Search text for a pattern",
    hash: "hash database access method",
    head: "Copy the first part of files",
    iconv: "Codeset conversion",
    id: "Return user identity",
    ipcrm: "Remove a message queue, semaphore set, or shared memory segment identifier",
    ipcs: "Report interprocess communication facilities status",
    jobs: "Display status of jobs in the current session",
    join: "Merges two sorted text files based on the presence of a common field",
    kill: "Terminate or signal processes",
    lex: "Generate programs for lexical tasks",
    link: "Create a hard link to a file",
    ln: "Link files",
    locale: "Get locale-specific information",
    localedef: "Define locale environment",
    logger: "Log messages",
    logname: "Return the user\"s login name",
    lp: "Send files to a printer",
    ls: "List directory contents",
    m4: "Macro processor",
    mailx: "Process messages",
    make: "Maintain, update, and regenerate groups of programs",
    man: "Display system documentation",
    mesg: "Permit or deny messages",
    mkdir: "Make directories",
    mkfifo: "Make FIFO special files",
    more: "Display files on a page-by-page basis",
    mv: "Move files",
    newgrp: "Change to a new group (functionaliy similar to sg[1])",
    nice: "Invoke a utility with an altered nice value",
    nl: "Line numbering filter",
    nm: "Write the name list of an object file",
    nohup: "Invoke a utility immune to hangups",
    od: "Dump files in various formats",
    paste: "Merge corresponding or subsequent lines of files",
    patch: "Apply changes to files",
    pathchk: "Check pathnames",
    pax: "Portable archive interchange",
    pr: "Print files",
    printf: "Write formatted output",
    prs: "Print an SCCS file",
    ps: "Report process status",
    pwd: "print working directory - Return working directory name",
    qalter: "Alter batch job",
    qdel: "Delete batch jobs",
    qhold: "Hold batch jobs",
    qmove: "Move batch jobs",
    qmsg: "Send message to batch jobs",
    qrerun: "Rerun batch jobs",
    qrls: "Release batch jobs",
    qselect: "Select batch jobs",
    qsig: "Signal batch jobs",
    qstat: "Show status of batch jobs",
    qsub: "Submit a script",
    read: "Read a line from standard input",
    renice: "Set nice values of running processes",
    rm: "Remove directory entries",
    rmdel: "Remove a delta from an SCCS file",
    rmdir: "Remove directories",
    sact: "Print current SCCS file-editing activity",
    sccs: "Front end for the SCCS subsystem",
    sed: "Stream editor",
    sh: "Shell, the standard command language interpreter",
    sleep: "Suspend execution for an interval",
    sort: "Sort, merge, or sequence check text files",
    split: "Split files into pieces",
    strings: "Find printable strings in files",
    strip: "Remove unnecessary information from executable files",
    stty: "Set the options for a terminal",
    tabs: "Set terminal tabs",
    tail: "Copy the last part of a file",
    talk: "Talk to another user",
    tee: "Duplicate the standard output",
    test: "Evaluate expression",
    time: "Time a simple command",
    touch: "Change file access and modification times",
    tput: "Change terminal characteristics",
    tr: "Translate characters",
    TRUE: "Return true value",
    tsort: "Topological sort",
    tty: "Return user\"s terminal name     ",
    type: "Displays how a name would be interpreted if used as a command",
    ulimit: "Set or report file size limit",
    umask: "Get or set the file mode creation mask",
    unalias: "Remove alias definitions",
    uname: "Return system name",
    uncompress: "Expand compressed data",
    unexpand: "Convert spaces to tabs",
    unget: "Undo a previous get of an SCCS file",
    uniq: "Report or filter out repeated lines in a file",
    unlink: "Call the unlink function",
    uucp: "System-to-system copy",
    uudecode: "Decode a binary file",
    uuencode: "Encode a binary file",
    uustat: "uucp status inquiry and job control",
    uux: "Remote command execution",
    val: "Validate SCCS files",
    vi: "Screen-oriented (visual) display editor",
    wait: "Await process completion",
    wc: "Line, word and byte or character count",
    what: "Identify SCCS files",
    who: "Display who is on the system",
    write: "Write to another user\"s terminal",
    xargs: "Construct argument lists and invoke utility",
    yacc: "Yet another compiler compiler",
    zcat: "Expand and concatenate data",
};


================================================
FILE: src/plugins/completion/Find.ts
================================================
import {PluginManager} from "../../PluginManager";
import {directoriesSuggestionsProvider} from "../completion_utils/Common";
import {combine} from "../completion_utils/Combine";
import {manPageOptions} from "../../utils/ManPages";

const findOptions = manPageOptions("find");

PluginManager.registerAutocompletionProvider("find", combine([directoriesSuggestionsProvider, findOptions]));


================================================
FILE: src/plugins/completion/Git.ts
================================================
import * as Git from "../../utils/Git";
import {
    commandWithSubcommands,
    emptyProvider,
    longFlag,
    provide,
    staticSuggestionsProvider,
    SubcommandConfig,
    Suggestion,
    unique,
} from "../completion_utils/Common";
import {combine} from "../completion_utils/Combine";
import {PluginManager} from "../../PluginManager";
import {executeCommand, linedOutputOf} from "../../PTY";
import {find, once, sortBy} from "lodash";
import {homeDirectory} from "../../utils/Common";
import {descriptions} from "../completion_utils/Descriptions";

const addOptions: Suggestion[] = [
    {
        label: "-p",
        detail: descriptions.git.add.patch,
    },
    {
        label: "--patch",
        detail: descriptions.git.add.patch,
    },
    {
        label: "-i",
        detail: descriptions.git.add.interactive,
    },
    {
        label: "--interactive",
        detail: descriptions.git.add.interactive,
    },
    {
        label: "-n",
        detail: descriptions.git.add.dryRun,
    },
    {
        label: "--dry-run",
        detail: descriptions.git.add.dryRun,
    },
    {
        label: "-v",
        detail: descriptions.git.add.verbose,
    },
    {
        label: "--verbose",
    },
    {
        label: "-f",
        detail: descriptions.git.add.force,
    },
    {
        label: "--force",
        detail: descriptions.git.add.force,
    },
    {
        label: "-e",
        detail: descriptions.git.add.edit,
    },
    {
        label: "--edit",
        detail: descriptions.git.add.edit,
    },
    {
        label: "-u",
        detail: descriptions.git.add.update,
    },
    {
        label: "--update",
        detail: descriptions.git.add.update,
    },
    {
        label: "-A",
        detail: descriptions.git.add.noIgnoreRemoval,
    },
    {
        label: "--all",
        detail: descriptions.git.add.noIgnoreRemoval,
    },
    {
        label: "--no-ignore-removal",
        detail: descriptions.git.add.noIgnoreRemoval,
    },
    {
        label: "--no-all",
        detail: descriptions.git.add.ignoreRemoval,
    },
    {
        label: "--ignore-removal",
        detail: descriptions.git.add.ignoreRemoval,
    },
    {
        label: "-N",
        detail: descriptions.git.add.intentToAdd,
    },
    {
        label: "--intent-to-add",
        detail: descriptions.git.add.intentToAdd,
    },
    {
        label: "--refresh",
        detail: descriptions.git.add.refresh,
    },
    {
        label: "--ignore-errors",
        detail: descriptions.git.add.ignoreErrors,
    },
    {
        label: "--ignore-missing",
        detail: descriptions.git.add.ignoreMissing,
    },
    {
        label: "--chmod=",
        detail: descriptions.git.add.chmod,
    },
    {
        label: "--",
        detail: descriptions.git.add.separator,
    },
];

const commitOptions: Suggestion[] = [
    {
        label: "--message",
        detail: descriptions.git.commit.message,
        kind: monaco.languages.CompletionItemKind.Snippet,
        insertText: {value: "--message \"${0:Commit message}\""},
    },
    {
        label: "-m",
        detail: descriptions.git.commit.message,
        kind: monaco.languages.CompletionItemKind.Snippet,
        insertText: {value: "-m \"${0:Commit message}\""},
    },
    {
        label: "--all",
        detail: descriptions.git.commit.all,
    },
    {
        label: "-a",
        detail: descriptions.git.commit.all,
    },
    {
        label: "--patch",
        detail: descriptions.git.commit.patch,
    },
    {
        label: "-p",
        detail: descriptions.git.commit.patch,
    },
    {
        label: "--null",
        detail: descriptions.git.commit.NULL,
    },
    {
        label: "-z",
        detail: descriptions.git.commit.NULL,
    },
    {
        label: "--template",
        detail: descriptions.git.commit.template,
    },
    {
        label: "-t",
        detail: descriptions.git.commit.template,
    },
    {
        label: "--signoff",
        detail: descriptions.git.commit.signoff,
    },
    {
        label: "-s",
        detail: descriptions.git.commit.signoff,
    },
    {
        label: "--no-verify",
        detail: descriptions.git.commit.noVerify,
    },
    {
        label: "-n",
        detail: descriptions.git.commit.noVerify,
    },
    {
        label: "--edit",
        detail: descriptions.git.commit.edit,
    },
    {
        label: "-e",
        detail: descriptions.git.commit.edit,
    },
    {
        label: "--include",
        detail: descriptions.git.commit.include,
    },
    {
        label: "-i",
        detail: descriptions.git.commit.include,
    },
    {
        label: "--only",
        detail: descriptions.git.commit.only,
    },
    {
        label: "-o",
        detail: descriptions.git.commit.only,
    },
    {
        label: "--verbose",
        detail: descriptions.git.commit.verbose,
    },
    {
        label: "-v",
        detail: descriptions.git.commit.verbose,
    },
    {
        label: "--quiet",
        detail: descriptions.git.commit.quiet,
    },
    {
        label: "-q",
        detail: descriptions.git.commit.quiet,
    },
    {
        label: "--reset-author",
        detail: descriptions.git.commit.resetAuthor,
    },
    {
        label: "--short",
        detail: descriptions.git.commit.short,
    },
    {
        label: "--branch",
        detail: descriptions.git.commit.branch,
    },
    {
        label: "--porcelain",
        detail: descriptions.git.commit.porcelain,
    },
    {
        label: "--long",
        detail: descriptions.git.commit.long,
    },
    {
        label: "--allow-empty",
        detail: descriptions.git.commit.allowEmpty,
    },
    {
        label: "--allow-empty-message",
        detail: descriptions.git.commit.allowEmptyMessage,
    },
    {
        label: "--no-edit",
        detail: descriptions.git.commit.noEdit,
    },
    {
        label: "--no-post-rewrite",
        detail: descriptions.git.commit.noPostRewrite,
    },
    {
        label: "--dry-run",
        detail: descriptions.git.commit.dryRun,
    },
    {
        label: "--status",
        detail: descriptions.git.commit.status,
    },
    {
        label: "--no-status",
        detail: descriptions.git.commit.noStatus,
    },
    {
        label: "--no-gpg-sign",
        detail: descriptions.git.commit.noGpgSign,
    },
];

const pushOptions: Suggestion[] = [
    {
        label: "--all",
        detail: descriptions.git.push.all,
    },
    {
        label: "--prune",
        detail: descriptions.git.push.prune,
    },
    {
        label: "--force",
    },
    {
        label: "--force-with-lease",
    },
];

const resetOptions: Suggestion[] = [
    {
        label: "--soft",
    },
    {
        label: "--mixed",
    },
    {
        label: "--hard",
    },
    {
        label: "--merge",
    },
    {
        label: "--keep",
    },
];

const stashOptions: Suggestion[] = [
    {
        label: "list",
    },
    {
        label: "show",
    },
    {
        label: "drop",
    },
    {
        label: "pop",
    },
    {
        label: "apply",
    },
    {
        label: "save",
    },
    {
        label: "push",
    },
    {
        label: "clear",
    },
    {
        label: "create",
    },
    {
        label: "store",
    },
];

const statusOptions: Suggestion[] = [
    {
        label: "-s",
        detail: descriptions.git.status.short,
    },
    {
        label: "--short",
        detail: descriptions.git.status.short,
    },
    {
        label: "-b",
        detail: descriptions.git.status.branch,
    },
    {
        label: "--branch",
        detail: descriptions.git.status.branch,
    },
    {
        label: "--porcelain",
        detail: descriptions.git.status.porcelain,
    },
    {
        label: "--long",
        detail: descriptions.git.status.long,
    },
    {
        label: "-v",
        detail: descriptions.git.status.verbose,
    },
    {
        label: "--verbose",
        detail: descriptions.git.status.verbose,
    },
    {
        label: "-u",
        detail: descriptions.git.status.untrackedFiles,
    },
    {
        label: "--untracked-files",
        detail: descriptions.git.status.untrackedFiles,
    },
    {
        label: "--ignore-submodules",
        detail: descriptions.git.status.ignoreSubmodules,
    },
    {
        label: "--ignored",
        detail: descriptions.git.status.ignored,
    },
    {
        label: "-z",
        detail: descriptions.git.status.terminateWithNull,
    },
    {
        label: "--column",
        detail: descriptions.git.status.column,
    },
    {
        label: "--no-column",
        detail: descriptions.git.status.column,
    },
];

const configOptions: Suggestion[] = [
    {
        label: "--global",
    },
    {
        label: "--system",
    },
    {
        label: "--list",
    },
    {
        label: "-l",
    },
    {
        label: "--edit",
    },
    {
        label: "-e",
    },
];

const fetchOptions: Suggestion[] = [
    {
        label: "--quiet",
    },
    {
        label: "--verbose",
    },
    {
        label: "--append",
    },
    {
        label: "--upload-pack",
    },
    {
        label: "--force",
    },
    {
        label: "--keep",
    },
    {
        label: "--depth=",
    },
    {
        label: "--tags",
    },
    {
        label: "--no-tags",
    },
    {
        label: "--all",
    },
    {
        label: "--prune",
    },
    {
        label: "--dry-run",
    },
    {
        label: "--recurse-submodules=",
    },
];

const checkoutOptions: Suggestion[] = [
    {
        label: "-b",
        detail: descriptions.git.checkout.branch,
    },
];

const commonMergeOptions: Suggestion[] = [
    {
        label: "--no-commit",
    },
    {
        label: "--no-stat",
    },
    {
        label: "--log",
    },
    {
        label: "--no-log",
    },
    {
        label: "--squash",
    },
    {
        label: "--strategy",
    },
    {
        label: "--commit",
    },
    {
        label: "--stat",
    },
    {
        label: "--no-squash",
    },
    {
        label: "--ff",
    },
    {
        label: "--no-ff",
    },
    {
        label: "--ff-only",
    },
    {
        label: "--edit",
    },
    {
        label: "--no-edit",
    },
    {
        label: "--verify-signatures",
    },
    {
        label: "--no-verify-signatures",
    },
    {
        label: "--gpg-sign",
    },
    {
        label: "--quiet",
    },
    {
        label: "--verbose",
    },
    {
        label: "--progress",
    },
    {
        label: "--no-progress",
    },
];

function doesLookLikeBranchAlias(word: string) {
    if (!word) return false;
    return word.startsWith("-") || word.includes("@") || word.includes("HEAD") || /\d/.test(word);
}

function canonizeBranchAlias(alias: string) {
    if (alias[0] === "-") {
        const steps = parseInt(alias.slice(1), 10) || 1;
        alias = `@{-${steps}}`;
    }

    return alias;
}

const remotes = provide(async context => {
    if (Git.isGitDirectory(context.environment.pwd)) {
        const names = await Git.remotes(context.environment.pwd);
        return names.map(name => ({label: name}));
    }

    return [];
});

const configVariables = unique(provide(async context => {
    const variables = await Git.configVariables(context.environment.pwd);

    return variables.map(variable => ({label: variable.name, detail: variable.value}));
}));

const branchesExceptCurrent = provide(async context => {
    if (Git.isGitDirectory(context.environment.pwd)) {
        const allBranches = (await Git.branches({
            directory: context.environment.pwd,
            remotes: true,
            tags: false,
        }));
        const nonCurrentBranches = allBranches.filter(branch => !branch.isCurrent());
        return nonCurrentBranches.map(branch => ({label: branch.toString()}));
    } else {
        return [];
    }
});

const branchAlias = provide(async context => {
    if (doesLookLikeBranchAlias(context.argument.value)) {
        let nameOfAlias = (await linedOutputOf("git", ["name-rev", "--name-only", canonizeBranchAlias(context.argument.value)], context.environment.pwd))[0];
        if (nameOfAlias && !nameOfAlias.startsWith("Could not get")) {
            return [{label: context.argument.value, detail: nameOfAlias}];
        }
    }

    return [];
});

const notStagedFiles = unique(provide(async context => {
    if (Git.isGitDirectory(context.environment.pwd)) {
        const fileStatuses = await Git.status(context.environment.pwd);
        return fileStatuses.map(fileStatus => ({label: fileStatus.value}));
    } else {
        return [];
    }
}));

const commandsData: SubcommandConfig[] = [
    {
        name: "add",
        detail: descriptions.git.subcommands.add,
        provider: combine([notStagedFiles, staticSuggestionsProvider(addOptions)]),
    },
    {
        name: "am",
        detail: descriptions.git.subcommands.am,
    },
    {
        name: "archive",
        detail: descriptions.git.subcommands.archive,
    },
    {
        name: "bisect",
        detail: descriptions.git.subcommands.bisect,
    },
    {
        name: "branch",
        detail: descriptions.git.subcommands.branch,
        provider: branchesExceptCurrent,
    },
    {
        name: "bundle",
        detail: descriptions.git.subcommands.bundle,
    },
    {
        name: "checkout",
        detail: descriptions.git.subcommands.checkout,
        provider: combine([branchesExceptCurrent, branchAlias, notStagedFiles, staticSuggestionsProvider(checkoutOptions)]),
    },
    {
        name: "cherry-pick",
        detail: descriptions.git.subcommands.cherryPick,
    },
    {
        name: "citool",
        detail: descriptions.git.subcommands.citool,
    },
    {
        name: "clean",
        detail: descriptions.git.subcommands.clean,
    },
    {
        name: "clone",
        detail: descriptions.git.subcommands.clone,
    },
    {
        name: "commit",
        detail: descriptions.git.subcommands.commit,
        provider: staticSuggestionsProvider(commitOptions),
    },
    {
        name: "config",
        detail: descriptions.git.subcommands.config,
        provider: combine([configVariables, staticSuggestionsProvider(configOptions)]),
    },
    {
        name: "describe",
        detail: descriptions.git.subcommands.describe,
    },
    {
        name: "diff",
        detail: descriptions.git.subcommands.diff,
    },
    {
        name: "fetch",
        detail: descriptions.git.subcommands.fetch,
        provider: combine([remotes, staticSuggestionsProvider(fetchOptions)]),
    },
    {
        name: "format-patch",
        detail: descriptions.git.subcommands.formatPatch,
    },
    {
        name: "gc",
        detail: descriptions.git.subcommands.gc,
    },
    {
        name: "grep",
        detail: descriptions.git.subcommands.grep,
    },
    {
        name: "gui",
        detail: descriptions.git.subcommands.gui,
    },
    {
        name: "init",
        detail: descriptions.git.subcommands.init,
    },
    {
        name: "log",
        detail: descriptions.git.subcommands.log,
    },
    {
        name: "merge",
        detail: descriptions.git.subcommands.merge,
        provider: combine([
            branchesExceptCurrent,
            branchAlias,
            staticSuggestionsProvider(commonMergeOptions),
            longFlag("rerere-autoupdate"),
            longFlag("no-rerere-autoupdate"),
            longFlag("abort"),
        ]),
    },
    {
        name: "mv",
        detail: descriptions.git.subcommands.mv,
    },
    {
        name: "notes",
        detail: descriptions.git.subcommands.notes,
    },
    {
        name: "pull",
        detail: descriptions.git.subcommands.pull,
        provider: combine([
            longFlag("rebase"),
            longFlag("no-rebase"),
            staticSuggestionsProvider(commonMergeOptions),
            staticSuggestionsProvider(fetchOptions),
        ]),
    },
    {
        name: "push",
        detail: descriptions.git.subcommands.push,
        provider: staticSuggestionsProvider(pushOptions),
    },
    {
        name: "rebase",
        detail: descriptions.git.subcommands.rebase,
    },
    {
        name: "reset",
        detail: descriptions.git.subcommands.reset,
        provider: staticSuggestionsProvider(resetOptions),
    },
    {
        name: "revert",
        detail: descriptions.git.subcommands.revert,
    },
    {
        name: "rm",
        detail: descriptions.git.subcommands.rm,
    },
    {
        name: "shortlog",
        detail: descriptions.git.subcommands.shortlog,
    },
    {
        name: "show",
        detail: descriptions.git.subcommands.show,
    },
    {
        name: "stash",
        detail: descriptions.git.subcommands.stash,
        provider: staticSuggestionsProvider(stashOptions),
    },
    {
        name: "status",
        detail: descriptions.git.subcommands.status,
        provider: staticSuggestionsProvider(statusOptions),
    },
    {
        name: "submodule",
        detail: descriptions.git.subcommands.submodule,
    },
    {
        name: "tag",
        detail: descriptions.git.subcommands.tag,
    },
    {
        name: "worktree",
        detail: descriptions.git.subcommands.worktree,
    },
];

const commands = once(async(): Promise<SubcommandConfig[]> => {
    const text = await executeCommand("git", ["help", "-a"], homeDirectory);
    const matches: string[] | null = text.match(/  ([\-a-zA-Z0-9]+)/gm);

    if (matches) {
        const suggestions = matches
            .filter(match => match.indexOf("--") === -1)
            .map(match => {
                const name = match.trim();
                const data = find(commandsData, {name});

                return {
                    name,
                    detail: data ? data.detail : "",
                    provider: data ? data.provider : emptyProvider,
                };
            });

        return sortBy(suggestions, suggestion => !suggestion.detail);
    }

    return [];
});

const aliases = once(async(): Promise<SubcommandConfig[]> => {
    const aliasList = await Git.aliases(homeDirectory);
    return aliasList.map(({ name, value }) => {
        let result: SubcommandConfig = {
            name: name,
        };

        const expandedAliasConfig = find(commandsData, data => data.name === value);
        if (expandedAliasConfig && expandedAliasConfig.provider) {
            result.provider = expandedAliasConfig.provider;
        }

        return result;
    });
});

PluginManager.registerAutocompletionProvider("git", async context => {
    const allCommands = [...(await aliases()), ...(await commands())];
    return commandWithSubcommands(allCommands)(context);
});


================================================
FILE: src/plugins/completion/Grep.ts
================================================
import {PluginManager} from "../../PluginManager";
import {
    longFlag, longAndShortFlag, mapSuggestions, anyFilesSuggestionsProvider,
    anyFilesSuggestions, directoriesSuggestions, provide,
} from "../completion_utils/Common";
import {combine} from "../completion_utils/Combine";
import {mapObject} from "../../utils/Common";

// Grep option suggestions based on linux  man file:
// http://linux.die.net/man/1/grep
const baseOptions = combine(mapObject(
    {
        // Generic Program Information
        "version": {
            short: "V",
            description: `Print the version number of grep to standard error.`,
        },
        // Matcher Selection
        "basic-regexp": {
            short: "G",
            description: `Interpret PATTERN as a basic regular expression. This is the default.`,
        },
        "perl-regexp": {
            short: "P",
            description: `Interpret PATTERN as a Perl regular expression.`,
        },
        // Matching Control
        "regexp": {
            short: "e",
            description: `Print the byte offset within the input file before each line of output`,
        },
        "file=": {
            short: "",
            description: `Obtain  patterns  from  FILE, one per line`,
        },
        "ignore-case": {
            short: "i",
            description: `Ignore case distinctions in both the PATTERN and the input files`,
        },
        "invert-match": {
            short: "v",
            description: `Invert the sense of matching, to select non-matching lines`,
        },
        "word-regexp": {
            short: "w",
            description: `Select only those  lines  containing  matches  that  form  whole words`,
        },
        "line-regexp": {
            short: "x",
            description: `Select only those matches that exactly match the whole line`,
        },
        // General Output Control
        "count": {
            short: "c",
            description: `Suppress normal output; instead print a count of matching lines for each input
                file. With the -v, --invert-match option (see below), count non-matching lines.`,
        },
        "color=": {
            short: "",
            description: `Surround the matching string with the marker find in GREP_COLOR environment variable`,
        },
        "files-without-match": {
            short: "L",
            description: `Suppress normal output; instead print the name of each input file from which no
            output would normally have been printed. The scanning will stop on the first match`,
        },
        "files-with-match": {
            short: "l",
            description: `Suppress normal output; instead print the name of each input file from which output
                would normally have been printed. The scanning will stop on the first match.`,
        },
        "max-count": {
            short: "m",
            description: `Stop reading a file after NUM matching lines. If the input is standard input from a
                regular file, and NUM matching lines are output, grep ensures that the standard input is positioned
                to just after the last matching line before exiting, regardless of the presence of trailing context
                lines.`,
        },
        "only-matching": {
            short: "o",
            description: `Print only the matched (non-empty) parts of a matching line, with each such part on a
                separate output line`,
        },
        "quiet": {
            short: "q",
            description: `Quiet; do not write anything to standard output. Exit immediately with zero status if
                any match is found, even if an error was detected.`,
        },
        "silent": {
            short: "",
            description: `Quiet; do not write anything to standard output. Exit immediately with zero status if
                any match is found, even if an error was detected.`,
        },
        "no-messages": {
            short: "s",
            description: `Suppress error messages about nonexistent or unreadable files`,
        },
        // Output Line Prefix Control
        "byte-offset": {
            short: "b",
            description: `Print the byte offset within the input file before each line of output.`,
        },
        "with-filename": {
            short: "H",
            description: `Quiet; do not write anything to standard output. Exit immediately with zero status
                if any match is found, even if an error was detected.`,
        },
        "no-filename": {
            short: "h",
            description: `Suppress the prefixing of file names on output. This is the default when there is
                only one file (or only standard input) to search.`,
        },
        "label=": {
            short: "",
            description: `Display input actually coming from standard input as input coming from file LABEL.`,
        },
        "line-number": {
            short: "n",
            description: `Prefix each line of output with the 1-based line number within its input file.`,
        },
        "initial-tab": {
            short: "T",
            description: `Make sure that the first character of actual line content lies on a tab stop, so
                that the alignment of tabs looks normal.`,
        },
        "unix-byte-offsets": {
            short: "u",
            description: `Report Unix-style byte offsets. This  switch causes grep to report byte offsets
                as if the file were Unix-style text file, i.e. with CR characters stripped off`,
        },
        "null": {
            short: "Z",
            description: `Output a zero byte (the ASCII NUL character) instead of the character that normally
                follows a file name`,
        },
        // Context Line Control
        "after-context": {
            short: "A",
            description: `Print NUM lines of trailing context after matching lines. Places a line containing a
                group separator (--) between contiguous groups of matches.`,
        },
        "before-context": {
            short: "B",
            description: `Print NUM lines of leading context before matching lines. Places a line containing
                a group separator (--) between contiguous groups of matches.`,
        },
        "context": {
            short: "C",
            description: `Print NUM lines of output context. Places a line containing a group separator (--)
                between contiguous groups of matches.`,
        },
        // File and Directory Selection
        "text": {
            short: "a",
            description: `Process a binary file as if it were text, equivalent to --binary-files=text`,
        },
        "binary-files=": {
            short: "r",
            description: `Read all files under each directory, recursively; this is equivalent to the
                -d recurse option`,
        },
        "devices=": {
            short: "D",
            description: `If an input file is a device, FIFO or socket, use ACTION to process  it`,
        },
        "directories=": {
            short: "d",
            description: `If an input file is a directory, use ACTION to process it. By default, ACTION is
                read, which means that directories are read just as if they were ordinary files.`,
        },
        "exclude=": {
            short: "",
            description: `Recurse in directories skip file matching PATTERN.`,
        },
        "exclude-from=": {
            short: "",
            description: `Skip files whose base name matches any of the file-name globs read from FILE (using
                wildcard matching as described under --exclude).`,
        },
        "exclude-dir=": {
            short: "",
            description: `Exclude directories matching the pattern DIR from recursive searches.`,
        },
        "include=": {
            short: "",
            description: `Search only files whose base name matches GLOB (using wildcard matching as described
                under --exclude).`,
        },
        "recursive": {
            short: "r",
            description: `Read all files under each directory, recursively; this is equivalent to the -d
                recurse option.`,
        },
        "line-buffered": {
            short: "",
            description: `Use line buffering on output. This can cause a performance penalty.`,
        },
        "binary": {
            short: "U",
            description: `Treat the file(s) as binary`,
        },
        "null-data": {
            short: "z",
            description: `Treat the input as a set of lines, each terminated by a zero byte (the ASCII NUL
                character) instead of a newline.`,
        },
    },
    (option, info) => {
        if (info.short) {
            return mapSuggestions(
                longAndShortFlag(option, info.short),
                suggestion => ({...suggestion, description: info.description}),
            );
        } else {
            return mapSuggestions(
                longFlag(option),
                suggestion => ({...suggestion, description: info.description}),
            );
        }
    },
));

const extendedRegexOption = combine([
    mapSuggestions(
        longAndShortFlag("extended-regexp", "E"),
        suggestion => ({
            ...suggestion,
            description: `Interpret <pattern> (defined using --regexp=<pattern> as an extended regular expression`,
        })),
]);

const fixedStringsOption = combine([
    mapSuggestions(
        longAndShortFlag("fixed-strings", "F"),
        suggestion => ({
            ...suggestion,
            description: `Interpret <pattern> (defined using --regexp=<pattern>) as a list of fixed strings, separated by new-lines lines, any of which is to be matched`,
        })),
]);

const binaryFilesValues = [
    {
        flag: "binary-files",
        displayValue: "binary",
        description: `(default) Outputs either a one-line message saying that a binary file matches or
            no message if there is no match`,
    },
    {
        flag: "binary-files",
        displayValue: "without-match",
        description: `Assumes that a binary file does not match.`,
    },
    {
        flag: "binary-files",
        displayValue: "text",
        description: `Processes a binary file as if it were text.`,
    }];

const devicesValues = [
    {
        flag: "devices",
        displayValue: "read",
        description: `(default) Devices are read just as if they were ordinary files`,
    },
    {
        flag: "devices",
        displayValue: "skip",
        description: `Devices are silently skipped`,
    }];

const colorValues = [
    {
        flag: "color",
        displayValue: "never",
        description: `Never highlight the matching pattern`,
    },
    {
        flag: "color",
        displayValue: "always",
        description: `Always highlight the matching pattern`,
    },
    {
        flag: "color",
        displayValue: "auto",
        description: `Auto highlight the matching pattern`,
    }];

const directoriesValues = [
    {
        flag: "directories",
        displayValue: "read",
        description: `(Default) Directories are read just as if they were ordinary files.`,
    },
    {
        flag: "directories",
        displayValue: "skip",
        description: `Directories are silently skipped.`,
    },
    {
        flag: "directories",
        displayValue: "recurse",
        description: `grep reads all files under each directory, recursively;
            this is equivalent to the -r option.`,
    }];

const fixedValueSuggestions = provide(async context => {
    const token = context.argument.value;
    let optionValues: any[] = [];

    if (token.startsWith("--binary-files=")) {
        optionValues = binaryFilesValues;
    } else if (token.startsWith("--devices=")) {
        optionValues = devicesValues;
    } else if (token.startsWith("--color=")) {
        optionValues = colorValues;
    } else if (token.startsWith("--directories=")) {
        optionValues = directoriesValues;
    } else {
        return [];
    }
    return optionValues.map(item => ({
        label: "--" + item.flag + "=" + item.displayValue,
        description: item.description,
    }));
});

const fileValueSuggestions = provide(async context => {
    const tokenValue = "--file=";
    const token = context.argument.value;

    if (token.startsWith(tokenValue)) {
        const workingDirectory = context.environment.pwd;
        const optionValue = token.slice(tokenValue.length);
        const fileSuggestions = await anyFilesSuggestions(optionValue, workingDirectory);
        return fileSuggestions.map(item =>
            ({label: tokenValue + item.label}));
    } else {
        return [];
    }
});

const excludeFromSuggestions = provide(async context => {
    const tokenValue = "--exclude-from=";
    const token = context.argument.value;

    if (token.startsWith(tokenValue)) {
        const workingDirectory = context.environment.pwd;
        const optionValue = token.slice(tokenValue.length);
        const fileSuggestions = await anyFilesSuggestions(optionValue, workingDirectory);
        return fileSuggestions.map(item => ({
            label: tokenValue + item.label,
        }));
    } else {
        return [];
    }
});

const excludeDirSuggestions = provide(async context => {
    const tokenValue = "--exclude-dir=";
    const token = context.argument.value;

    if (token.startsWith(tokenValue)) {
        const workingDirectory = context.environment.pwd;
        const optionValue = token.slice(tokenValue.length);
        const directorySuggestions = await directoriesSuggestions(optionValue, workingDirectory);
        return directorySuggestions.map(item =>
            ({
                label: tokenValue + item.label,
            }));
    } else {
        return [];
    }
});

const commonOptions = combine([baseOptions, fixedValueSuggestions, fileValueSuggestions,
    anyFilesSuggestionsProvider, excludeFromSuggestions, excludeDirSuggestions]);

const grepOptions = combine([commonOptions, fixedStringsOption, extendedRegexOption]);

const eGrepOptions = combine([commonOptions, extendedRegexOption]);

const fGrepOptions = combine([commonOptions, fixedStringsOption]);

PluginManager.registerAutocompletionProvider("grep", combine([grepOptions]));

PluginManager.registerAutocompletionProvider("egrep", combine([eGrepOptions]));

PluginManager.registerAutocompletionProvider("fgrep", combine([fGrepOptions]));


================================================
FILE: src/plugins/completion/History.ts
================================================
import {HistoryRecord} from "../../services/HistoryService";
import {scan} from "../../shell/Scanner";
import {isAbsolute} from "path";
import {services} from "../../services/index";
import {HistoryTrie} from "../../utils/HistoryTrie";
import {Suggestion} from "../completion_utils/Common";

function cdIntoRelativePathFilter(record: HistoryRecord, pwd: string): boolean {
    if (record.directory === pwd) {
        return true;
    }

    const tokens = scan(record.expandedCommand);

    if (tokens[0].value !== "cd") {
        return true;
    }

    const directoryToken = tokens[1];

    if (directoryToken && isAbsolute(directoryToken.value)) {
        return true;
    }

    return false;
}

const historyTrie = new HistoryTrie();
services.history.all.forEach(record => historyTrie.add(record.command));
services.history.onNewRecord.subscribe(record => historyTrie.add(record.command));

export function getHistorySuggestions(input: string, pwd: string): Suggestion[] {
    const trieSuggestions = historyTrie.getContinuationsFor(input).map(continuation => ({
        label: continuation.value,
        description: `×${continuation.occurrences}`,
    }));

    if (trieSuggestions.length) {
        return trieSuggestions;
    } else {
        return services.history.all
            .filter(record => cdIntoRelativePathFilter(record, pwd))
            .map(record => record.command)
            .filter(command => command.toLowerCase().includes(input.toLowerCase()))
            .map(command => ({
                label: command.trim(),
            }))
            .reverse();
    }
}


================================================
FILE: src/plugins/completion/Ln.ts
================================================
import {PluginManager} from "../../PluginManager";
import {anyFilesSuggestionsProvider} from "../completion_utils/Common";
import {combine} from "../completion_utils/Combine";
import {manPageOptions} from "../../utils/ManPages";

const combinedOptions = combine([anyFilesSuggestionsProvider, manPageOptions("ln")]);
PluginManager.registerAutocompletionProvider("ln", combinedOptions);
PluginManager.registerAutocompletionProvider("link", combinedOptions);


================================================
FILE: src/plugins/completion/Locate.ts
================================================
import {PluginManager} from "../../PluginManager";
import {manPageOptions} from "../../utils/ManPages";

PluginManager.registerAutocompletionProvider("locate", manPageOptions("locate"));


================================================
FILE: src/plugins/completion/Ls.ts
================================================
import {PluginManager} from "../../PluginManager";
import {directoriesSuggestionsProvider} from "../completion_utils/Common";
import {combine} from "../completion_utils/Combine";
import {manPageOptions} from "../../utils/ManPages";

const lsOptions = manPageOptions("ls");

PluginManager.registerAutocompletionProvider("ls", combine([directoriesSuggestionsProvider, lsOptions]));


================================================
FILE: src/plugins/completion/Mkdir.ts
================================================
import {PluginManager} from "../../PluginManager";
import {directoriesSuggestionsProvider} from "../completion_utils/Common";
import {combine} from "../completion_utils/Combine";
import {manPageOptions} from "../../utils/ManPages";

PluginManager.registerAutocompletionProvider("mkdir", combine([manPageOptions("mkdir"), directoriesSuggestionsProvider]));


================================================
FILE: src/plugins/completion/Mv.ts
================================================
import {PluginManager} from "../../PluginManager";
import {anyFilesSuggestionsProvider} from "../completion_utils/Common";
import {combine} from "../completion_utils/Combine";
import {manPageOptions} from "../../utils/ManPages";

PluginManager.registerAutocompletionProvider("mv", combine([manPageOptions("mv"), anyFilesSuggestionsProvider]));


================================================
FILE: src/plugins/completion/NPM.ts
================================================
import * as Path from "path";
import {commandWithSubcommands} from "../completion_utils/Common";
import {io, mapObject} from "../../utils/Common";
import {PluginManager} from "../../PluginManager";
import {AutocompletionContext} from "../../Interfaces";

const npmCommandConfig = [
    {
        name: "access",
        detail: "Set access level on published packages",
    },
    {
        name: "adduser",
        detail: "Add a registry user account",
    },
    {
        name: "bin",
        detail: "Display npm bin folder",
    },
    {
        name: "bugs",
        detail: "Bugs for a package in a web browser maybe",
    },
    {
        name: "build",
        detail: "Build a package",
    },
    {
        name: "bundle",
        detail: "REMOVED",
    },
    {
        name: "cache",
        detail: "Manipulates packages cache",
    },
    {
        name: "completion",
        detail: "Tab Completion for npm",
    },
    {
        name: "config",
        detail: "Manage the npm configuration files",
    },
    {
        name: "dedupe",
        detail: "Reduce duplication",
    },
    {
        name: "deprecate",
        detail: "Deprecate a version of a package",
    },
    {
        name: "dist-tag",
        detail: "Modify package distribution tags",
    },
    {
        name: "docs",
        detail: "Docs for a package in a web browser maybe",
    },
    {
        name: "edit",
        detail: "Edit an installed package",
    },
    {
        name: "explore",
        detail: "Browse an installed package",
    },
    {
        name: "help",
        detail: "Get help on npm",
    },
    {
        name: "help-search",
        detail: "Search npm help documentation",
    },
    {
        name: "init",
        detail: "Interactively create a package.json file",
    },
    {
        name: "install",
        detail: "Install a package",
    },
    {
        name: "install-test",
        detail: "",
    },
    {
        name: "link",
        detail: "Symlink a package folder",
    },
    {
        name: "logout",
        detail: "Log out of the registry",
    },
    {
        name: "ls",
        detail: "List installed packages",
    },
    {
        name: "npm",
        detail: "javascript package manager",
    },
    {
        name: "outdated",
        detail: "Check for outdated packages",
    },
    {
        name: "owner",
        detail: "Manage package owners",
    },
    {
        name: "pack",
        detail: "Create a tarball from a package",
    },
    {
        name: "ping",
        detail: "Ping npm registry",
    },
    {
        name: "prefix",
        detail: "Display prefix",
    },
    {
        name: "prune",
        detail: "Remove extraneous packages",
    },
    {
        name: "publish",
        detail: "Publish a package",
    },
    {
        name: "rebuild",
        detail: "Rebuild a package",
    },
    {
        name: "repo",
        detail: "Open package repository page in the browser",
    },
    {
        name: "restart",
        detail: "Restart a package",
    },
    {
        name: "root",
        detail: "Display npm root",
    },
    {
        name: "run",
        detail: "Run arbitrary package scripts",
        provider: async (context: AutocompletionContext) => {
            const packageFilePath = Path.join(context.environment.pwd, "package.json");
            if (await io.fileExists(packageFilePath)) {
                const parsed = JSON.parse(await io.readFile(packageFilePath)).scripts || {};
                return mapObject(parsed, (key: string, value: string) => ({
                    label: key,
                    detail: value,
                }));
            } else {
                return [];
            }
        },
    },
    {
        name: "search",
        detail: "Search for packages",
    },
    {
        name: "shrinkwrap",
        detail: "Lock down dependency versions",
    },
    {
        name: "star",
        detail: "Mark your favorite packages",
    },
    {
        name: "stars",
        detail: "View packages marked as favorites",
    },
    {
        name: "start",
        detail: "Start a package",
    },
    {
        name: "stop",
        detail: "Stop a package",
    },
    {
        name: "tag",
        detail: "Tag a published version",
    },
    {
        name: "team",
        detail: "Manage organization teams and team memberships",
    },
    {
        name: "test",
        detail: "Test a package",
    },
    {
        name: "uninstall",
        detail: "Remove a package",
    },
    {
        name: "unpublish",
        detail: "Remove a package from the registry",
    },
    {
        name: "update",
        detail: "Update a package",
    },
    {
        name: "version",
        detail: "Bump a package version",
    },
    {
        name: "view",
        detail: "View registry info",
    },
    {
        name: "whoami",
        detail: "Display npm username",
    },
];

PluginManager.registerAutocompletionProvider("npm", commandWithSubcommands(npmCommandConfig));


================================================
FILE: src/plugins/completion/Ps.ts
================================================
import {PluginManager} from "../../PluginManager";
import {combine} from "../completion_utils/Combine";
import {provide, Suggestion} from "../completion_utils/Common";
import {AutocompletionContext, AutocompletionProvider} from "../../Interfaces";
import * as Process from "../../utils/Process";
import {find} from "lodash";

// ps option suggestions based on linux  man file:
// http://linux.die.net/man/1/ps
interface ShortFlagItem {
    flag: string;
    detail: string;
}

const shortOptions: ShortFlagItem[] = [
    {
        flag: "C",
        detail: `Select by command name.`,
    },
    {
        flag: "G",
        detail: `Select by real group ID (RGID) or name.`,
    },
    {
        flag: "U",
        detail: `Select by effective user ID (EUID) or name.`,
    },
];

interface TokenInfo {
    params: string[];
    start: string;
}

const argInfo = (context: AutocompletionContext): TokenInfo => {
    const token: string = context.argument.value;
    const flag = token.substring(0, token.indexOf("=") + 1);
    let params: string[] = [];
    let start = flag;
    if (token.includes(",")) {
        params = token.substring(start.length, token.lastIndexOf(",")).split(",");
        start = token.substring(0, token.lastIndexOf(",") + 1);
    }
    return <TokenInfo>{params: params, start: start};
};

interface LongFlagItem {
    flag: string;
    detail: string;
    provider: AutocompletionProvider;
}

const realUserSuggestions = provide(async context => {
    const arg = argInfo(context);
    const users = await Process.users();
    return users
        .filter(i => !arg.params.includes(i.ruser))
        .map(i =>
            ({
                label: i.ruser, displayValue: i.ruser,
                detail: `User '${i.ruser}' with id '${i.ruserid}'`,
            }));
});

const effectiveUserSuggestions = provide(async context => {
    const arg = argInfo(context);
    const users = await Process.users();
    return users
        .filter(i => !arg.params.includes(i.euser))
        .map(i =>
            ({
                label: i.euser, displayValue: i.euser,
                detail: `User '${i.euser}' with id '${i.euserid}'`,
            }));
});

const effectiveGroupSuggestions = provide(async context => {
    const arg = argInfo(context);
    const groups = await Process.groups();
    return groups
        .filter(i => !arg.params.includes(i.egroup))
        .map(i =>
            ({
                label: i.egroup, displayValue: i.egroup,
                detail: `Group '${i.egroup}' with id '${i.egroupid}'`,
            }));
});

const realGroupSuggestions = provide(async context => {
    const arg = argInfo(context);
    const groups = await Process.groups();
    return groups
        .filter(i => !arg.params.includes(i.rgroup))
        .map(i =>
            ({
                label: i.rgroup, displayValue: i.rgroup,
                detail: `Group '${i.rgroup}' with id '${i.rgroupid}'`,
            }));
});

const terminalSuggestions = provide(async context => {
    const arg = argInfo(context);
    const terminals = await Process.terminals();
    return terminals
        .filter(i => !arg.params.includes(i.name))
        .map(i => ({
            label: i.name, displayValue: i.name,
            detail: `Terminal '${i.name}' with ruser '${i.ruser}'`,
        }));
});

const processSuggestions = provide(async context => {
    const arg = argInfo(context);
    const processes = await Process.processes();
    return processes
        .filter(i => !arg.params.includes(i.pid))
        .map(i => ({
            label: i.pid, displayValue: i.pid,
            detail: `Process with command '${i.cmd.slice(0, 25)}'
                     and ruser '${i.ruser}'`,
        }));
});

const sessionSuggestions = provide(async context => {
    const arg = argInfo(context);
    const sessions = await Process.sessions();
    return sessions
        .filter(i => !arg.params.includes(i.sid))
        .map(i => ({
            label: i.sid, displayValue: i.sid,
            detail: `Session '${i.sid}' with ruser '${i.ruser} and
                     rgroup '${i.rgroup}'`,
        }));
});

const longOptions: LongFlagItem[] = [
    {
        flag: "user=",
        detail: `Select by effective user ID (EUID) or name. Identical to -u and U.`,
        provider: effectiveUserSuggestions,
    },
    {
        flag: "User=",
        detail: `Select by real user ID (RUID) or name. Identical to -U.`,
        provider: realUserSuggestions,
    },
    {
        flag: "group=",
        detail: `Select by effective group ID (EGID) or name.`,
        provider: effectiveGroupSuggestions,
    },
    {
        flag: "Group=",
        detail: `Select by real group ID (RGID) or name. Identical to -G.`,
        provider: realGroupSuggestions,
    },
    {
        flag: "tty=",
        detail: `selects the processes associated with the terminals given
                 in ttylist. Identical to -T.`,
        provider: terminalSuggestions,
    },
    {
        flag: "pid=",
        detail: `Select by process ID. Identical to -p and p.`,
        provider: processSuggestions,
    },
    {
        flag: "sid=",
        detail: `Select by session ID. Identical to -s.`,
        provider: sessionSuggestions,
    },
];

const psOptions = provide(async context => {
    let suggestions: Suggestion[] = [];
    const token: string = context.argument.value;

    if (!token.includes("=")) {
        const shortOptSuggestions = shortOptions.map(s =>
                <Suggestion>{label: "-" + s.flag, detail: s.detail});
        const longOptSuggestions = longOptions.map(l =>
                <Suggestion>{label: "--" + l.flag, detail: l.detail});
        suggestions = [...shortOptSuggestions, ...longOptSuggestions];
    }
    return suggestions;
});

const psLongOptionValues = provide(async context => {
    let suggestions: Suggestion[] = [];
    const token: string = context.argument.value;

    if (token.startsWith("--") && token.includes("=")) {
        const flag = token.slice(2, token.indexOf("=") + 1);
        const longOption = find(longOptions, {flag});
        suggestions = longOption ? await longOption.provider(context) : [];
    }
    return suggestions;
});

PluginManager.registerAutocompletionProvider("ps", combine([psOptions, psLongOptionValues]));


================================================
FILE: src/plugins/completion/Pwd.ts
================================================
import {PluginManager} from "../../PluginManager";
import {manPageOptions} from "../../utils/ManPages";

PluginManager.registerAutocompletionProvider("pwd", manPageOptions("pwd"));


================================================
FILE: src/plugins/completion/Rails.ts
================================================
import {commandWithSubcommands} from "../completion_utils/Common";
import {PluginManager} from "../../PluginManager";

const railsCommandConfig = [
    {
        name: "runner",
        description: "Run a piece of code in the application environment",
    },
    {
        name: "console",
        description: "Start the Rails console",
    },
    {
        name: "server",
        description: "Start the Rails server",
    },
    {
        name: "generate",
        description: "Generate new code'g')",
    },
    {
        name: "destroy",
        description: "generate",
    },
    {
        name: "dbconsole",
        description: "Start a console for the Rails database",
    },
    {
        name: "new",
        description: "Create a new Rails application",
    },
    {
        name: "plugin new",
        description: "Generates skeleton for developing a Rails plugin",
    },
];

PluginManager.registerAutocompletionProvider("rails", commandWithSubcommands(railsCommandConfig));


================================================
FILE: src/plugins/completion/Rake.ts
================================================
import {PluginManager} from "../../PluginManager";
import {directoriesSuggestionsProvider} from "../completion_utils/Common";
import {combine} from "../completion_utils/Combine";
import {manPageOptions} from "../../utils/ManPages";

const rakeOptions = manPageOptions("rake", "OPTIONS");

PluginManager.registerAutocompletionProvider("rake", combine([directoriesSuggestionsProvider, rakeOptions]));


================================================
FILE: src/plugins/completion/Rm.ts
================================================
import {PluginManager} from "../../PluginManager";
import {anyFilesSuggestionsProvider} from "../completion_utils/Common";
import {combine} from "../completion_utils/Combine";
import {manPageOptions} from "../../utils/ManPages";

PluginManager.registerAutocompletionProvider("rm", combine([manPageOptions("rm"), anyFilesSuggestionsProvider]));


================================================
FILE: src/plugins/completion/Scp.ts
================================================
import {PluginManager} from "../../PluginManager";
import {directoriesSuggestionsProvider} from "../completion_utils/Common";
import {combine} from "../completion_utils/Combine";
import {manPageOptions} from "../../utils/ManPages";

const scpOptions = manPageOptions("scp");

PluginManager.registerAutocompletionProvider("scp", combine([directoriesSuggestionsProvider, scpOptions]));


================================================
FILE: src/plugins/completion/Shutdown.ts
================================================
import {PluginManager} from "../../PluginManager";
import {manPageOptions} from "../../utils/ManPages";

PluginManager.registerAutocompletionProvider("shutdown", manPageOptions("shutdown"));


================================================
FILE: src/plugins/completion/Tail.ts
================================================
import {PluginManager} from "../../PluginManager";
import {directoriesSuggestionsProvider} from "../completion_utils/Common";
import {combine} from "../completion_utils/Combine";
import {manPageOptions} from "../../utils/ManPages";

const tailOptions = manPageOptions("tail");

PluginManager.registerAutocompletionProvider("tail", combine([directoriesSuggestionsProvider, tailOptions]));


================================================
FILE: src/plugins/completion/Top.ts
================================================
import {PluginManager} from "../../PluginManager";
import {shortFlag, mapSuggestions} from "../completion_utils/Common";
import {combine} from "../completion_utils/Combine";
import {mapObject} from "../../utils/Common";

const options = combine(mapObject(
    {
        b: {
            short: "Batch mode operation",
            long: "Starts  top  in  ’Batch  mode’,  which could be useful for sending\
               output from top to other programs or to a file.  In this mode, top\
               will  not  accept input and runs until the iterations limit you’ve\
               set with the ’-n’ command-line option or until killed.",
        },

        c: {
            short: "Command line/Program name toggle",
            long: "Starts top with the last remembered ’c’ state reversed.  Thus,  if\
                top was displaying command lines, now that field will show program\
                names, and visa  versa.   See  the  ’c’  interactive  command  for\
                additional information.",
        },

        d: {
            short: "Delay time interval as: -d ss.tt (seconds.tenths)",
            long: "Specifies  the  delay  between  screen  updates, and overrides the\
                corresponding value in one’s personal configuration  file  or  the\
                startup  default.   Later  this can be changed with the ’d’ or ’s’\
                interactive commands.\
\
                Fractional seconds are honored,  but  a  negative  number  is  not\
                allowed.   In  all  cases, however, such changes are prohibited if\
                top is running in ’Secure mode’, except for root (unless  the  ’s’\
                command-line  option  was  used).   For  additional information on\
                ’Secure mode’ see topic 5a. SYSTEM Configuration File.",
        },

        h: {
            short: "Help",
            long: "Show library version and the usage prompt, then quit.",
        },

        H: {
            short: "Threads toggle",
            long: "Starts top with the last remembered ’H’ state reversed.  When this\
                toggle   is   On,   all  individual  threads  will  be  displayed.\
                Otherwise, top displays a summation of all threads in a process.",
        },

        i: {
            short: "Idle Processes toggle", long: "Starts top with the last remembered ’i’ state reversed.  When this\
                toggle  is  Off,  tasks  that  are  idled  or  zombied will not be\
                displayed.",
        },

        n: {
            short: "Number of iterations limit as: -n number",
            long: "Specifies the maximum number of iterations, or frames, top  should\
                produce before ending.",
        },

        u: {
            short: "Monitor by user as:  -u somebody",
            long: "Monitor only processes with an effective UID or user name matching\
                that given.",
        },

        U: {
            short: "Monitor by user as:  -U somebody",
            long: "Monitor only processes with a  UID  or  user  name  matching  that\
                given.   This matches real, effective, saved, and filesystem UIDs.",
        },

        p: {
            short: "Monitor PIDs as:  -pN1 -pN2 ...  or  -pN1, N2 [,...]",
            long: "Monitor only processes with specified process  IDs.   This  option\
                can  be given up to 20 times, or you can provide a comma delimited\
                list  with  up  to  20  pids.   Co-mingling  both  approaches   is\
                permitted.\
\
                This is a command-line option only.  And should you wish to return\
                to normal operation, it is not necessary to quit and  and  restart\
                top  --  just issue the ’=’ interactive command.",
        },

        s: {
            short: "Secure mode operation",
            long: "Starts  top  with secure mode forced, even for root.  This mode is\
                far better controlled through the system configuration  file  (see\
                topic 5. FILES).",
        },

        S: {
            short: "Cumulative time mode toggle",
            long: "Starts  top  with  the  last  remembered ’S’ state reversed.  When\
                ’Cumulative mode’ is On, each process is listed with the cpu  time\
                that  it and its dead children have used.  See the ’S’ interactive\
                command for additional information regarding this mode.",
        },

        v: {
            short: "Version",
            long: "Show library version and the usage prompt, then quit.",
        },
    },
    (option, descriptions) => mapSuggestions(shortFlag(option), suggestion => ({...suggestion, detail: descriptions.short})),
));


PluginManager.registerAutocompletionProvider("top", options);


================================================
FILE: src/plugins/completion/Vagrant.ts
================================================
import {PluginManager} from "../../PluginManager";
import {linedOutputOf} from "../../PTY";
import {commandWithSubcommands, emptyProvider, SubcommandConfig} from "../completion_utils/Common";
import {once} from "lodash";
import {homeDirectory} from "../../utils/Common";

const vargrantCommandConfig = once(async() => {
    try {
        return (await linedOutputOf("vagrant", ["list-commands"], homeDirectory))
            .map(line => {
                const matches = line.match(/([\-a-zA-Z0-9]+)  /);

                if (matches) {
                    const name = matches[1];
                    const description = line.replace(matches[1], "").trim();

                    return {
                        name,
                        description,
                        provider: emptyProvider,
                    };
                }
            })
            .filter(suggestion => suggestion) as SubcommandConfig[];
    } catch (e) {
        return [] as SubcommandConfig[];
    }
});

PluginManager.registerAutocompletionProvider("vagrant", async (context) => {
    return commandWithSubcommands(await vargrantCommandConfig())(context);
});


================================================
FILE: src/plugins/completion_utils/Button.tsx
================================================
import * as React from "react";
import {colors} from "../../views/css/colors";

const buttonStyles = (color: string) => ({
  borderColor: color,
  borderStyle: "solid",
  borderRadius: "4px",
  borderWidth: "1px",
  padding: "2px",
  color: color,
  WebkitUserSelect: "none",
  fontSize: "10px",
  margin: "4px",
  cursor: "pointer",
});

type ButtonProps = {
  onClick: () => void;
  children: string;
  color?: string;
};

export const Button = ({ onClick, children, color = colors.blue }: ButtonProps) => <span
  style={buttonStyles(color)}
  onClick={onClick}
>{children}</span>;


================================================
FILE: src/plugins/completion_utils/Combine.ts
================================================
import * as _ from "lodash";
import {AutocompletionContext, AutocompletionProvider} from "../../Interfaces";
import {Suggestion} from "./Common";

export const combine = (providers: AutocompletionProvider[]): AutocompletionProvider => {
    return async(context: AutocompletionContext): Promise<Suggestion[]> => {
        return _.flatten(await Promise.all(providers.map(provider => provider(context))));
    };
};


================================================
FILE: src/plugins/completion_utils/Common.ts
================================================
import {directoryName, escapeFilePath, io, resolveDirectory, userFriendlyPath} from "../../utils/Common";
import {AutocompletionContext, AutocompletionProvider, FileInfo} from "../../Interfaces";
import {combine} from "./Combine";
import * as modeToPermissions from "mode-to-permissions";
import * as Path from "path";
import * as _ from "lodash";

// Copy of monaco.languages.CompletionItem, but with optional `kind`.
export interface Suggestion {
    /**
     * The label of this completion item. By default
     * this is also the text that is inserted when selecting
     * this completion.
     */
    label: string;
    /**
     * The kind of this completion item. Based on the kind
     * an icon is chosen by the editor.
     */
    kind?: monaco.languages.CompletionItemKind;
    /**
     * A human-readable string with additional information
     * about this item, like type or symbol information.
     */
    detail?: string;
    /**
     * A human-readable string that represents a doc-comment.
     */
    documentation?: string;
    /**
     * A string that should be used when comparing this item
     * with other items. When `falsy` the [label](#CompletionItem.label)
     * is used.
     */
    sortText?: string;
    /**
     * A string that should be used when filtering a set of
     * completion items. When `falsy` the [label](#CompletionItem.label)
     * is used.
     */
    filterText?: string;
    /**
     * A string or snippet that should be inserted in a document when selecting
     * this completion. When `falsy` the [label](#CompletionItem.label)
     * is used.
     */
    insertText?: string | monaco.languages.SnippetString;
    /**
     * A range of text that should be replaced by this completion item.
     *
     * Defaults to a range from the start of the [current word](#TextDocument.getWordRangeAtPosition) to the
     * current position.
     *
     * *Note:* The range must be a [single line](#Range.isSingleLine) and it must
     * [contain](#Range.contains) the position at which completion has been [requested](#CompletionItemProvider.provideCompletionItems).
     */
    range?: monaco.Range;
    /**
     * @deprecated **Deprecated** in favor of `CompletionItem.insertText` and `CompletionItem.range`.
     *
     * ~~An [edit](#TextEdit) which is applied to a document when selecting
     * this completion. When an edit is provided the value of
     * [insertText](#CompletionItem.insertText) is ignored.~~
     *
     * ~~The [range](#Range) of the edit must be single-line and on the same
     * line completions were [requested](#CompletionItemProvider.provideCompletionItems) at.~~
     */
    textEdit?: monaco.editor.ISingleEditOperation;
}

export function provide(provider: AutocompletionProvider): AutocompletionProvider {
    return provider;
}

export const unique = (provider: AutocompletionProvider) => provide(async context => {
    const suggestions = await provider(context);
    return suggestions.filter(suggestion => !context.argument.command.hasArgument(suggestion.label, context.argument));
});

const filesSuggestions = (filter: (info: FileInfo) => boolean) => async (tokenValue: string, directory: string): Promise<Suggestion[]> => {
    const parentDirectory = userFriendlyPath(directory.replace(/\/$/, "").split(Path.sep).slice(0, -1).join(Path.sep));
    const suggestions: Suggestion[] = [];

    if (_.last(tokenValue.split(Path.sep))!.startsWith(".")) {
        suggestions.push({label: "../", detail: parentDirectory});
    }

    const tokenDirectory = directoryName(tokenValue);
    const basePath = tokenValue.slice(tokenDirectory.length);
    const directoryPath = resolveDirectory(directory, tokenDirectory);
    const stats = await io.lstatsIn(directoryPath);

    return stats
        .filter(info => info.name.startsWith(".") ? basePath.startsWith(".") : true)
        .filter(info => info.stat.isDirectory() || filter(info))
        .map(info => {
            const escapedName: string = escapeFilePath(info.name);

            if (info.stat.isDirectory() || info.stat.isSymbolicLink()) {
                return {label: escapedName + "/"};
            } else {
                return {label: escapedName};
            }
        }).concat(suggestions);
};

const filesSuggestionsProvider =
    (filter: (info: FileInfo) => boolean) =>
        (context: AutocompletionContext, directory = context.environment.pwd): Promise<Suggestion[]> =>
            filesSuggestions(filter)(context.argument.value, directory);

export const executableFilesSuggestions = filesSuggestions(info => info.stat.isFile() && modeToPermissions(info.stat.mode).execute.owner);
export const anyFilesSuggestions = filesSuggestions(() => true);
export const anyFilesSuggestionsProvider = unique(filesSuggestionsProvider(() => true));
export const directoriesSuggestions = filesSuggestions(info => info.stat.isDirectory() || info.stat.isSymbolicLink());
export const directoriesSuggestionsProvider = filesSuggestionsProvider(info => info.stat.isDirectory() || info.stat.isSymbolicLink());

export const environmentVariableSuggestions = provide(async context => {
    if (context.argument.value.startsWith("$")) {
        return context.environment.map((key, value) =>
            ({label: "$" + key, detail: value}),
        );
    } else {
        return [];
    }
});

export function contextIndependent(provider: () => Promise<Suggestion[]>) {
    return _.memoize(provider, () => "");
}

export function staticSuggestionsProvider(suggestions: Suggestion[]) {
    return contextIndependent(async () => suggestions);
}

export const emptyProvider = provide(async() => []);

export const defaultAutocompletionProvider = provide(async context => {
    if (context.argument.value.length) {
        return combine([environmentVariableSuggestions, anyFilesSuggestionsProvider])(context);
    } else {
        return [];
    }
});

export const longAndShortFlag = (name: string, shortName = name[0]) => provide(async context => {
    const longValue = `--${name}`;
    const shortValue = `-${shortName}`;

    if (context.argument.command.hasArgument(longValue, context.argument) || context.argument.command.hasArgument(shortValue, context.argument)) {
        return [];
    }

    const value = context.argument.value === shortValue ? shortValue : longValue;

    return [{label: value}];
});

export const shortFlag = (char: string) => unique(async() => [{label: `-${char}`}]);
export const longFlag = (name: string) => unique(async() => [{label: `--${name}`}]);

export const mapSuggestions = (provider: AutocompletionProvider, mapper: (suggestion: Suggestion) => Suggestion) => provide(async context => (await provider(context)).map(mapper));

export interface SubcommandConfig {
    name: string;
    detail?: string;
    provider?: AutocompletionProvider;
}

export const commandWithSubcommands = (subCommands: SubcommandConfig[]) => {
    return async (context: AutocompletionContext) => {
        if (context.argument.position === 1) {
            return subCommands.map(({ name, detail, provider }) => ({
                label: name,
                detail,
                space: provider !== undefined,
            }));
        } else if (context.argument.position === 2) {
            const firstArgument = context.argument.command.nthArgument(1);
            if (firstArgument) {
                const subCommandConfig = subCommands.find(config => config.name === firstArgument.value);
                if (subCommandConfig && subCommandConfig.provider) {
                    return await subCommandConfig.provider(context);
                }
            }
        }
        return [];
    };
};


================================================
FILE: src/plugins/completion_utils/Descriptions.ts
================================================
/* tslint:disable:max-line-length */

export const descriptions = {
    git: {
        subcommands: {
            add: "Add file contents to the index.",
            am: "Apply a series of patches from a mailbox.",
            archive: "Create an archive of files from a named tree.",
            bisect: "Find by binary search the change that introduced a bug.",
            branch: "List, create, or delete branches.",
            bundle: "Move objects and refs by archive.",
            checkout: "Switch branches or restore working tree files.",
            cherryPick: "Apply the changes introduced by some existing commits.",
            citool: "Graphical alternative to git-commit.",
            clean: "Remove untracked files from the working tree.",
            clone: "Clone a repository into a new directory.",
            commit: "Record changes to the repository.",
            config: "Get and set repository or global options",
            describe: "Describe a commit using the most recent tag reachable from it.",
            diff: "Show changes between commits, commit and working tree, etc.",
            fetch: "Download objects and refs from another repository.",
            formatPatch: "Prepare patches for e-mail submission.",
            gc: "Cleanup unnecessary files and optimize the local repository.",
            grep: "Print lines matching a pattern.",
            gui: "A portable graphical interface to Git.",
            init: "Create an empty Git repository or reinitialize an existing one.",
            log: "Show commit logs.",
            merge: "Join two or more development histories together.",
            mv: "Move or rename a file, a directory, or a symlink.",
            notes: "Add or inspect object notes.",
            pull: "Fetch from and integrate with another repository or a local branch.",
            push: "Update remote refs along with associated objects.",
            rebase: "Forward-port local commits to the updated upstream head.",
            reset: "Reset current HEAD to the specified state.",
            revert: "Revert some existing commits.",
            rm: "Remove files from the working tree and from the index.",
            shortlog: "Summarize git log output.",
            show: "Show various types of objects.",
            stash: "Stash the changes in a dirty working directory away.",
            status: "Show the working tree status.",
            submodule: "Initialize, update or inspect submodules.",
            tag: "Create, list, delete or verify a tag object signed with GPG.",
            worktree: "Manage multiple worktrees.",
        },
        add: {
            patch: 'Interactively choose hunks of patch between the index and the work tree and add them to the index. This gives the user a chance to review the difference before adding modified contents to the index. This effectively runs add --interactive, but bypasses the initial command menu and directly jumps to the patch subcommand. See "Interactive mode" for details.',
            interactive: 'Add modified contents in the working tree interactively to the index. Optional path arguments may be supplied to limit operation to a subset of the working tree. See "Interactive mode" for details.',
            dryRun: "Don't actually add the file(s), just show if they exist and/or will be ignored.",
            force: "Allow adding otherwise ignored files.",
            edit: "Open the diff vs. the index in an editor and let the user edit it. After the editor was closed, adjust the hunk headers and apply the patch to the index. The intent of this option is to pick and choose lines of the patch to apply, or even to modify the contents of lines to be staged. This can be quicker and more flexible than using the interactive hunk selector. However, it is easy to confuse oneself and create a patch that does not apply to the index. See EDITING PATCHES below.",
            update: "Update the index just where it already has an entry matching <pathspec>. This removes as well as modifies index entries to match the working tree, but adds no new files. If no <pathspec> is given when -u option is used, all tracked files in the entire working tree are updated (old versions of Git used to limit the update to the current directory and its subdirectories).",
            noIgnoreRemoval: "Update the index not only where the working tree has a file matching <pathspec> but also where the index already has an entry. This adds, modifies, and removes index entries to match the working tree. If no <pathspec> is given when -A option is used, all files in the entire working tree are updated (old versions of Git used to limit the update to the current directory and its subdirectories).",
            ignoreRemoval: 'Update the index by adding new files that are unknown to the index and files modified in the working tree, but ignore files that have been removed from the working tree. This option is a no-op when no <pathspec> is used. This option is primarily to help users who are used to older versions of Git, whose "git add <pathspec>..." was a synonym for "git add --no-all <pathspec>...", i.e. ignored removed files.',
            intentToAdd: "Record only the fact that the path will be added later. An entry for the path is placed in the index with no content. This is useful for, among other things, showing the unstaged content of such files with git diff and committing them with git commit -a.",
            refresh: "Don't add the file(s), but only refresh their stat() information in the index.",
            ignoreErrors: "If some files could not be added because of errors indexing them, do not abort the operation, but continue adding the others. The command shall still exit with non-zero status. The configuration variable add.ignoreErrors can be set to true to make this the default behaviour.",
            ignoreMissing: "This option can only be used together with --dry-run. By using this option the user can check if any of the given files would be ignored, no matter if they are already present in the work tree or not.",
            chmod: "Override the executable bit of the added files. The executable bit is only changed in the index, the files on disk are left unchanged.",
            separator: "This option can be used to separate command-line options from the list of files, (useful when filenames might be mistaken for command-line options).",
            verbose: "Be verbose.",
        },
        checkout: {
            branch: "Create a new branch and start it at <start_point>; see git-branch(1) for details.",
        },
        commit: {
            message: "Use the given <msg> as the commit message. If multiple -m options are given, their values are concatenated as separate paragraphs.",
            all: "Tell the command to automatically stage files that have been modified and deleted, but new files you have not told Git about are not affected.",
            patch: "Use the interactive patch selection interface to chose which changes to commit. See git-add(1) for details.",
            NULL: "When showing short or porcelain status output, terminate entries in the status output with NULL, instead of LF. If no format is given, implies the --porcelain output format.",
            template: "When editing the commit message, start the editor with the contents in the given file. The commit.template configuration variable is often used to give this option implicitly to the command. This mechanism can be used by projects that want to guide participants with some hints on what to write in the message in what order. If the user exits the editor without editing the message, the commit is aborted. This has no effect when a message is given by other means, e.g. with the -m or -F options.",
            signoff: "Add Signed-off-by line by the committer at the end of the commit log message. The meaning of a signoff depends on the project, but it typically certifies that committer has the rights to submit this work under the same license and agrees to a Developer Certificate of Origin (see http://developercertificate.org/ for more information).",
            noVerify: "This option bypasses the pre-commit and commit-msg hooks. See also githooks(5).",
            edit: "The message taken from file with -F, command line with -m, and from commit object with -C are usually used as the commit log message unmodified. This option lets you further edit the message taken from these sources.",
            include: "Before making a commit out of staged contents so far, stage the contents of paths given on the command line as well. This is usually not what you want unless you are concluding a conflicted merge.",
            only: "Make a commit by taking the updated working tree contents of the paths specified on the command line, disregarding any contents that have been staged for other paths. This is the default mode of operation of git commit if any paths are given on the command line, in which case this option can be omitted. If this option is specified together with --amend, then no paths need to be specified, which can be used to amend the last commit without committing changes that have already been staged.",
            verbose: "Show unified diff between the HEAD commit and what would be committed at the bottom of the commit message template to help the user describe the commit by reminding what changes the commit has. Note that this diff output doesn't have its lines prefixed with #. This diff will not be a part of the commit message. See the commit.verbose configuration variable in git-config(1). If specified twice, show in addition the unified diff between what would be committed and the worktree files, i.e. the unstaged changes to tracked files.",
            quiet: "Suppress commit summary message.",
            resetAuthor: "When used with -C/-c/--amend options, or when committing after a a conflicting cherry-pick, declare that the authorship of the resulting commit now belongs to the committer. This also renews the author timestamp.",
            short: "When doing a dry-run, give the output in the short-format. See git-status(1) for details. Implies --dry-run.",
            branch: "Show the branch and tracking info even in short-format.",
            porcelain: "When doing a dry-run, give the output in a porcelain-ready format. See git-status(1) for details. Implies --dry-run.",
            long: "When doing a dry-run, give the output in a the long-format. Implies --dry-run.",
            allowEmpty: "Usually recording a commit that has the exact same tree as its sole parent commit is a mistake, and the command prevents you from making such a commit. This option bypasses the safety, and is primarily for use by foreign SCM interface scripts.",
            allowEmptyMessage: "Like --allow-empty this command is primarily for use by foreign SCM interface scripts. It allows you to create a commit with an empty commit message without using plumbing commands like git-commit-tree(1).",
            noEdit: "Use the selected commit message without launching an editor. For example, git commit --amend --no-edit amends a commit without changing its commit message.",
            noPostRewrite: "Bypass the post-rewrite hook.",
            dryRun: "Do not create a commit, but show a list of paths that are to be committed, paths with local changes that will be left uncommitted and paths that are untracked.",
            status: "Include the output of git-status(1) in the commit message template when using an editor to prepare the commit message. Defaults to on, but can be used to override configuration variable commit.status.",
            noStatus: "Do not include the output of git-status(1) in the commit message template when using an editor to prepare the default commit message.",
            noGpgSign: "Countermand commit.gpgSign configuration variable that is set to force each and every commit to be signed.",
        },
        status: {
            short: "Give the output in the short-format.",
            branch: "Show the branch and tracking info even in short-format.",
            porcelain: "Give the output in an easy-to-parse format for scripts. This is similar to the short output, but will remain stable across Git versions and regardless of user configuration. See below for details. The version parameter is used to specify the format version. This is optional and defaults to the original version v1 format.",
            long: "Give the output in the long-format. This is the default.",
            verbose: "In addition to the names of files that have been changed, also show the textual changes that are staged to be committed (i.e., like the output of git diff --cached). If -v is specified twice, then also show the changes in the working tree that have not yet been staged (i.e., like the output of git diff).",
            untrackedFiles: "Show untracked files. The mode parameter is used to specify the handling of untracked files. It is optional: it defaults to all, and if specified, it must be stuck to the option (e.g.  -uno, but not -u no). The possible options are: o   no - Show no untracked files. o   normal - Shows untracked files and directories. o   all - Also shows individual files in untracked directories. When -u option is not used, untracked files and directories are shown (i.e. the same as specifying normal), to help you avoid forgetting to add newly created files. Because it takes extra work to find untracked files in the filesystem, this mode may take some time in a large working tree. Consider enabling untracked cache and split index if supported (see git update-index --untracked-cache and git update-index --split-index), Otherwise you can use no to have git status return more quickly without showing untracked files. The default can be changed using the status.showUntrackedFiles configuration variable documented in git-config(1).",
            ignoreSubmodules: 'Ignore changes to submodules when looking for changes. <when> can be either "none", "untracked", "dirty" or "all", which is the default. Using "none" will consider the submodule modified when it either contains untracked or modified files or its HEAD differs from the commit recorded in the superproject and can be used to override any settings of the ignore option in git- config(1) or gitmodules(5). When "untracked" is used submodules are not considered dirty when they only contain untracked content (but they are still scanned for modified content). Using "dirty" ignores all changes to the work tree of submodules, only changes to the commits stored in the superproject are shown (this was the behavior before 1.7.0). Using "all" hides all changes to submodules (and suppresses the output of submodule summaries when the config option status.subm
Download .txt
gitextract_wntplryt/

├── .dockerignore
├── .gitignore
├── .node-version
├── .npmrc
├── .nvmrc
├── .travis.yml
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── build/
│   └── icon.icns
├── docs/
│   └── vscodedebugging.md
├── package.json
├── src/
│   ├── Autocompletion.ts
│   ├── Char.ts
│   ├── Decorators.ts
│   ├── EmitterWithUniqueID.ts
│   ├── Enums.ts
│   ├── Interfaces.ts
│   ├── Output.ts
│   ├── PTY.ts
│   ├── PluginManager.ts
│   ├── main/
│   │   └── Main.ts
│   ├── monaco/
│   │   ├── Loader.ts
│   │   ├── PromptTheme.ts
│   │   ├── ShellHistoryLanguage.ts
│   │   └── ShellLanguage.ts
│   ├── plugins/
│   │   ├── AliasSuggestions.ts
│   │   ├── DotEnvLoader.ts
│   │   ├── GitGrep.tsx
│   │   ├── JSON.tsx
│   │   ├── JobFinishedNotifications.ts
│   │   ├── NVM.ts
│   │   ├── PWDOperatingSystemIntegrator.ts
│   │   ├── RVM.ts
│   │   ├── SaveHistory.ts
│   │   ├── SaveWindowBounds.ts
│   │   ├── Show.tsx
│   │   ├── UpdateLastPresentWorkingDirectory.ts
│   │   ├── completion/
│   │   │   ├── Brew.ts
│   │   │   ├── Cat.ts
│   │   │   ├── Cd.ts
│   │   │   ├── Cp.ts
│   │   │   ├── Df.ts
│   │   │   ├── Executable.ts
│   │   │   ├── Find.ts
│   │   │   ├── Git.ts
│   │   │   ├── Grep.ts
│   │   │   ├── History.ts
│   │   │   ├── Ln.ts
│   │   │   ├── Locate.ts
│   │   │   ├── Ls.ts
│   │   │   ├── Mkdir.ts
│   │   │   ├── Mv.ts
│   │   │   ├── NPM.ts
│   │   │   ├── Ps.ts
│   │   │   ├── Pwd.ts
│   │   │   ├── Rails.ts
│   │   │   ├── Rake.ts
│   │   │   ├── Rm.ts
│   │   │   ├── Scp.ts
│   │   │   ├── Shutdown.ts
│   │   │   ├── Tail.ts
│   │   │   ├── Top.ts
│   │   │   └── Vagrant.ts
│   │   └── completion_utils/
│   │       ├── Button.tsx
│   │       ├── Combine.ts
│   │       ├── Common.ts
│   │       └── Descriptions.ts
│   ├── references.d.ts
│   ├── services/
│   │   ├── FontService.ts
│   │   ├── GitService.ts
│   │   ├── HistoryService.ts
│   │   ├── JobsService.ts
│   │   ├── SessionsService.ts
│   │   ├── UpdatesService.ts
│   │   ├── WindowService.ts
│   │   └── index.ts
│   ├── shell/
│   │   ├── Aliases.ts
│   │   ├── BuiltInCommands.ts
│   │   ├── CommandExecutor.ts
│   │   ├── Environment.ts
│   │   ├── Job.ts
│   │   ├── Parser.ts
│   │   ├── Prompt.ts
│   │   ├── Scanner.ts
│   │   └── Session.ts
│   ├── utils/
│   │   ├── Common.ts
│   │   ├── Git.ts
│   │   ├── HistoryTrie.ts
│   │   ├── JSONTree.tsx
│   │   ├── Link.tsx
│   │   ├── ManPageParsingUtils.ts
│   │   ├── ManPages.ts
│   │   ├── OrderedSet.ts
│   │   ├── Process.ts
│   │   └── Shell.ts
│   └── views/
│       ├── ApplicationComponent.tsx
│       ├── JobComponent.tsx
│       ├── JobHeaderComponent.tsx
│       ├── Main.tsx
│       ├── OutputComponent.tsx
│       ├── PrettifyToggleComponent.tsx
│       ├── PromptComponent.tsx
│       ├── SearchComponent.tsx
│       ├── SessionComponent.tsx
│       ├── TabComponent.tsx
│       ├── TabHeaderComponent.tsx
│       ├── ViewUtils.ts
│       ├── css/
│       │   ├── FontAwesome.ts
│       │   ├── colors.ts
│       │   ├── functions.ts
│       │   └── styles.ts
│       ├── index.html
│       ├── keyevents/
│       │   └── Keybindings.ts
│       ├── menu/
│       │   └── Menu.ts
│       └── mouseevents/
│           └── MouseEvents.ts
├── test/
│   ├── e2e.ts
│   ├── environment_spec.ts
│   ├── output_spec.ts
│   ├── pty_spec.ts
│   ├── references.d.ts
│   ├── shell/
│   │   └── scanner_spec.ts
│   ├── test_files/
│   │   ├── file_names_test/
│   │   │   └── file with brackets()
│   │   └── vttest/
│   │       ├── 1-1
│   │       ├── 1-2
│   │       ├── 1-3
│   │       ├── 1-4
│   │       ├── 1-5
│   │       ├── 1-6
│   │       ├── 2-1
│   │       ├── 2-10
│   │       ├── 2-11
│   │       ├── 2-12
│   │       ├── 2-13
│   │       ├── 2-14
│   │       ├── 2-15
│   │       ├── 2-2
│   │       ├── 2-3
│   │       ├── 2-4
│   │       ├── 2-5
│   │       ├── 2-6
│   │       ├── 2-7
│   │       ├── 2-8
│   │       └── 2-9
│   └── utils/
│       ├── ManPages_spec.ts
│       ├── common_spec.ts
│       ├── history_trie_spec.ts
│       └── ordered_set_spec.ts
├── tsconfig.json
├── tslint.json
└── typings/
    ├── Interfaces.d.ts
    ├── Overrides.d.ts
    ├── child-process-promise.d.ts
    ├── dirStat.d.ts
    ├── mode-to-permissions.d.ts
    └── uuid.d.ts
Download .txt
SYMBOL INDEX (651 symbols across 68 files)

FILE: src/Autocompletion.ts
  type GetSuggestionsOptions (line 7) | type GetSuggestionsOptions = {
  function getSuggestions (line 16) | async function getSuggestions({

FILE: src/Char.ts
  type Char (line 16) | interface Char {
  function createChar (line 21) | function createChar(char: string, attributes: Attributes): Char {

FILE: src/Decorators.ts
  function memoize (line 3) | function memoize(resolver: ((...args: any[]) => any) | undefined = undef...
  function debounce (line 30) | function debounce(wait: number = 0) {

FILE: src/EmitterWithUniqueID.ts
  class EmitterWithUniqueID (line 3) | class EmitterWithUniqueID extends events.EventEmitter {
    method constructor (line 6) | constructor() {

FILE: src/Enums.ts
  type KeyCode (line 5) | enum KeyCode {
  type Color (line 60) | enum Color {
  type Status (line 71) | enum Status {
  type ScreenMode (line 76) | enum ScreenMode {
  type BufferType (line 81) | enum BufferType {
  type Weight (line 86) | enum Weight {
  type Brightness (line 92) | enum Brightness {
  type LogLevel (line 97) | enum LogLevel {
  type KeyboardAction (line 103) | enum KeyboardAction {

FILE: src/Interfaces.ts
  type ColorCode (line 13) | type ColorCode = number | number[];
  type Attributes (line 15) | interface Attributes {
  type PreliminaryAutocompletionContext (line 27) | interface PreliminaryAutocompletionContext {
  type AutocompletionContext (line 33) | interface AutocompletionContext extends PreliminaryAutocompletionContext {
  type AutocompletionProvider (line 37) | type AutocompletionProvider = (context: AutocompletionContext) => Promis...
  type FileInfo (line 39) | interface FileInfo {
  type Prettyfier (line 44) | interface Prettyfier {
  type EnvironmentObserverPlugin (line 49) | interface EnvironmentObserverPlugin {
  type TerminalLikeDevice (line 54) | interface TerminalLikeDevice {
  type UserEvent (line 59) | type UserEvent = KeyboardEvent | ClipboardEvent;
  type MouseEvent (line 61) | type MouseEvent = DragEvent;

FILE: src/Output.ts
  type HandlerResult (line 13) | interface HandlerResult {
  type SavedState (line 20) | interface SavedState {
  type CharacterSets (line 31) | enum CharacterSets {
  type DesignatedCharacterSets (line 36) | interface DesignatedCharacterSets {
  type SelectedCharacterSet (line 43) | type SelectedCharacterSet = keyof DesignatedCharacterSets;
  function or1 (line 45) | function or1(value: number | undefined) {
  function logPosition (line 54) | function logPosition(buffer: Buffer) {
  constant SGR (line 99) | const SGR: { [indexer: string]: (attributes: Attributes) => Attributes }...
  constant CSI (line 144) | const CSI = {
  class Output (line 158) | class Output extends events.EventEmitter {
    method constructor (line 166) | constructor(private terminalDevice: TerminalLikeDevice, public dimensi...
    method write (line 240) | write(ansiString: string) {
    method toLines (line 245) | toLines() {
    method toString (line 249) | toString(): string {
    method isEmpty (line 253) | isEmpty(): boolean {
    method activeBuffer (line 257) | get activeBuffer() {
    method escapeHandler (line 265) | private escapeHandler(collected: any, flag: string) {
    method decPrivateModeHandler (line 368) | private decPrivateModeHandler(ps: number, flag: "h" | "l"): HandlerRes...
    method csiHandler (line 475) | private csiHandler(_collected: any, rawParams: number[] | number, flag...
    method setColor (line 698) | private setColor(sgr: number, color: ColorCode): void {
  class Buffer (line 708) | class Buffer {
    method constructor (line 729) | constructor(private output: Output, private maxScrollbackSize: number) {
    method map (line 733) | map<T>(callback: (row: List<Char>, index: number) => T): T[] {
    method writeOne (line 749) | writeOne(char: string): void {
    method scrollDown (line 807) | scrollDown(count: number) {
    method scrollUp (line 812) | scrollUp(count: number, deletedLine = this._margins.top) {
    method attributes (line 817) | get attributes(): i.Attributes {
    method resetAttributes (line 821) | resetAttributes(): void {
    method setAttributes (line 825) | setAttributes(attributes: i.Attributes): void {
    method toLines (line 829) | toLines(): string[] {
    method showCursor (line 833) | showCursor(state: boolean): void {
    method blinkCursor (line 837) | blinkCursor(state: boolean): void {
    method moveCursorRelative (line 841) | moveCursorRelative(advancement: Advancement): this {
    method moveCursorAbsolute (line 856) | moveCursorAbsolute(position: Partial<RowColumn>): this {
    method deleteRight (line 870) | deleteRight(n: number) {
    method insertSpaceRight (line 877) | insertSpaceRight(n: number) {
    method eraseRight (line 884) | eraseRight(n: number) {
    method clearRow (line 893) | clearRow() {
    method clearRowToEnd (line 897) | clearRowToEnd() {
    method clearRowToBeginning (line 907) | clearRowToBeginning() {
    method clear (line 914) | clear() {
    method clearToBeginning (line 919) | clearToBeginning() {
    method clearToEnd (line 926) | clearToEnd() {
    method scrollbackSize (line 931) | get scrollbackSize(): number {
    method size (line 935) | get size(): number {
    method margins (line 939) | set margins(margins: Partial<Margins>) {
    method marginTop (line 943) | get marginTop(): number {
    method marginBottom (line 947) | get marginBottom(): number {
    method at (line 955) | at(position: RowColumn): Char {
    method saveCurrentState (line 959) | saveCurrentState() {
    method restoreCurrentState (line 969) | restoreCurrentState() {
    method setTabStop (line 980) | setTabStop() {
    method clearTabStop (line 984) | clearTabStop() {
    method clearAllTabStops (line 988) | clearAllTabStops() {
    method nextTabStopIndex (line 992) | get nextTabStopIndex() {
    method homePosition (line 997) | private get homePosition(): RowColumn {
    method set (line 1005) | private set(char: Char): void {
    method ensureCursorRowExists (line 1010) | private ensureCursorRowExists(): void {
    method charFromCharset (line 1029) | private charFromCharset(char: string) {
    method lastColumnIndex (line 1037) | private get lastColumnIndex() {
    method emptyLine (line 1041) | private get emptyLine() {
    method spaces (line 1045) | private spaces(n: number, attributes = this.attributes) {
    method dimensions (line 1049) | get dimensions() {

FILE: src/PTY.ts
  type ITerminal (line 8) | interface ITerminal {
  class PTY (line 15) | class PTY {
    method constructor (line 21) | constructor(words: EscapedShellWord[], env: ProcessEnvironment, dimens...
    method write (line 38) | write(data: string): void {
    method resize (line 42) | resize(dimensions: Dimensions) {
    method kill (line 46) | kill(signal: string): void {
  function executeCommand (line 63) | function executeCommand(
  function linedOutputOf (line 87) | async function linedOutputOf(command: string, args: string[], directory:...
  function executeCommandWithShellConfig (line 92) | async function executeCommandWithShellConfig(command: string): Promise<s...

FILE: src/PluginManager.ts
  class PluginManager (line 7) | class PluginManager {
    method registerPrettyfier (line 12) | static registerPrettyfier(prettyfier: Prettyfier): void {
    method prettyfiers (line 16) | static get prettyfiers(): Prettyfier[] {
    method registerEnvironmentObserver (line 20) | static registerEnvironmentObserver(plugin: EnvironmentObserverPlugin):...
    method environmentObservers (line 24) | static get environmentObservers(): EnvironmentObserverPlugin[] {
    method registerAutocompletionProvider (line 28) | static registerAutocompletionProvider(commandName: string, provider: A...
    method autocompletionProviderFor (line 32) | static autocompletionProviderFor(commandName: string): AutocompletionP...
  function loadAllPlugins (line 38) | async function loadAllPlugins(): Promise<void> {

FILE: src/main/Main.ts
  function windowBounds (line 45) | function windowBounds(): Electron.Rectangle {

FILE: src/monaco/Loader.ts
  function requireMonaco (line 1) | function requireMonaco(callback: () => void) {

FILE: src/monaco/ShellLanguage.ts
  function getTokensAtLine (line 207) | function getTokensAtLine(model: any, lineNumber: number) {

FILE: src/plugins/NVM.ts
  function withNvmPath (line 6) | async function withNvmPath(directory: string, callback: (path: string) =...

FILE: src/plugins/RVM.ts
  function getRubyVersion (line 10) | async function getRubyVersion(directory: string): Promise<string> {
  function getGemSetName (line 19) | async function getGemSetName(directory: string): Promise<string> {
  function getGemSetPaths (line 32) | function getGemSetPaths(rubyVersion: string, gemSetName: string): string...
  function binPaths (line 37) | function binPaths(rubyVersion: string, gemSetName: string): string[] {
  function withRvmData (line 45) | async function withRvmData(directory: string, callback: (binPaths: strin...

FILE: src/plugins/completion/Brew.ts
  type FormulaAttributes (line 16) | interface FormulaAttributes {
  type BrewCommandData (line 81) | interface BrewCommandData {

FILE: src/plugins/completion/Git.ts
  function doesLookLikeBranchAlias (line 547) | function doesLookLikeBranchAlias(word: string) {
  function canonizeBranchAlias (line 552) | function canonizeBranchAlias(alias: string) {

FILE: src/plugins/completion/History.ts
  function cdIntoRelativePathFilter (line 8) | function cdIntoRelativePathFilter(record: HistoryRecord, pwd: string): b...
  function getHistorySuggestions (line 32) | function getHistorySuggestions(input: string, pwd: string): Suggestion[] {

FILE: src/plugins/completion/Ps.ts
  type ShortFlagItem (line 10) | interface ShortFlagItem {
  type TokenInfo (line 30) | interface TokenInfo {
  type LongFlagItem (line 47) | interface LongFlagItem {

FILE: src/plugins/completion_utils/Button.tsx
  type ButtonProps (line 17) | type ButtonProps = {

FILE: src/plugins/completion_utils/Common.ts
  type Suggestion (line 9) | interface Suggestion {
  function provide (line 71) | function provide(provider: AutocompletionProvider): AutocompletionProvid...
  function contextIndependent (line 128) | function contextIndependent(provider: () => Promise<Suggestion[]>) {
  function staticSuggestionsProvider (line 132) | function staticSuggestionsProvider(suggestions: Suggestion[]) {
  type SubcommandConfig (line 164) | interface SubcommandConfig {

FILE: src/services/FontService.ts
  function getLetterSize (line 3) | function getLetterSize(size: number, fontFamily: string) {
  class FontService (line 21) | class FontService {
    method constructor (line 28) | constructor() {
    method resetSize (line 32) | resetSize() {
    method increaseSize (line 37) | increaseSize() {
    method decreaseSize (line 42) | decreaseSize() {
    method updateFont (line 47) | private updateFont(size: number, family: string) {

FILE: src/services/GitService.ts
  constant INTERVAL (line 14) | const INTERVAL = 5000;
  function getState (line 16) | async function getState(directory: string): Promise<GitState> {
  function createObservable (line 30) | function createObservable(directory: string) {
  class GitService (line 43) | class GitService {
    method observableFor (line 46) | observableFor(directory: string): Observable<GitState> {

FILE: src/services/HistoryService.ts
  type HistoryRecordWithoutID (line 9) | interface HistoryRecordWithoutID {
  type HistoryRecord (line 17) | interface HistoryRecord extends HistoryRecordWithoutID {
  class HistoryService (line 36) | class HistoryService {
    method constructor (line 41) | constructor() {
    method all (line 45) | get all(): HistoryRecord[] {
    method latest (line 49) | get latest(): HistoryRecord | undefined {
    method add (line 53) | add(recordWithoutID: HistoryRecordWithoutID) {
    method get (line 65) | get(id: number): HistoryRecord {
    method nextID (line 69) | private get nextID(): number {

FILE: src/services/JobsService.ts
  class JobsService (line 6) | class JobsService {

FILE: src/services/SessionsService.ts
  class SessionsService (line 8) | class SessionsService {
    method create (line 12) | create() {
    method get (line 27) | get(id: SessionID) {
    method close (line 31) | close(ids: SessionID | SessionID[]) {
    method closeAll (line 51) | closeAll() {

FILE: src/services/UpdatesService.ts
  class UpdatesService (line 4) | class UpdatesService {
    method constructor (line 9) | constructor() {
    method checkUpdate (line 19) | private checkUpdate() {

FILE: src/services/WindowService.ts
  class WindowService (line 9) | class WindowService {
    method constructor (line 14) | constructor() {

FILE: src/services/index.ts
  type Services (line 10) | interface Services {

FILE: src/shell/Aliases.ts
  function loadAliasesFromConfig (line 6) | async function loadAliasesFromConfig(): Promise<void> {
  function parseAlias (line 11) | function parseAlias(line: string) {
  class Aliases (line 32) | class Aliases {
    method constructor (line 35) | constructor(aliases: Dictionary<string>) {
    method add (line 39) | add(name: string, value: string) {
    method has (line 43) | has(name: string): name is ExistingAlias {
    method get (line 47) | get(name: ExistingAlias): string {
    method getNameByValue (line 51) | getNameByValue(value: string): string | undefined {
    method remove (line 55) | remove(name: string) {
    method toObject (line 59) | toObject(): Dictionary<string> {

FILE: src/shell/BuiltInCommands.ts
  function sourceFile (line 88) | function sourceFile(session: Session, fileName: string) {
  class Command (line 104) | class Command {
    method executor (line 107) | static executor(command: string): (i: Job, args: string[]) => void {
    method isBuiltIn (line 111) | static isBuiltIn(command: string): boolean {
  function expandHistoricalDirectory (line 116) | function expandHistoricalDirectory(alias: string, historicalDirectories:...
  function isHistoricalDirectory (line 135) | function isHistoricalDirectory(directory: string): boolean {

FILE: src/shell/CommandExecutor.ts
  class NonZeroExitCodeError (line 8) | class NonZeroExitCodeError extends Error {
  method canExecute (line 12) | static async canExecute(_job: Job): Promise<boolean> {
  method constructor (line 16) | constructor(protected job: Job) {
  class BuiltInCommandExecutionStrategy (line 22) | class BuiltInCommandExecutionStrategy extends CommandExecutionStrategy {
    method canExecute (line 23) | static async canExecute(job: Job) {
    method startExecution (line 27) | startExecution() {
  class ShellExecutionStrategy (line 39) | class ShellExecutionStrategy extends CommandExecutionStrategy {
    method canExecute (line 40) | static async canExecute(job: Job) {
    method isBashFunc (line 47) | private static isBashFunc(job: Job): boolean {
    method isExecutableFromPath (line 51) | private static async isExecutableFromPath(job: Job): Promise<boolean> {
    method isPathOfExecutable (line 55) | private static async isPathOfExecutable(job: Job): Promise<boolean> {
    method startExecution (line 59) | startExecution() {
  class WindowsShellExecutionStrategy (line 72) | class WindowsShellExecutionStrategy extends CommandExecutionStrategy {
    method canExecute (line 73) | static async canExecute(_job: Job) {
    method startExecution (line 77) | startExecution() {
    method cmdPath (line 93) | private get cmdPath(): EscapedShellWord {
  class CommandExecutor (line 104) | class CommandExecutor {
    method execute (line 111) | static async execute(job: Job): Promise<{}> {

FILE: src/shell/Environment.ts
  function loadEnvironment (line 38) | async function loadEnvironment(): Promise<void> {
  class Environment (line 51) | class Environment {
    method constructor (line 54) | constructor(environment: Dictionary<string>) {
    method set (line 58) | set(key: string, value: string): void {
    method setMany (line 62) | setMany(pairs: Dictionary<string>): void {
    method toObject (line 68) | toObject(): ProcessEnvironment {
    method map (line 72) | map<R>(mapper: (key: string, value: string) => R): Array<R> {
    method get (line 82) | get(key: string): string {
    method has (line 86) | has(key: string): boolean {
    method path (line 90) | get path(): EnvironmentPath {
    method cdpath (line 94) | get cdpath(): FullPath[] {
    method pwd (line 98) | get pwd(): string {
    method pwd (line 106) | set pwd(value: string) {
  class EnvironmentPath (line 111) | class EnvironmentPath extends AbstractOrderedSet<string> {
    method constructor (line 112) | constructor(private environment: Environment) {

FILE: src/shell/Job.ts
  class Job (line 16) | class Job extends EmitterWithUniqueID implements TerminalLikeDevice {
    method constructor (line 23) | constructor(private _session: Session, private _prompt: Prompt) {
    method execute (line 29) | async execute(): Promise<void> {
    method handleError (line 49) | handleError(message: NonZeroExitCodeError | string): void {
    method isRunningPty (line 61) | isRunningPty(): boolean {
    method setPty (line 65) | setPty(pty: PTY) {
    method write (line 70) | write(input: string | KeyboardEvent) {
    method session (line 74) | get session(): Session {
    method hasOutput (line 78) | hasOutput(): boolean {
    method interrupt (line 82) | interrupt(): void {
    method resize (line 90) | resize(): void {
    method canBePrettified (line 97) | canBePrettified(): boolean {
    method prettify (line 101) | prettify(): React.ReactElement<any> {
    method environment (line 109) | get environment(): Environment {
    method firstApplicablePrettyfier (line 113) | private get firstApplicablePrettyfier(): i.Prettyfier | undefined {
    method output (line 117) | get output(): Output {
    method prompt (line 121) | get prompt(): Prompt {
    method setStatus (line 125) | setStatus(status: Status): void {

FILE: src/shell/Parser.ts
  method constructor (line 27) | constructor(private token: Scanner.Token) {
  method fullStart (line 31) | get fullStart(): number {
  method fullEnd (line 35) | get fullEnd(): number {
  method precedingSpaces (line 39) | get precedingSpaces(): string {
  method followingSpaces (line 48) | get followingSpaces(): string {
  method raw (line 62) | get raw(): string {
  method value (line 66) | get value(): string {
  method constructor (line 77) | constructor(tokens: Scanner.Token[]) {
  method fullStart (line 82) | get fullStart(): number {
  method fullEnd (line 86) | get fullEnd(): number {
  class CompleteCommand (line 94) | class CompleteCommand extends BranchNode {
    method children (line 96) | get children(): ASTNode[] {
    method firstCommand (line 112) | get firstCommand(): Command {
  class List (line 122) | class List extends BranchNode {
    method children (line 124) | get children(): ASTNode[] {
  class AndOr (line 141) | class AndOr extends BranchNode {
    method children (line 143) | get children(): ASTNode[] {
  class Pipeline (line 160) | class Pipeline extends BranchNode {
    method children (line 162) | get children(): ASTNode[] {
  class PipeSequence (line 167) | class PipeSequence extends BranchNode {
    method children (line 169) | get children(): ASTNode[] {
  class Command (line 186) | class Command extends BranchNode {
    method children (line 188) | get children(): ASTNode[] {
    method commandWord (line 215) | get commandWord(): CommandWord | undefined {
    method parameterAssignments (line 222) | get parameterAssignments(): ParameterAssignmentList | undefined {
    method argumentList (line 229) | get argumentList(): ArgumentList | undefined {
    method nthArgument (line 235) | nthArgument(position: OneBasedPosition): Argument | undefined {
    method hasArgument (line 241) | hasArgument(value: string, currentArgument: Argument): boolean {
    method ioRedirect (line 250) | private get ioRedirect(): IORedirect | undefined {
    method categorizedTokens (line 257) | private get categorizedTokens() {
  class IORedirect (line 283) | class IORedirect extends BranchNode {
    method children (line 285) | get children(): ASTNode[] {
  class IOFile (line 301) | class IOFile extends LeafNode {
    method suggestions (line 302) | suggestions(context: PreliminaryAutocompletionContext): Promise<Sugges...
  class ShellSyntaxNode (line 307) | class ShellSyntaxNode extends LeafNode {
    method suggestions (line 308) | async suggestions(_context: PreliminaryAutocompletionContext): Promise...
  class ParameterAssignmentList (line 313) | class ParameterAssignmentList extends BranchNode {
    method children (line 315) | get children(): ASTNode[] {
  class ParameterAssignment (line 320) | class ParameterAssignment extends LeafNode {
    method suggestions (line 321) | async suggestions(_context: PreliminaryAutocompletionContext): Promise...
  class CommandWord (line 326) | class CommandWord extends LeafNode {
    method suggestions (line 327) | async suggestions({
  class ArgumentList (line 347) | class ArgumentList extends BranchNode {
    method constructor (line 348) | constructor(childTokens: Scanner.Token[], private command: Command) {
    method children (line 353) | get children(): ASTNode[] {
    method arguments (line 358) | get arguments(): Argument[] {
  class Argument (line 363) | class Argument extends LeafNode {
    method constructor (line 367) | constructor(token: Scanner.Token, command: Command, position: number) {
    method suggestions (line 373) | async suggestions(context: PreliminaryAutocompletionContext): Promise<...
  function argumentOfExpandedAST (line 385) | function argumentOfExpandedAST(argument: Argument, aliases: Aliases) {
  class UnknownNode (line 403) | class UnknownNode extends LeafNode {
    method suggestions (line 404) | async suggestions(_context: PreliminaryAutocompletionContext): Promise...
  class EmptyNode (line 409) | class EmptyNode extends LeafNode {
    method constructor (line 410) | constructor() {
    method fullEnd (line 415) | get fullEnd() {
    method suggestions (line 419) | async suggestions(_context: PreliminaryAutocompletionContext): Promise...
  function leafNodeAt (line 424) | function leafNodeAt(position: number, node: ASTNode): LeafNode {
  function serializeReplacing (line 450) | function serializeReplacing(tree: ASTNode, focused: LeafNode, replacemen...

FILE: src/shell/Prompt.ts
  class Prompt (line 6) | class Prompt extends events.EventEmitter {
    method constructor (line 10) | constructor(private session: Session) {
    method value (line 14) | get value(): string {
    method setValue (line 18) | setValue(value: string): void {
    method expandedTokens (line 25) | get expandedTokens(): Token[] {
    method commandName (line 29) | get commandName(): string {
    method arguments (line 36) | get arguments(): Token[] {

FILE: src/shell/Scanner.ts
  method constructor (line 7) | constructor(raw: string, fullStart: number) {
  class Empty (line 20) | class Empty extends Token {
    method constructor (line 21) | constructor() {
    method value (line 25) | get value() {
    method escapedValue (line 29) | get escapedValue() {
  method value (line 35) | get value() {
  class Word (line 40) | class Word extends StringLiteral {
    method value (line 41) | get value() {
    method escapedValue (line 45) | get escapedValue() {
  class Pipe (line 50) | class Pipe extends Token {
    method value (line 51) | get value() {
    method escapedValue (line 55) | get escapedValue(): EscapedShellWord {
  class Semicolon (line 60) | class Semicolon extends Token {
    method value (line 61) | get value() {
    method escapedValue (line 65) | get escapedValue(): EscapedShellWord {
  class And (line 70) | class And extends Token {
    method value (line 71) | get value() {
    method escapedValue (line 75) | get escapedValue(): EscapedShellWord {
  class Or (line 80) | class Or extends Token {
    method value (line 81) | get value() {
    method escapedValue (line 85) | get escapedValue(): EscapedShellWord {
  class InputRedirectionSymbol (line 90) | class InputRedirectionSymbol extends Token {
    method value (line 91) | get value() {
    method escapedValue (line 95) | get escapedValue(): EscapedShellWord {
  class OutputRedirectionSymbol (line 100) | class OutputRedirectionSymbol extends Token {
    method value (line 101) | get value() {
    method escapedValue (line 105) | get escapedValue(): EscapedShellWord {
  class AppendingOutputRedirectionSymbol (line 110) | class AppendingOutputRedirectionSymbol extends Token {
    method value (line 111) | get value() {
    method escapedValue (line 115) | get escapedValue(): EscapedShellWord {
  class CompositeStringLiteral (line 120) | class CompositeStringLiteral extends StringLiteral {
    method constructor (line 123) | constructor(tokens: Token[]) {
    method value (line 129) | get value() {
    method escapedValue (line 133) | get escapedValue() {
  class SingleQuotedStringLiteral (line 138) | class SingleQuotedStringLiteral extends StringLiteral {
    method escapedValue (line 139) | get escapedValue(): EscapedShellWord {
  class DoubleQuotedStringLiteral (line 144) | class DoubleQuotedStringLiteral extends StringLiteral {
    method escapedValue (line 145) | get escapedValue(): EscapedShellWord {
  class NewLine (line 150) | class NewLine extends Token {
    method value (line 151) | get value() {
    method escapedValue (line 155) | get escapedValue() {
  class Invalid (line 160) | class Invalid extends Token {
    method value (line 161) | get value() {
    method escapedValue (line 165) | get escapedValue(): EscapedShellWord {
  function scan (line 219) | function scan(input: string): Token[] {
  function squashLiterals (line 252) | function squashLiterals(tokens: Token[]): Token[] {
  function concatTokens (line 271) | function concatTokens(left: Token[], right: Token[]): Token[] {
  function shouldSquash (line 275) | function shouldSquash(left: Token, right: Token): boolean {
  function expandAliases (line 282) | function expandAliases(tokens: Token[], aliases: Aliases): Token[] {
  function stringLiteralValue (line 305) | function stringLiteralValue(literal: string): string | undefined {

FILE: src/shell/Session.ts
  type SessionID (line 16) | type SessionID = number & {__isSessionID: true};
  class Session (line 18) | class Session extends events.EventEmitter {
    method constructor (line 25) | constructor(private _dimensions: Dimensions = {columns: 80, rows: 25}) {
    method createJob (line 33) | createJob(prompt: Prompt): void {
    method dimensions (line 48) | get dimensions(): Dimensions {
    method dimensions (line 52) | set dimensions(value: Dimensions) {
    method lastJob (line 57) | get lastJob(): Job | undefined {
    method clearJobs (line 61) | clearJobs(): void {
    method close (line 66) | close(): void {
    method directory (line 70) | get directory(): string {
    method directory (line 74) | set directory(value: string) {
    method deserialize (line 92) | private deserialize(): void {
    method readSerialized (line 96) | private readSerialized<T>(file: string, defaultValue: T): T {

FILE: src/utils/Common.ts
  type FSExtraWalkObject (line 10) | interface FSExtraWalkObject {
  function info (line 15) | function info(...args: any[]): void {
  function log (line 19) | function log(...args: any[]): void {
  function error (line 23) | function error(...args: any[]): void {
  function print (line 27) | function print(level: e.LogLevel, args: Array<any>): void {
  function times (line 33) | function times(n: number, action: Function): void {
  function joinPath (line 97) | function joinPath(...parts: string[]) {
  function normalizeDirectory (line 104) | function normalizeDirectory(directoryPath: string): string {
  function directoryName (line 112) | function directoryName(path: string): string {
  function resolveDirectory (line 125) | function resolveDirectory(pwd: string, directory: string): FullPath {
  function resolveFile (line 129) | function resolveFile(pwd: string, file: string): FullPath {
  function userFriendlyPath (line 133) | function userFriendlyPath(path: string): string {
  function filterAsync (line 137) | async function filterAsync<T>(values: T[], asyncPredicate: (t: T) => Pro...
  function reduceAsync (line 142) | async function reduceAsync<A, E>(array: E[], initial: A, callback: (a: A...
  function pluralize (line 152) | function pluralize(word: string, count = 2) {
  function isImage (line 163) | function isImage(extension: string) {
  function pluralFormOf (line 167) | function pluralFormOf(word: string) {
  function groupWhen (line 175) | function groupWhen<T>(grouper: (a: T, b: T) => boolean, row: T[]): T[][] {
  function csi (line 199) | function csi(char: string) {
  function ss3 (line 203) | function ss3(char: string) {
  function normalizeProcessInput (line 207) | function normalizeProcessInput(input: string | KeyboardEvent, isCursorKe...
  function normalizeKey (line 246) | function normalizeKey(key: string, isCursorKeysModeSet: boolean): string {
  function commonPrefix (line 298) | function commonPrefix(left: string, right: string) {
  function mapObject (line 307) | function mapObject<T, R>(object: Dictionary<T>, mapper: (key: string, va...
  function escapeFilePath (line 317) | function escapeFilePath(unescaped: string): string {
  function fuzzyMatch (line 326) | function fuzzyMatch(input: string, candidate: string): boolean {

FILE: src/utils/Git.ts
  class Branch (line 8) | class Branch {
    method constructor (line 9) | constructor(private refName: string, private _isCurrent: boolean) {
    method toString (line 12) | toString(): string {
    method isCurrent (line 16) | isCurrent(): boolean {
  type ConfigVariable (line 21) | interface ConfigVariable {
  type StatusCode (line 26) | type StatusCode =
  function lettersToStatusCode (line 60) | function lettersToStatusCode(letters: string): StatusCode {
  class FileStatus (line 96) | class FileStatus {
    method constructor (line 97) | constructor(private _line: string) {
    method value (line 100) | get value(): string {
    method code (line 104) | get code(): StatusCode {
  type GitDirectoryPath (line 109) | type GitDirectoryPath = string & { __isGitDirectoryPath: boolean };
  function isGitDirectory (line 111) | function isGitDirectory(directory: string): directory is GitDirectoryPath {
  type BranchesOptions (line 115) | type BranchesOptions = {
  function currentBranchName (line 121) | async function currentBranchName(directory: GitDirectoryPath): Promise<s...
  type RepositoryState (line 142) | enum RepositoryState {
  function repositoryState (line 151) | async function repositoryState(directory: string): Promise<RepositorySta...
  function branches (line 177) | async function branches({
  function configVariables (line 204) | async function configVariables(directory: string): Promise<ConfigVariabl...
  function aliases (line 221) | async function aliases(directory: string): Promise<ConfigVariable[]> {
  function remotes (line 234) | async function remotes(directory: GitDirectoryPath): Promise<string[]> {
  function status (line 238) | async function status(directory: GitDirectoryPath): Promise<FileStatus[]> {
  function repoRoot (line 243) | async function repoRoot(directory: GitDirectoryPath): Promise<GitDirecto...

FILE: src/utils/HistoryTrie.ts
  type TrieNode (line 5) | interface TrieNode {
  type Continuation (line 11) | interface Continuation {
  function untokenize (line 17) | function untokenize(tokens: string[]): string {
  function tokenize (line 21) | function tokenize(string: string) {
  function getContinuation (line 25) | function getContinuation(node: TrieNode): Continuation {
  class HistoryTrie (line 33) | class HistoryTrie {
    method add (line 36) | add(input: string | string[], node: TrieNode = this.root) {
    method getContinuationsFor (line 53) | getContinuationsFor(input: string): Continuation[] {
    method getNodeAt (line 97) | private getNodeAt(path: string[], node: TrieNode = this.root): TrieNod...
    method getLongestNonAmbiguousPrefix (line 109) | private getLongestNonAmbiguousPrefix(node: TrieNode, path: string[]): ...

FILE: src/utils/JSONTree.tsx
  type JSONProps (line 30) | type JSONProps = {
  type JSONState (line 37) | type JSONState = {
  type JSONValueProps (line 42) | type JSONValueProps = {
  class JSONArrayNode (line 97) | class JSONArrayNode extends React.Component<JSONProps, JSONState> {
    method constructor (line 101) | constructor(props: JSONProps) {
    method getDefaultProps (line 115) | getDefaultProps() {
    method componentWillReceiveProps (line 119) | componentWillReceiveProps() {
    method getChildNodes (line 130) | getChildNodes() {
    method getItemString (line 145) | getItemString() {
    method render (line 152) | render(): JSX.Element {
  class JSONObjectNode (line 174) | class JSONObjectNode extends React.Component<JSONProps, any> {
    method constructor (line 179) | constructor(props: JSONProps) {
    method getDefaultProps (line 190) | getDefaultProps() {
    method componentWillReceiveProps (line 194) | componentWillReceiveProps() {
    method getChildNodes (line 205) | getChildNodes() {
    method getItemString (line 223) | getItemString() {
    method render (line 241) | render(): JSX.Element {
  class JSONStringNode (line 263) | class JSONStringNode extends React.Component<JSONValueProps, any> {
    method render (line 264) | render(): JSX.Element {
  class JSONNumberNode (line 277) | class JSONNumberNode extends React.Component<JSONValueProps, any> {
    method render (line 278) | render(): JSX.Element {
  class JSONNullNode (line 292) | class JSONNullNode extends React.Component<JSONValueProps, any> {
    method render (line 293) | render(): JSX.Element {
  class JSONBooleanNode (line 306) | class JSONBooleanNode extends React.Component<JSONValueProps, any> {
    method render (line 307) | render(): JSX.Element {
  class JSONTree (line 323) | class JSONTree extends React.Component<JSONProps, any> {
    method render (line 324) | render(): JSX.Element {

FILE: src/utils/OrderedSet.ts
  method constructor (line 2) | constructor(private storageGetter: () => T[], private storageSetter: (t:...
  method prepend (line 5) | prepend(element: T) {
  method remove (line 10) | remove(toRemove: T) {
  method removeWhere (line 14) | removeWhere(removePredicate: (existing: T) => boolean) {
  method size (line 18) | get size() {
  method at (line 22) | at(index: number): T | undefined {
  method toArray (line 30) | toArray() {
  class OrderedSet (line 35) | class OrderedSet<T> extends AbstractOrderedSet<T> {
    method constructor (line 36) | constructor() {

FILE: src/utils/Process.ts
  type User (line 6) | interface User {
  type Group (line 13) | interface Group {
  type Terminal (line 20) | interface Terminal {
  type Process (line 25) | interface Process {
  type Session (line 32) | interface Session {

FILE: src/utils/Shell.ts
  method existingConfigFiles (line 19) | async existingConfigFiles(): Promise<string[]> {
  method executeCommandSwitches (line 26) | get executeCommandSwitches() {
  method interactiveCommandSwitches (line 30) | get interactiveCommandSwitches() {
  method commandExecutorPath (line 34) | get commandExecutorPath() {
  method environmentCommand (line 38) | get environmentCommand() {
  method loadAliases (line 42) | loadAliases() {
  method combineCommands (line 46) | combineCommands(commands: string[]) {
  class Bash (line 51) | class Bash extends UnixShell {
    method executableName (line 52) | get executableName() {
    method configFiles (line 56) | get configFiles() {
    method noConfigSwitches (line 70) | get noConfigSwitches() {
    method preCommandModifiers (line 74) | get preCommandModifiers(): string[] {
  class ZSH (line 79) | class ZSH extends UnixShell {
    method executableName (line 80) | get executableName() {
    method configFiles (line 84) | get configFiles() {
    method noConfigSwitches (line 100) | get noConfigSwitches() {
    method preCommandModifiers (line 104) | get preCommandModifiers() {
  class Cmd (line 115) | class Cmd extends Shell {
    method cmdPath (line 116) | static get cmdPath() {
    method executableName (line 120) | get executableName() {
    method configFiles (line 124) | get configFiles() {
    method executeCommandSwitches (line 129) | get executeCommandSwitches() {
    method interactiveCommandSwitches (line 133) | get interactiveCommandSwitches() {
    method noConfigSwitches (line 137) | get noConfigSwitches() {
    method preCommandModifiers (line 141) | get preCommandModifiers(): string[] {
    method commandExecutorPath (line 145) | get commandExecutorPath() {
    method environmentCommand (line 149) | get environmentCommand() {
    method combineCommands (line 153) | combineCommands(commands: string[]) {
    method loadAliases (line 157) | async loadAliases() {

FILE: src/views/ApplicationComponent.tsx
  type ApplicationState (line 14) | type ApplicationState = {
  class ApplicationComponent (line 19) | class ApplicationComponent extends React.Component<{}, ApplicationState> {
    method constructor (line 22) | constructor(props: {}) {
    method render (line 48) | render() {
    method isMacOS (line 93) | isMacOS() {
    method focusedTabComponent (line 101) | get focusedTabComponent() {
    method addTab (line 105) | addTab(): void {
    method focusPreviousTab (line 123) | focusPreviousTab() {
    method focusNextTab (line 129) | focusNextTab() {
    method focusTab (line 135) | focusTab(index: number): void {
    method closeFocusedTab (line 147) | closeFocusedTab() {
    method focusedSession (line 156) | get focusedSession() {
    method closeFocusedSession (line 160) | closeFocusedSession() {
    method otherSession (line 164) | otherSession(): void {
    method resizeTabSessions (line 180) | private resizeTabSessions(tabIndex: number): void {
    method resizeAllSessions (line 184) | private resizeAllSessions() {
    method removeSessionFromState (line 190) | private removeSessionFromState(id: SessionID) {
    method removeTabFromState (line 206) | private removeTabFromState(index: number): void {
    method cloneState (line 223) | private cloneState(): ApplicationState {

FILE: src/views/JobComponent.tsx
  type Props (line 7) | interface Props {
  type State (line 13) | interface State {
  class JobComponent (line 17) | class JobComponent extends React.Component<Props, State> {
    method constructor (line 18) | constructor(props: Props) {
    method componentDidMount (line 26) | componentDidMount() {
    method shouldComponentUpdate (line 35) | shouldComponentUpdate(nextProps: Props, nextState: State) {
    method render (line 41) | render() {
    method jobNode (line 66) | private get jobNode(): HTMLDivElement {

FILE: src/views/JobHeaderComponent.tsx
  type Props (line 5) | interface Props {
  class JobHeaderComponent (line 13) | class JobHeaderComponent extends React.Component<Props, {}> {
    method render (line 14) | render() {

FILE: src/views/Main.tsx
  function main (line 31) | async function main() {

FILE: src/views/OutputComponent.tsx
  type RowProps (line 20) | interface RowProps {
  class RowComponent (line 24) | class RowComponent extends React.Component<RowProps, {}> {
    method shouldComponentUpdate (line 25) | shouldComponentUpdate(nextProps: RowProps) {
    method render (line 29) | render() {
  type Props (line 43) | interface Props {
  class OutputComponent (line 47) | class OutputComponent extends React.Component<Props, {}> {
    method componentDidMount (line 48) | componentDidMount() {
    method componentDidUpdate (line 52) | componentDidUpdate() {
    method render (line 56) | render() {

FILE: src/views/PrettifyToggleComponent.tsx
  type Props (line 4) | interface Props {

FILE: src/views/PromptComponent.tsx
  type Props (line 10) | interface Props {
  type Mode (line 15) | enum Mode {
  type State (line 20) | interface State {
  class PromptComponent (line 25) | class PromptComponent extends React.Component<Props, State> {
    method constructor (line 32) | constructor(props: Props) {
    method componentDidMount (line 42) | componentDidMount() {
    method componentDidUpdate (line 129) | componentDidUpdate(prevProps: Props, prevState: State) {
    method render (line 146) | render() {
    method setHistorySearchMode (line 154) | setHistorySearchMode() {
    method setNormalMode (line 158) | setNormalMode() {
    method acceptSelectedSuggestion (line 162) | acceptSelectedSuggestion() {
    method isInHistorySearchMode (line 172) | get isInHistorySearchMode(): boolean {
    method focus (line 176) | focus(): void {
    method clear (line 180) | clear(): void {
    method onReturnKeyPress (line 184) | onReturnKeyPress(): void {
    method appendLastLArgumentOfPreviousCommand (line 192) | async appendLastLArgumentOfPreviousCommand(): Promise<void> {
    method setValue (line 200) | setValue(value: string): void {
    method insertValueInPlace (line 207) | insertValueInPlace(value: string): void {
    method execute (line 212) | private async execute(): Promise<void> {
    method setPreviousHistoryItem (line 225) | private setPreviousHistoryItem(): void {
    method setNextHistoryItem (line 247) | private setNextHistoryItem(): void {
    method promptContentNode (line 265) | private get promptContentNode(): HTMLDivElement {
    method isEmpty (line 270) | private isEmpty(): boolean {
    method triggerSuggest (line 274) | private triggerSuggest() {
    method addShortcut (line 278) | private addShortcut(keybinding: number, handlerId: string) {
    method unbindDefaultAction (line 286) | private unbindDefaultAction(handlerId: string) {

FILE: src/views/SearchComponent.tsx
  class SearchComponent (line 5) | class SearchComponent extends React.Component<{}, {}> {
    method constructor (line 8) | constructor(props: any) {
    method render (line 14) | render() {
    method isFocused (line 27) | get isFocused(): boolean {
    method clearSelection (line 31) | clearSelection(): void {
    method blur (line 36) | blur() {
    method handleInput (line 40) | private handleInput(event: React.KeyboardEvent<HTMLInputElement>) {
    method input (line 52) | private get input(): HTMLInputElement {

FILE: src/views/SessionComponent.tsx
  type Props (line 14) | interface Props {
  class SessionComponent (line 20) | class SessionComponent extends React.Component<Props, {}> {
    method constructor (line 24) | constructor(props: Props) {
    method componentDidMount (line 28) | componentDidMount() {
    method render (line 33) | render() {
    method resizeSession (line 67) | resizeSession(): void {
    method status (line 74) | get status() {
    method session (line 79) | private get session() {
    method sessionRef (line 83) | private get sessionRef() {
    method footerRef (line 87) | private get footerRef() {
    method handleClick (line 91) | private handleClick() {
    method size (line 97) | private get size(): Size {
  type GitStatusProps (line 113) | type GitStatusProps = { directory: string };
  class GitStatusComponent (line 115) | class GitStatusComponent extends React.Component<GitStatusProps, GitStat...
    method constructor (line 118) | constructor(props: GitStatusProps) {
    method componentDidMount (line 126) | componentDidMount() {
    method componentWillUpdate (line 130) | componentWillUpdate(nextProps: GitStatusProps) {
    method componentWillUnmount (line 137) | componentWillUnmount() {
    method render (line 141) | render() {
    method subscribe (line 153) | private subscribe(directory: string) {

FILE: src/views/TabComponent.tsx
  type Props (line 5) | type Props = {
  class TabComponent (line 12) | class TabComponent extends React.Component<Props, {}> {
    method render (line 16) | render() {

FILE: src/views/TabHeaderComponent.tsx
  type Props (line 5) | interface Props {
  class TabHeaderComponent (line 12) | class TabHeaderComponent extends React.Component<Props, {}> {
    method render (line 13) | render() {

FILE: src/views/ViewUtils.ts
  function isModifierKey (line 3) | function isModifierKey(event: KeyboardEvent) {
  function setCaretPosition (line 7) | function setCaretPosition(node: Node, position: number) {
  function getCaretPosition (line 24) | function getCaretPosition(element: Node): number {

FILE: src/views/css/colors.ts
  function toRgb (line 48) | function toRgb(colorComponent: number) {
  function generateIndexedColors (line 56) | function generateIndexedColors() {
  function generateGreyScaleColors (line 66) | function generateGreyScaleColors() {
  function colorValue (line 73) | function colorValue(color: ColorCode, options = {isBright: false}) {

FILE: src/views/css/functions.ts
  function lighten (line 3) | function lighten(color: string, percent: number) {
  function darken (line 7) | function darken(color: string, percent: number) {
  function failurize (line 11) | function failurize(color: string) {

FILE: src/views/keyevents/Keybindings.ts
  type KeybindingType (line 9) | type KeybindingType = {
  function isCtrlOrCmd (line 14) | function isCtrlOrCmd(e: KeyboardEvent): boolean {
  function isKeybindingForEvent (line 86) | function isKeybindingForEvent(event: KeyboardEvent, action: KeyboardActi...
  type KeybindingMenuType (line 101) | type KeybindingMenuType = {
  function getAcceleratorForAction (line 175) | function getAcceleratorForAction(action: KeyboardAction): string {
  function isMenuShortcut (line 186) | function isMenuShortcut(event: KeyboardEvent): boolean {
  function toAccelerator (line 191) | function toAccelerator(event: KeyboardEvent): string {
  function handleUserEvent (line 218) | function handleUserEvent(application: ApplicationComponent, search: Sear...

FILE: src/views/menu/Menu.ts
  function buildMenuTemplate (line 7) | function buildMenuTemplate(

FILE: src/views/mouseevents/MouseEvents.ts
  function isDirectory (line 7) | function isDirectory(path: string): boolean {
  function handleMouseEvent (line 11) | function handleMouseEvent(application: ApplicationComponent, event: Mous...

FILE: test/e2e.ts
  class Page (line 8) | class Page {
    method constructor (line 11) | constructor(private client: SpectronClient) {}
    method waitTillLoaded (line 13) | waitTillLoaded() {
    method executeCommand (line 17) | executeCommand(command: string) {
    method prompt (line 24) | get prompt() {
    method job (line 28) | get job() {
    method footer (line 32) | get footer() {
  method constructor (line 38) | constructor(
  class Job (line 44) | class Job extends Block {
    method output (line 45) | get output() {
  class Footer (line 50) | class Footer extends Block {
    method presentDirectory (line 51) | get presentDirectory() {

FILE: test/output_spec.ts
  class DummyTerminal (line 9) | class DummyTerminal implements TerminalLikeDevice {
    method constructor (line 14) | constructor(dimensions: Dimensions = {columns: 80, rows: 80}) {
  type CSIFinalCharacter (line 19) | type CSIFinalCharacter = "A" | "B" | "C" | "D" | "E" | "F" | "R" | "m" |...
  function vttest (line 214) | function vttest(fileName: string, expectedOutput: string[]) {

FILE: test/utils/common_spec.ts
  type SimulatedKeyboardEvent (line 5) | interface SimulatedKeyboardEvent {
  function simulateKeyboardEvent (line 13) | function simulateKeyboardEvent(event: SimulatedKeyboardEvent) {

FILE: test/utils/history_trie_spec.ts
  function getSuggestions (line 5) | function getSuggestions(history: string[], input: string): string[] {

FILE: typings/Interfaces.d.ts
  type Size (line 1) | interface Size {
  type Dimensions (line 6) | interface Dimensions {
  type Advancement (line 11) | interface Advancement {
  type RowColumn (line 16) | interface RowColumn {
  type GitState (line 21) | type GitState = {
  type Margins (line 27) | interface Margins {
  type Dictionary (line 34) | interface Dictionary<T> {
  type ProcessEnvironment (line 38) | interface ProcessEnvironment extends Dictionary<string> {
  type EscapedShellWord (line 42) | type EscapedShellWord = string & {__isEscapedShellToken: any};
  type FullPath (line 43) | type FullPath = string & { __isFullPath: boolean };
  type ExistingAlias (line 44) | type ExistingAlias = string & { __isExistingAlias: boolean };
  type OneBasedPosition (line 45) | type OneBasedPosition = number;

FILE: typings/Overrides.d.ts
  type IntersectionObserverEntry (line 1) | interface IntersectionObserverEntry {
  type IntersectionObserverInit (line 10) | interface IntersectionObserverInit {
  type Window (line 28) | interface Window {
  class AnsiParser (line 33) | class AnsiParser {
  type Array (line 39) | interface Array<T> {
  type NodeBuffer (line 43) | interface NodeBuffer extends Uint8Array {
  type ObjectConstructor (line 47) | interface ObjectConstructor {

FILE: typings/mode-to-permissions.d.ts
  type PermittedGroups (line 1) | interface PermittedGroups {
  type Permissions (line 7) | interface Permissions {
Condensed preview — 157 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (672K chars).
[
  {
    "path": ".dockerignore",
    "chars": 36,
    "preview": "node_modules/\ndist/\ncompiled/\ntest/\n"
  },
  {
    "path": ".gitignore",
    "chars": 562,
    "preview": "/node_modules/\n/compiled/src/*\n/tmp/*\n/npm-debug.log\n/dist/*\n\n# Created by https://www.gitignore.io/api/osx\n\n### OSX ###"
  },
  {
    "path": ".node-version",
    "chars": 7,
    "preview": "8.11.0\n"
  },
  {
    "path": ".npmrc",
    "chars": 56,
    "preview": "save-exact = true\nregistry = https://registry.npmjs.org\n"
  },
  {
    "path": ".nvmrc",
    "chars": 8,
    "preview": "v8.11.0\n"
  },
  {
    "path": ".travis.yml",
    "chars": 1118,
    "preview": "language: node_js\n\nbefore_script:\n  - if [[ \"$TRAVIS_OS_NAME\" == \"linux\" ]]; then export DISPLAY=:99.0; sh -e /etc/init."
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 1544,
    "preview": "I have found a bug!\n-------------------\n\nAwesome, but before you [report it to us](issues/new), make sure to [check whet"
  },
  {
    "path": "Dockerfile",
    "chars": 187,
    "preview": "FROM node:8.11.0\n\nRUN mkdir /upterm\nWORKDIR /upterm\n\nCOPY package.json .\nCOPY .npmrc .\n\nRUN npm install\nCOPY . /upterm\nR"
  },
  {
    "path": "LICENSE",
    "chars": 1085,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 Volodymyr Shatsky\n\nPermission is hereby granted, free of charge, to any person"
  },
  {
    "path": "README.md",
    "chars": 3023,
    "preview": "[![Join the chat at https://gitter.im/railsware/upterm](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/upt"
  },
  {
    "path": "docs/vscodedebugging.md",
    "chars": 5486,
    "preview": "# Debugging Upterm in Visual Studio Code\n\nMicrosoft's open source Visual Studio Code (vscode) provides debugging for Typ"
  },
  {
    "path": "package.json",
    "chars": 3222,
    "preview": "{\n  \"name\": \"upterm\",\n  \"productName\": \"Upterm\",\n  \"description\": \"A terminal emulator for the 21st century.\",\n  \"versio"
  },
  {
    "path": "src/Autocompletion.ts",
    "chars": 1203,
    "preview": "import {leafNodeAt, ASTNode} from \"./shell/Parser\";\nimport * as _ from \"lodash\";\nimport {Environment} from \"./shell/Envi"
  },
  {
    "path": "src/Char.ts",
    "chars": 729,
    "preview": "import {Attributes} from \"./Interfaces\";\nimport {Brightness, Weight, Color} from \"./Enums\";\n\nexport const defaultAttribu"
  },
  {
    "path": "src/Decorators.ts",
    "chars": 1106,
    "preview": "import * as _ from \"lodash\";\n\nexport function memoize(resolver: ((...args: any[]) => any) | undefined = undefined) {\n   "
  },
  {
    "path": "src/EmitterWithUniqueID.ts",
    "chars": 197,
    "preview": "import * as events from \"events\";\n\nexport class EmitterWithUniqueID extends events.EventEmitter {\n    public id: number;"
  },
  {
    "path": "src/Enums.ts",
    "chars": 2301,
    "preview": "/**\n * @link https://css-tricks.com/snippets/javascript/javascript-keycodes/\n * @link https://lists.w3.org/Archives/Publ"
  },
  {
    "path": "src/Interfaces.ts",
    "chars": 1849,
    "preview": "import {Weight, Brightness} from \"./Enums\";\nimport {Stats} from \"fs\";\nimport {ReactElement} from \"react\";\nimport {Job} f"
  },
  {
    "path": "src/Output.ts",
    "chars": 40696,
    "preview": "import * as events from \"events\";\nimport {defaultAttributes, createChar, Char} from \"./Char\";\nimport * as i from \"./Inte"
  },
  {
    "path": "src/PTY.ts",
    "chars": 3454,
    "preview": "import * as ChildProcess from \"child_process\";\nimport * as OS from \"os\";\nimport * as _ from \"lodash\";\nimport * as pty fr"
  },
  {
    "path": "src/PluginManager.ts",
    "chars": 1630,
    "preview": "import {Prettyfier, EnvironmentObserverPlugin, AutocompletionProvider} from \"./Interfaces\";\nimport * as Path from \"path\""
  },
  {
    "path": "src/main/Main.ts",
    "chars": 1661,
    "preview": "import {app, ipcMain, nativeImage, BrowserWindow, screen} from \"electron\";\nimport {readFileSync} from \"fs\";\nimport {wind"
  },
  {
    "path": "src/monaco/Loader.ts",
    "chars": 1384,
    "preview": "export function requireMonaco(callback: () => void) {\n    const g = (global as any);\n    const nodeRequire = g.require;\n"
  },
  {
    "path": "src/monaco/PromptTheme.ts",
    "chars": 1462,
    "preview": "import {backgroundColor, colors, textColor} from \"../views/css/colors\";\n\nmonaco.editor.defineTheme(\"upterm-prompt-theme\""
  },
  {
    "path": "src/monaco/ShellHistoryLanguage.ts",
    "chars": 934,
    "preview": "import {services} from \"../services/index\";\nimport * as _ from \"lodash\";\n\nmonaco.languages.setMonarchTokensProvider(\"she"
  },
  {
    "path": "src/monaco/ShellLanguage.ts",
    "chars": 7343,
    "preview": "import {SessionID} from \"../shell/Session\";\nimport {getSuggestions} from \"../Autocompletion\";\nimport {services} from \".."
  },
  {
    "path": "src/plugins/AliasSuggestions.ts",
    "chars": 394,
    "preview": "import {services} from \"../services/index\";\n\nservices.jobs.onStart.subscribe(job => {\n    const input = job.prompt.value"
  },
  {
    "path": "src/plugins/DotEnvLoader.ts",
    "chars": 520,
    "preview": "import {Session} from \"../shell/Session\";\nimport {PluginManager} from \"../PluginManager\";\nimport * as Path from \"path\";\n"
  },
  {
    "path": "src/plugins/GitGrep.tsx",
    "chars": 1349,
    "preview": "import * as React from \"react\";\nimport {PluginManager} from \"../PluginManager\";\nimport {Job} from \"../shell/Job\";\nimport"
  },
  {
    "path": "src/plugins/JSON.tsx",
    "chars": 594,
    "preview": "import * as React from \"react\";\nimport {Job} from \"../shell/Job\";\nimport {PluginManager} from \"../PluginManager\";\nimport"
  },
  {
    "path": "src/plugins/JobFinishedNotifications.ts",
    "chars": 753,
    "preview": "import {services} from \"../services/index\";\nimport {remote} from \"electron\";\nimport {Status} from \"../Enums\";\n\nservices."
  },
  {
    "path": "src/plugins/NVM.ts",
    "chars": 885,
    "preview": "import {Session} from \"../shell/Session\";\nimport {PluginManager} from \"../PluginManager\";\nimport * as Path from \"path\";\n"
  },
  {
    "path": "src/plugins/PWDOperatingSystemIntegrator.ts",
    "chars": 378,
    "preview": "import {Session} from \"../shell/Session\";\nimport {PluginManager} from \"../PluginManager\";\nimport {remote} from \"electron"
  },
  {
    "path": "src/plugins/RVM.ts",
    "chars": 2959,
    "preview": "import {Session} from \"../shell/Session\";\nimport {PluginManager} from \"../PluginManager\";\nimport * as Path from \"path\";\n"
  },
  {
    "path": "src/plugins/SaveHistory.ts",
    "chars": 617,
    "preview": "import {appendFileSync} from \"fs\";\nimport {historyFilePath} from \"../utils/Common\";\nimport * as csvStringify from \"csv-s"
  },
  {
    "path": "src/plugins/SaveWindowBounds.ts",
    "chars": 230,
    "preview": "import {services} from \"../services/index\";\nimport {windowBoundsFilePath} from \"../utils/Common\";\nimport {outputJSON} fr"
  },
  {
    "path": "src/plugins/Show.tsx",
    "chars": 494,
    "preview": "import * as React from \"react\";\nimport {PluginManager} from \"../PluginManager\";\nimport {Job} from \"../shell/Job\";\n\nPlugi"
  },
  {
    "path": "src/plugins/UpdateLastPresentWorkingDirectory.ts",
    "chars": 262,
    "preview": "import {services} from \"../services/index\";\nimport {outputJSON} from \"fs-extra\";\nimport {presentWorkingDirectoryFilePath"
  },
  {
    "path": "src/plugins/completion/Brew.ts",
    "chars": 9827,
    "preview": "import {\n    emptyProvider,\n    longFlag,\n    provide,\n    shortFlag,\n    staticSuggestionsProvider,\n    Suggestion,\n} f"
  },
  {
    "path": "src/plugins/completion/Cat.ts",
    "chars": 346,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {anyFilesSuggestionsProvider} from \"../completion_utils/Common"
  },
  {
    "path": "src/plugins/completion/Cd.ts",
    "chars": 885,
    "preview": "import {directoriesSuggestionsProvider, Suggestion} from \"../completion_utils/Common\";\nimport * as _ from \"lodash\";\nimpo"
  },
  {
    "path": "src/plugins/completion/Cp.ts",
    "chars": 344,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {anyFilesSuggestionsProvider} from \"../completion_utils/Common"
  },
  {
    "path": "src/plugins/completion/Df.ts",
    "chars": 179,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {manPageOptions} from \"../../utils/ManPages\";\n\nPluginManager.r"
  },
  {
    "path": "src/plugins/completion/Executable.ts",
    "chars": 6931,
    "preview": "export const commandDescriptions: Dictionary<string> = {\n    admin: \"Create and administer SCCS files\",\n    alias: \"Defi"
  },
  {
    "path": "src/plugins/completion/Find.ts",
    "chars": 388,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {directoriesSuggestionsProvider} from \"../completion_utils/Com"
  },
  {
    "path": "src/plugins/completion/Git.ts",
    "chars": 18733,
    "preview": "import * as Git from \"../../utils/Git\";\nimport {\n    commandWithSubcommands,\n    emptyProvider,\n    longFlag,\n    provid"
  },
  {
    "path": "src/plugins/completion/Grep.ts",
    "chars": 14631,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {\n    longFlag, longAndShortFlag, mapSuggestions, anyFilesSugg"
  },
  {
    "path": "src/plugins/completion/History.ts",
    "chars": 1596,
    "preview": "import {HistoryRecord} from \"../../services/HistoryService\";\nimport {scan} from \"../../shell/Scanner\";\nimport {isAbsolut"
  },
  {
    "path": "src/plugins/completion/Ln.ts",
    "chars": 456,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {anyFilesSuggestionsProvider} from \"../completion_utils/Common"
  },
  {
    "path": "src/plugins/completion/Locate.ts",
    "chars": 187,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {manPageOptions} from \"../../utils/ManPages\";\n\nPluginManager.r"
  },
  {
    "path": "src/plugins/completion/Ls.ts",
    "chars": 380,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {directoriesSuggestionsProvider} from \"../completion_utils/Com"
  },
  {
    "path": "src/plugins/completion/Mkdir.ts",
    "chars": 356,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {directoriesSuggestionsProvider} from \"../completion_utils/Com"
  },
  {
    "path": "src/plugins/completion/Mv.ts",
    "chars": 344,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {anyFilesSuggestionsProvider} from \"../completion_utils/Common"
  },
  {
    "path": "src/plugins/completion/NPM.ts",
    "chars": 5036,
    "preview": "import * as Path from \"path\";\nimport {commandWithSubcommands} from \"../completion_utils/Common\";\nimport {io, mapObject} "
  },
  {
    "path": "src/plugins/completion/Ps.ts",
    "chars": 6308,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {combine} from \"../completion_utils/Combine\";\nimport {provide,"
  },
  {
    "path": "src/plugins/completion/Pwd.ts",
    "chars": 181,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {manPageOptions} from \"../../utils/ManPages\";\n\nPluginManager.r"
  },
  {
    "path": "src/plugins/completion/Rails.ts",
    "chars": 995,
    "preview": "import {commandWithSubcommands} from \"../completion_utils/Common\";\nimport {PluginManager} from \"../../PluginManager\";\n\nc"
  },
  {
    "path": "src/plugins/completion/Rake.ts",
    "chars": 399,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {directoriesSuggestionsProvider} from \"../completion_utils/Com"
  },
  {
    "path": "src/plugins/completion/Rm.ts",
    "chars": 344,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {anyFilesSuggestionsProvider} from \"../completion_utils/Common"
  },
  {
    "path": "src/plugins/completion/Scp.ts",
    "chars": 384,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {directoriesSuggestionsProvider} from \"../completion_utils/Com"
  },
  {
    "path": "src/plugins/completion/Shutdown.ts",
    "chars": 191,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {manPageOptions} from \"../../utils/ManPages\";\n\nPluginManager.r"
  },
  {
    "path": "src/plugins/completion/Tail.ts",
    "chars": 388,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {directoriesSuggestionsProvider} from \"../completion_utils/Com"
  },
  {
    "path": "src/plugins/completion/Top.ts",
    "chars": 4828,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {shortFlag, mapSuggestions} from \"../completion_utils/Common\";"
  },
  {
    "path": "src/plugins/completion/Vagrant.ts",
    "chars": 1156,
    "preview": "import {PluginManager} from \"../../PluginManager\";\nimport {linedOutputOf} from \"../../PTY\";\nimport {commandWithSubcomman"
  },
  {
    "path": "src/plugins/completion_utils/Button.tsx",
    "chars": 584,
    "preview": "import * as React from \"react\";\nimport {colors} from \"../../views/css/colors\";\n\nconst buttonStyles = (color: string) => "
  },
  {
    "path": "src/plugins/completion_utils/Combine.ts",
    "chars": 415,
    "preview": "import * as _ from \"lodash\";\nimport {AutocompletionContext, AutocompletionProvider} from \"../../Interfaces\";\nimport {Sug"
  },
  {
    "path": "src/plugins/completion_utils/Common.ts",
    "chars": 7670,
    "preview": "import {directoryName, escapeFilePath, io, resolveDirectory, userFriendlyPath} from \"../../utils/Common\";\nimport {Autoco"
  },
  {
    "path": "src/plugins/completion_utils/Descriptions.ts",
    "chars": 15548,
    "preview": "/* tslint:disable:max-line-length */\n\nexport const descriptions = {\n    git: {\n        subcommands: {\n            add: \""
  },
  {
    "path": "src/references.d.ts",
    "chars": 395,
    "preview": "/// <reference path=\"../typings/Overrides.d.ts\" />\n/// <reference path=\"../typings/Interfaces.d.ts\" />\n\n/// <reference p"
  },
  {
    "path": "src/services/FontService.ts",
    "chars": 1444,
    "preview": "import {Subject} from \"rxjs/Subject\";\n\nfunction getLetterSize(size: number, fontFamily: string) {\n    const height = siz"
  },
  {
    "path": "src/services/GitService.ts",
    "chars": 1894,
    "preview": "import {Observable} from \"rxjs/Observable\";\nimport {BehaviorSubject} from \"rxjs/BehaviorSubject\";\nimport \"rxjs/add/obser"
  },
  {
    "path": "src/services/HistoryService.ts",
    "chars": 1951,
    "preview": "import {readFileSync} from \"fs\";\nimport {historyFilePath} from \"../utils/Common\";\nimport * as _ from \"lodash\";\n\nimport c"
  },
  {
    "path": "src/services/JobsService.ts",
    "chars": 230,
    "preview": "import {Subject} from \"rxjs/Subject\";\nimport \"rxjs/add/observable/fromEvent\";\nimport {Job} from \"../shell/Job\";\n\n\nexport"
  },
  {
    "path": "src/services/SessionsService.ts",
    "chars": 1384,
    "preview": "import {Session, SessionID} from \"../shell/Session\";\nimport {Observable} from \"rxjs/Observable\";\nimport {Subject} from \""
  },
  {
    "path": "src/services/UpdatesService.ts",
    "chars": 1161,
    "preview": "import {remote} from \"electron\";\nimport * as https from \"https\";\n\nexport class UpdatesService {\n    isAvailable = false;"
  },
  {
    "path": "src/services/WindowService.ts",
    "chars": 1565,
    "preview": "import {remote} from \"electron\";\nimport {Observable} from \"rxjs/Observable\";\nimport \"rxjs/add/observable/fromEvent\";\nimp"
  },
  {
    "path": "src/services/index.ts",
    "chars": 851,
    "preview": "import {FontService} from \"./FontService\";\nimport {HistoryService} from \"./HistoryService\";\nimport {UpdatesService} from"
  },
  {
    "path": "src/shell/Aliases.ts",
    "chars": 1572,
    "preview": "import {loginShell} from \"../utils/Shell\";\nimport * as _ from \"lodash\";\n\nexport const aliasesFromConfig: Dictionary<stri"
  },
  {
    "path": "src/shell/BuiltInCommands.ts",
    "chars": 4871,
    "preview": "import {Job} from \"./Job\";\nimport {existsSync, statSync} from \"fs\";\nimport {homeDirectory, pluralize, resolveDirectory, "
  },
  {
    "path": "src/shell/CommandExecutor.ts",
    "chars": 4103,
    "preview": "import {Job} from \"./Job\";\nimport {Command} from \"./BuiltInCommands\";\nimport {PTY} from \"../PTY\";\nimport * as Path from "
  },
  {
    "path": "src/shell/Environment.ts",
    "chars": 3518,
    "preview": "import {delimiter} from \"path\";\nimport * as _ from \"lodash\";\nimport {executeCommandWithShellConfig} from \"../PTY\";\nimpor"
  },
  {
    "path": "src/shell/Job.ts",
    "chars": 3817,
    "preview": "import * as _ from \"lodash\";\nimport * as i from \"../Interfaces\";\nimport * as React from \"react\";\nimport {Session} from \""
  },
  {
    "path": "src/shell/Parser.ts",
    "chars": 13509,
    "preview": "import * as Scanner from \"./Scanner\";\nimport * as _ from \"lodash\";\nimport {memoizeAccessor} from \"../Decorators\";\nimport"
  },
  {
    "path": "src/shell/Prompt.ts",
    "chars": 1156,
    "preview": "import * as events from \"events\";\nimport {scan, Token, expandAliases} from \"./Scanner\";\nimport {CompleteCommand} from \"."
  },
  {
    "path": "src/shell/Scanner.ts",
    "chars": 7833,
    "preview": "import {Aliases} from \"./Aliases\";\n\nexport abstract class Token {\n    readonly raw: string;\n    readonly fullStart: numb"
  },
  {
    "path": "src/shell/Session.ts",
    "chars": 2991,
    "preview": "import {readFileSync} from \"fs\";\nimport {Job} from \"./Job\";\nimport * as events from \"events\";\nimport {PluginManager} fro"
  },
  {
    "path": "src/utils/Common.ts",
    "chars": 10388,
    "preview": "import * as walk from \"klaw\";\nimport * as Path from \"path\";\nimport * as i from \"./../Interfaces\";\nimport * as e from \"./"
  },
  {
    "path": "src/utils/Git.ts",
    "chars": 7055,
    "preview": "import {linedOutputOf} from \"../PTY\";\nimport * as Path from \"path\";\nimport * as fs from \"fs\";\nimport {executeCommand} fr"
  },
  {
    "path": "src/utils/HistoryTrie.ts",
    "chars": 3596,
    "preview": "import * as _ from \"lodash\";\nimport {fuzzyMatch} from \"./Common\";\nimport {scan} from \"../shell/Scanner\";\n\ninterface Trie"
  },
  {
    "path": "src/utils/JSONTree.tsx",
    "chars": 10273,
    "preview": "import * as React from \"react\";\nimport {colors} from \"../views/css/colors\";\n\n/*\n =========================\n * React JSON"
  },
  {
    "path": "src/utils/Link.tsx",
    "chars": 338,
    "preview": "import * as React from \"react\";\nimport * as e from \"electron\";\n\nexport const Link: React.StatelessComponent<{absolutePat"
  },
  {
    "path": "src/utils/ManPageParsingUtils.ts",
    "chars": 3182,
    "preview": "import {Suggestion} from \"../plugins/completion_utils/Common\";\n\nexport const combineManPageLines = (lines: string[]) => "
  },
  {
    "path": "src/utils/ManPages.ts",
    "chars": 1829,
    "preview": "import {execFile} from \"child-process-promise\";\nimport {contextIndependent, unique, Suggestion} from \"../plugins/complet"
  },
  {
    "path": "src/utils/OrderedSet.ts",
    "chars": 1035,
    "preview": "export abstract class AbstractOrderedSet<T> {\n    constructor(private storageGetter: () => T[], private storageSetter: ("
  },
  {
    "path": "src/utils/Process.ts",
    "chars": 2556,
    "preview": "import {executeCommandWithShellConfig} from \"../PTY\";\nimport {intersection} from \"lodash\";\n\n// http://linuxcommand.org/m"
  },
  {
    "path": "src/utils/Shell.ts",
    "chars": 4485,
    "preview": "import {basename} from \"path\";\nimport * as Path from \"path\";\nimport {resolveFile, io, isWindows, filterAsync, homeDirect"
  },
  {
    "path": "src/views/ApplicationComponent.tsx",
    "chars": 7314,
    "preview": "import {type as osType} from \"os\";\nimport * as classNames from \"classnames\";\nimport {TabHeaderComponent, Props} from \"./"
  },
  {
    "path": "src/views/JobComponent.tsx",
    "chars": 2093,
    "preview": "import * as React from \"react\";\nimport {Job} from \"../shell/Job\";\nimport {OutputComponent} from \"./OutputComponent\";\nimp"
  },
  {
    "path": "src/views/JobHeaderComponent.tsx",
    "chars": 813,
    "preview": "import * as React from \"react\";\nimport {PrettifyToggleComponent} from \"./PrettifyToggleComponent\";\nimport {Job} from \".."
  },
  {
    "path": "src/views/Main.tsx",
    "chars": 2553,
    "preview": "import {handleUserEvent} from \"./keyevents/Keybindings\";\nimport {handleMouseEvent} from \"./mouseevents/MouseEvents\";\n\npr"
  },
  {
    "path": "src/views/OutputComponent.tsx",
    "chars": 2422,
    "preview": "import * as React from \"react\";\nimport {Char} from \"../Char\";\nimport {groupWhen} from \"../utils/Common\";\nimport {List} f"
  },
  {
    "path": "src/views/PrettifyToggleComponent.tsx",
    "chars": 364,
    "preview": "import * as React from \"react\";\nimport {fontAwesome} from \"./css/FontAwesome\";\n\ninterface Props {\n    prettifyToggler: ("
  },
  {
    "path": "src/views/PromptComponent.tsx",
    "chars": 8965,
    "preview": "/// <reference path=\"../../node_modules/monaco-editor/monaco.d.ts\" />\n\nimport * as _ from \"lodash\";\nimport * as React fr"
  },
  {
    "path": "src/views/SearchComponent.tsx",
    "chars": 1614,
    "preview": "import * as React from \"react\";\nimport {remote} from \"electron\";\nimport {fontAwesome} from \"./css/FontAwesome\";\n\nexport "
  },
  {
    "path": "src/views/SessionComponent.tsx",
    "chars": 5016,
    "preview": "import * as React from \"react\";\nimport * as _ from \"lodash\";\nimport {SessionID} from \"../shell/Session\";\nimport {Job} fr"
  },
  {
    "path": "src/views/TabComponent.tsx",
    "chars": 1772,
    "preview": "import {SessionComponent} from \"./SessionComponent\";\nimport * as React from \"react\";\nimport {SessionID} from \"../shell/S"
  },
  {
    "path": "src/views/TabHeaderComponent.tsx",
    "chars": 791,
    "preview": "/* tslint:disable:no-unused-variable */\nimport * as React from \"react\";\nimport {fontAwesome} from \"./css/FontAwesome\";\n\n"
  },
  {
    "path": "src/views/ViewUtils.ts",
    "chars": 1154,
    "preview": "import {KeyCode} from \"../Enums\";\n\nexport function isModifierKey(event: KeyboardEvent) {\n    return [KeyCode.Shift, KeyC"
  },
  {
    "path": "src/views/css/FontAwesome.ts",
    "chars": 17822,
    "preview": "export const fontAwesome = {\n    adjust: \"\\uf042\",\n    adn: \"\\uf170\",\n    alignCenter: \"\\uf037\",\n    alignJustify: \"\\uf0"
  },
  {
    "path": "src/views/css/colors.ts",
    "chars": 1992,
    "preview": "import * as _ from \"lodash\";\nimport {ColorCode} from \"../../Interfaces\";\nimport {darken} from \"./functions\";\n\nexport con"
  },
  {
    "path": "src/views/css/functions.ts",
    "chars": 398,
    "preview": "const tinyColor: any = require(\"tinycolor2\");\n\nexport function lighten(color: string, percent: number) {\n    return tiny"
  },
  {
    "path": "src/views/css/styles.ts",
    "chars": 2110,
    "preview": "import {Weight, Brightness, Color} from \"../../Enums\";\nimport {backgroundColor, colors, colorValue, textColor} from \"./c"
  },
  {
    "path": "src/views/index.html",
    "chars": 15614,
    "preview": "<!DOCTYPE html>\n<html>\n\n    <head>\n        <meta charset=\"utf-8\" />\n        <title>Upterm</title>\n        <style>\n      "
  },
  {
    "path": "src/views/keyevents/Keybindings.ts",
    "chars": 9707,
    "preview": "import {KeyCode, KeyboardAction, Status} from \"../../Enums\";\nimport {error} from \"../../utils/Common\";\nimport {SearchCom"
  },
  {
    "path": "src/views/menu/Menu.ts",
    "chars": 6201,
    "preview": "import {KeyboardAction} from \"../../Enums\";\nimport {remote} from \"electron\";\nimport {getAcceleratorForAction} from \"../k"
  },
  {
    "path": "src/views/mouseevents/MouseEvents.ts",
    "chars": 1143,
    "preview": "import {ApplicationComponent} from \"../ApplicationComponent\";\nimport {MouseEvent} from \"../../Interfaces\";\nimport * as f"
  },
  {
    "path": "test/e2e.ts",
    "chars": 2738,
    "preview": "import {Application, SpectronClient} from \"spectron\";\nimport {expect} from \"chai\";\nimport {join} from \"path\";\nimport {us"
  },
  {
    "path": "test/environment_spec.ts",
    "chars": 1009,
    "preview": "import \"mocha\";\nimport {expect} from \"chai\";\nimport {Environment, preprocessEnv} from \"../src/shell/Environment\";\n\ndescr"
  },
  {
    "path": "test/output_spec.ts",
    "chars": 30369,
    "preview": "/// <reference path=\"../typings/Interfaces.d.ts\" />\n\nimport \"mocha\";\nimport {expect} from \"chai\";\nimport {Output} from \""
  },
  {
    "path": "test/pty_spec.ts",
    "chars": 706,
    "preview": "import \"mocha\";\nimport {expect} from \"chai\";\nimport {PTY} from \"../src/PTY\";\nimport {scan} from \"../src/shell/Scanner\";\n"
  },
  {
    "path": "test/references.d.ts",
    "chars": 52,
    "preview": "/// <reference path=\"../typings/Interfaces.d.ts\" />\n"
  },
  {
    "path": "test/shell/scanner_spec.ts",
    "chars": 6928,
    "preview": "import {expect} from \"chai\";\nimport {\n    scan, Word, DoubleQuotedStringLiteral, SingleQuotedStringLiteral, CompositeStr"
  },
  {
    "path": "test/test_files/file_names_test/file with brackets()",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "test/test_files/vttest/1-1",
    "chars": 5798,
    "preview": "\u0007\u001b[0c\u001b[?1l\u001b[?3l\u001b[?4l\u001b[?5l\u001b[?6l\u001b[?7h\u001b[?8l\u001b[?40h\u001b[?45l\u001b[r\u001b[0m\u001b[2J\u001b[3;10HVT100 test program, version 2.7 (20140305)\u001b[4;10HL"
  },
  {
    "path": "test/test_files/vttest/1-2",
    "chars": 13228,
    "preview": "\u0007\u001b[0c\u001b[?1l\u001b[?3l\u001b[?4l\u001b[?5l\u001b[?6l\u001b[?7h\u001b[?8l\u001b[?40h\u001b[?45l\u001b[r\u001b[0m\u001b[2J\u001b[3;10HVT100 test program, version 2.7 (20140305)\u001b[4;10HL"
  },
  {
    "path": "test/test_files/vttest/1-3",
    "chars": 777,
    "preview": "\u001b[?3l\u001b[?3lTest of autowrap, mixing control and print characters.\r\r\nThe left/right margins should have letters in order:\r"
  },
  {
    "path": "test/test_files/vttest/1-4",
    "chars": 811,
    "preview": "\u001b[?3hTest of autowrap, mixing control and print characters.\r\r\nThe left/right margins should have letters in order:\r\r\n\u001b[3"
  },
  {
    "path": "test/test_files/vttest/1-5",
    "chars": 338,
    "preview": "\u001b[?3l\u001b[2J\u001b[1;1HTest of cursor-control characters inside ESC sequences.\r\r\nBelow should be four identical lines:\r\r\n\r\r\nA B "
  },
  {
    "path": "test/test_files/vttest/1-6",
    "chars": 814,
    "preview": "\u001b[2J\u001b[1;1HTest of leading zeros in ESC sequences.\r\r\nTwo lines below you should see the sentence \"This is a correct sente"
  },
  {
    "path": "test/test_files/vttest/2-1",
    "chars": 537,
    "preview": "\u001b[?3l\u001b[2J\u001b[1;1H\u001b[?7h****************************************************************************************************"
  },
  {
    "path": "test/test_files/vttest/2-10",
    "chars": 17694,
    "preview": "\u001b[0c\u001b[?1l\u001b[?3l\u001b[?4l\u001b[?5l\u001b[?6l\u001b[?7h\u001b[?8l\u001b[?40h\u001b[?45l\u001b[r\u001b[0m\u001b[2J\u001b[3;10HVT100 test program, version 2.7 (20140305)\u001b[4;10HLi"
  },
  {
    "path": "test/test_files/vttest/2-11",
    "chars": 17853,
    "preview": "\u001b[0c\u001b[?1l\u001b[?3l\u001b[?4l\u001b[?5l\u001b[?6l\u001b[?7h\u001b[?8l\u001b[?40h\u001b[?45l\u001b[r\u001b[0m\u001b[2J\u001b[3;10HVT100 test program, version 2.7 (20140305)\u001b[4;10HLi"
  },
  {
    "path": "test/test_files/vttest/2-12",
    "chars": 18000,
    "preview": "\u001b[0c\u001b[?1l\u001b[?3l\u001b[?4l\u001b[?5l\u001b[?6l\u001b[?7h\u001b[?8l\u001b[?40h\u001b[?45l\u001b[r\u001b[0m\u001b[2J\u001b[3;10HVT100 test program, version 2.7 (20140305)\u001b[4;10HLi"
  },
  {
    "path": "test/test_files/vttest/2-13",
    "chars": 18581,
    "preview": "\u001b[0c\u001b[?1l\u001b[?3l\u001b[?4l\u001b[?5l\u001b[?6l\u001b[?7h\u001b[?8l\u001b[?40h\u001b[?45l\u001b[r\u001b[0m\u001b[2J\u001b[3;10HVT100 test program, version 2.7 (20140305)\u001b[4;10HLi"
  },
  {
    "path": "test/test_files/vttest/2-14",
    "chars": 18628,
    "preview": "\u001b[0c\u001b[?1l\u001b[?3l\u001b[?4l\u001b[?5l\u001b[?6l\u001b[?7h\u001b[?8l\u001b[?40h\u001b[?45l\u001b[r\u001b[0m\u001b[2J\u001b[3;10HVT100 test program, version 2.7 (20140305)\u001b[4;10HLi"
  },
  {
    "path": "test/test_files/vttest/2-15",
    "chars": 1347,
    "preview": "\u001b[?5l\u001b[2J\u001b[8;12Hnormal\u001b[8;24Hbold\u001b[8;36Hunderscored\u001b[8;48Hblinking\u001b[8;60Hreversed\u001b[10;1Hstars:\u001b[12;1Hline:\u001b[14;1Hx'es:\u001b["
  },
  {
    "path": "test/test_files/vttest/2-2",
    "chars": 502,
    "preview": "\u001b[2J\u001b[3g\u001b[1;1H\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C\u001bH\u001b[3C"
  },
  {
    "path": "test/test_files/vttest/2-3",
    "chars": 2933,
    "preview": "\u001b[0c\u001b[?1l\u001b[?3l\u001b[?4l\u001b[?5l\u001b[?6l\u001b[?7h\u001b[?8l\u001b[?40h\u001b[?45l\u001b[r\u001b[0m\u001b[2J\u001b[3;10HVT100 test program, version 2.7 (20140305)\u001b[4;10HLi"
  },
  {
    "path": "test/test_files/vttest/2-4",
    "chars": 3908,
    "preview": "\u001b[0c\u001b[?1l\u001b[?3l\u001b[?4l\u001b[?5l\u001b[?6l\u001b[?7h\u001b[?8l\u001b[?40h\u001b[?45l\u001b[r\u001b[0m\u001b[2J\u001b[3;10HVT100 test program, version 2.7 (20140305)\u001b[4;10HLi"
  },
  {
    "path": "test/test_files/vttest/2-5",
    "chars": 5052,
    "preview": "\u001b[0c\u001b[?1l\u001b[?3l\u001b[?4l\u001b[?5l\u001b[?6l\u001b[?7h\u001b[?8l\u001b[?40h\u001b[?45l\u001b[r\u001b[0m\u001b[2J\u001b[3;10HVT100 test program, version 2.7 (20140305)\u001b[4;10HLi"
  },
  {
    "path": "test/test_files/vttest/2-6",
    "chars": 6009,
    "preview": "\u001b[0c\u001b[?1l\u001b[?3l\u001b[?4l\u001b[?5l\u001b[?6l\u001b[?7h\u001b[?8l\u001b[?40h\u001b[?45l\u001b[r\u001b[0m\u001b[2J\u001b[3;10HVT100 test program, version 2.7 (20140305)\u001b[4;10HLi"
  },
  {
    "path": "test/test_files/vttest/2-7",
    "chars": 8940,
    "preview": "\u001b[0c\u001b[?1l\u001b[?3l\u001b[?4l\u001b[?5l\u001b[?6l\u001b[?7h\u001b[?8l\u001b[?40h\u001b[?45l\u001b[r\u001b[0m\u001b[2J\u001b[3;10HVT100 test program, version 2.7 (20140305)\u001b[4;10HLi"
  },
  {
    "path": "test/test_files/vttest/2-8",
    "chars": 2918,
    "preview": "\u001b[1;24r\u001b[2J\u001b[24BSoft scroll up region [1..24] size 24 Line 1\r\nSoft scroll up region [1..24] size 24 Line 2\r\nSoft scroll "
  },
  {
    "path": "test/test_files/vttest/2-9",
    "chars": 14778,
    "preview": "\u001b[0c\u001b[?1l\u001b[?3l\u001b[?4l\u001b[?5l\u001b[?6l\u001b[?7h\u001b[?8l\u001b[?40h\u001b[?45l\u001b[r\u001b[0m\u001b[2J\u001b[3;10HVT100 test program, version 2.7 (20140305)\u001b[4;10HLi"
  },
  {
    "path": "test/utils/ManPages_spec.ts",
    "chars": 3382,
    "preview": "import \"mocha\";\nimport {expect} from \"chai\";\n\nimport {\n  combineManPageLines,\n  preprocessManPage,\n  extractManPageSecti"
  },
  {
    "path": "test/utils/common_spec.ts",
    "chars": 1484,
    "preview": "import \"mocha\";\nimport {expect} from \"chai\";\nimport {commonPrefix, fuzzyMatch, normalizeProcessInput} from \"../../src/ut"
  },
  {
    "path": "test/utils/history_trie_spec.ts",
    "chars": 3311,
    "preview": "import \"mocha\";\nimport {expect} from \"chai\";\nimport {HistoryTrie} from \"../../src/utils/HistoryTrie\";\n\nfunction getSugge"
  },
  {
    "path": "test/utils/ordered_set_spec.ts",
    "chars": 695,
    "preview": "import \"mocha\";\nimport {expect} from \"chai\";\nimport {OrderedSet} from \"../../src/utils/OrderedSet\";\n\ndescribe(\"ordered s"
  },
  {
    "path": "tsconfig.json",
    "chars": 514,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES6\",\n    \"module\": \"commonjs\",\n    \"removeComments\": true,\n    \"preserveConstEn"
  },
  {
    "path": "tslint.json",
    "chars": 2458,
    "preview": "{\n  \"rules\": {\n    \"align\": [\n      true,\n      \"parameters\",\n      \"arguments\",\n      \"statements\"\n    ],\n    \"ban\": [\n"
  },
  {
    "path": "typings/Interfaces.d.ts",
    "chars": 831,
    "preview": "interface Size {\n    height: number;\n    width: number;\n}\n\ninterface Dimensions {\n    columns: number;\n    rows: number;"
  },
  {
    "path": "typings/Overrides.d.ts",
    "chars": 1650,
    "preview": "interface IntersectionObserverEntry {\n    readonly time: number;\n    readonly rootBounds: ClientRect | DOMRect;\n    read"
  },
  {
    "path": "typings/child-process-promise.d.ts",
    "chars": 149,
    "preview": "declare module \"child-process-promise\" {\n  function execFile(file: string, args: string[], options: {}): Promise<{stdout"
  },
  {
    "path": "typings/dirStat.d.ts",
    "chars": 106,
    "preview": "declare module \"dirStat\" {\n  function dirStat(path: string, cb: (err: any, results: any) => void): void\n}\n"
  },
  {
    "path": "typings/mode-to-permissions.d.ts",
    "chars": 371,
    "preview": "interface PermittedGroups {\n    owner: boolean;\n    group: boolean;\n    others: boolean;\n}\n\ninterface Permissions {\n    "
  },
  {
    "path": "typings/uuid.d.ts",
    "chars": 50,
    "preview": "declare module \"uuid\" {\n  function v4(): string\n}\n"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the railsware/upterm GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 157 files (582.8 KB), approximately 170.0k tokens, and a symbol index with 651 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!