Remove obsolete stuffs

This commit is contained in:
leokhoa
2025-10-05 17:33:37 +02:00
parent 71b1fe4850
commit 1c759708e4
15680 changed files with 4890893 additions and 139873 deletions

View File

@@ -0,0 +1,27 @@
# See https://github.com/ignacio/lua-appveyor-example for reference
clone_depth: 1
init:
- '"C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\vcvarsall.bat""'
- set PATH=C:\Python27\Scripts;%PATH%
cache:
# - .lua -> .appveyor.yml
- c:\cache -> .appveyor.yml
install:
- pip install hererocks codecov
- hererocks .lua -l5.1 -rlatest --downloads c:\cache\d --builds c:\cache\bat
- .lua\bin\activate
- luarocks install busted
- luarocks install cluacov
- luarocks install luacheck
build: off
test_script:
- luacheck .
- busted
after_test:
- codecov -X gcov -f luacov.report.out

View File

@@ -0,0 +1,7 @@
return {
default = {
coverage = true,
verbose = true,
lpath = "./modules/?.lua"
}
}

Binary file not shown.

View File

@@ -0,0 +1,10 @@
.history
*.sublime-*
settings
# testing stuff
lua_modules
luacov.*.out
#local lua
.lua

View File

@@ -0,0 +1,3 @@
-- The line below extends package.path with modules
-- directory to allow to require them
package.path = debug.getinfo(1, "S").source:match[[^@?(.*[\/])[^\/]-$]] .."modules/?.lua;".. package.path

View File

@@ -0,0 +1,7 @@
return {
exclude_files = { ".lua", "modules/JSON.lua", "lua_modules" },
files = {
spec = { std = "+busted" },
},
globals = { "clink", "rl_state", "rl", "settings", "log", "path" }
}

View File

@@ -0,0 +1,6 @@
return {
include = { "modules/*" },
exclude = { "lua_modules/*", ".lua/*", "modules/clink_version.lua" },
deletestats = false,
runreport = true
}

View File

@@ -0,0 +1,17 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "0.1.0",
"command": "cmd",
"args": ["/c"],
"isShellCommand": true,
"showOutput": "silent",
"tasks": [
{
"taskName": "test",
"isTestCommand": true,
"showOutput": "always",
"suppressTaskName": false
}
]
}

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Vladimir Kotikov
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.

View File

@@ -0,0 +1,41 @@
[![Build status](https://ci.appveyor.com/api/projects/status/h401gvqery4wwa6p/branch/master?svg=true)](https://ci.appveyor.com/project/vladimir-kotikov/clink-completions/branch/master)
[![codecov](https://codecov.io/gh/vladimir-kotikov/clink-completions/branch/master/graph/badge.svg)](https://codecov.io/gh/vladimir-kotikov/clink-completions)
clink-completions
=================
Completion files to [clink](https://github.com/mridgers/clink) util. Bundled with [Cmder](https://github.com/cmderdev/cmder).
Notes
=====
Master branch of this repo contains all available completions. If you lack some functionality, post a feature request.
Some of completion generators in this bundle uses features from latest clink distribuition. If you get an error messages in console while using these completions, consider upgrading clink to latest version.
If this doesn't help, feel free to submit an issue.
Development and contribution
============================
The new flow is single `master` branch for all more or less valuable changes. The `master` should be clean and show nice history of project. The bugfixes are made and land directly into `master`.
The `dev` branch is intended to be used as a staging branch for current or incompleted work. The `dev` branch is unstable and contributors and users should never rely on it since its history can overwritten at the moment, some commits may be squashed, etc.
The feature development should be done in separate branch per feature. The completed features then should be merged into master as a single commit with meaningful description.
The PRs should be submitted from corresponding feature branches directly to `master`.
Requirements
============
These completions requires clink@0.4.3 or higher version
# Test
You will need `busted` package to be installed locally (to `lua_modules` directory). To install it
using Luarocks call `luarocks install --tree=lua_modules busted`. You might also want to install
`luacov` to get the coverage information.
After installing call `test.bat` from repo root and watch tests passing. That's it.

View File

@@ -0,0 +1,189 @@
# Release Notes
## 0.3.7 (Apr 10, 2021)
* 0a9ea6b [ssh] Allow - in known hosts (#139)
* e2784e0 [cmder] Check for global cmderGitStatusOptIn var (#141)
* dc590e8 [git] Colored completions for `git checkout ...` with Clink v1.1.12 popup list (#135)
* a9b3134 [common] Update JSON.lua (#137)
* 4cf49eb [scoop] Fix scoop config discovery (#134)
## 0.3.6 (Dec 16, 2020)
* c9ed54d [git] Fix stash completions (0 based). (#133)
* 82a0311 [git] Fix stash completion to work west of GMT. (#132)
* a63cbca [git] Add completions for git-worktree (#130)
* b6a521f [scoop] added commands "hold" and "unhold" (#129)
* f639287 [npm] Extend completions (#125)
* 04541ff [git] Add support for `git remote get-url ...` (#124)
## 0.3.5 (Dec 5, 2019)
* eb3099e [git] Add `restore` and `switch` commands (#119)
* 50954bc [.net] Add completions for dotnet (#120)
* aa0541f [k8s] Basic kubectl completion script (#113)
* a3339f8 [py] Added pipenv completion (#111)
* 8228a33 [py] Added pip completion (#110)
* b366d5d [scoop] Added scoop completions (#109)
* 4a8056d [.net] Add netcoreapp3.1 (#123)
## 0.3.4 (Aug 19, 2019)
Improvements/bugfixes for git completions/prompt
* f85c7a1 [git] fix gsub branch (#114)
* bf114aa [git] Add support for detecting branch names in worktrees (#96)
* 5d33037 [git] Add missing clone options for git (#106)
* b2d207d [net] Add three remaining help topics (#107)
* 781c0bf Don't default to origin if no remote is configured (#102)
## 0.3.3 (Oct 24, 2017)
A lot of improvements for vagrant completions (thanks to @Andegawen) and a few bugfixes for `yarn`, `ssh` and `git`.
* `af5f6d1` [git] Fix git main worktree detection (#95)
* `032ff0c` [vagrant] Close Vagrantfile after usage (#93)
* `757c096` [vagrant] Enhance regex for finding provision names (#91)
* `84884db` [vagrant] Vagrant list provisions on `--provision-with` (#88)
* `59055f7` [vagrant] add `global-status` and `snapshot` commands (#86)
* `e4d562a` [ssh] Improves pattern matching for searching hosts (#85)
* `34d3c0c` [common] Make luacheck happy (#83)
* `f1898a0` [git] Support completing files for `git diff` (#82)
* `c288656` [yarn] Suggest installed executables for yarn run
* `162d402` [common] Fix arguments clobbering 'table' class
* `a552d8c` [chore] Remove trailing whitespace to pass CI (#70)
* `3f635f9` [yarn] Upgrade commands for Yarn v0.17.8 (#69)
* `b76867a` [git] Add support for fetch --all (#68)
* `8edbf28` Add completions for angular-cli (#67)
* `9cc940c` [common] Enable luacheck
* `a369227` [common] Configure CI
* `0714e67` [common] Add tests for funclib and color modules
* `a4c83df` [test] Add test harness and instructions
* `834dbf3` [git] Display git push destination in prompt
## 0.3.2 (Nov 6, 2016)
This release adds completions for `yarn` package manager and a bunch of minor improvements and bugfixes
* `9789bc8` [npm] Improve prompt output in some situations
* `795f6a9` [npm] Resolve lua error when package.json is empty
* `fea1e21` [git] Add completions for 'git difftool'
* `f840079` Add completions for Yarn v0.14
* `8400a8b` [git] Add basic completions for cherry-pick
* `f411878` [git] Complete branches in `git reset`
* `83c71e1` [vagrant] Fix help parser for Vagrant completions
* `2845966` [npm] Add version flag
* `1e3931f` [git] '--prune' option for 'fetch'
* `cc51616` [cordova] Add statusbar to core plugins
## 0.3.1 (June 11, 2016)
This release adds a few fixes and small improvements for `npm` prompt and completions
* `f2e335d` [npm] Do not query global modules when completing FS paths in 'npm link'
* `c59c0d9` [npm] Improve package.json handling for npm prompt
* `6edf054` [npm] Do not fetch package name and version for private packages
* `23d7599` [npm] Improve package.json parsing
## 0.3.0 (May 8, 2016)
This release adds support for completions inside of git submodules and a completions for a couple of new commands (`ssh` and `nvm`)
* `21464d1` [ssh] Refactor hosts search logic
* `26f4f99` [ssh] Add ssh completion from known_hosts file
* `9a4d308` [nvm] Add basic nvm completions
* `3c25f96` [git] Housekeeping
* `b39e617` [git] Fix fetch --tags completion
* `99140d1` [git] Allow multiple branches for git branch -d
* `087874b` [cordova] Add a couple of new completions for coho
* `e4cf69d` [cordova] Remove old core plugin IDs from 'plugin add/rm'
* `a14af9c` [git] Adds basic support for submodules
* `e2467f6` [choco] Fix chocolatey non-meta packages listing
* `9540aa6` [npm] Adds 'npm outdated' flags
* `91cef45` [ssh] Adds ssh autocomplete script
## 0.2.2 (Dec 10, 2015)
Another bugfix release. Multiple small fixes for git inclded.
* `83ef129` [git] Fixes failure when trying to complete git commmands outside of repo
* `7f4c223` [git] add merge strategies and options parsers to pull/rebase/checkout
* `faf92f2` [git] Distinguish real and suggestes branch names
* `ad24a7f` [git] Adds "core.trustctime" to available options
* `e6921a3` [npm] Query npm config lazily (only when required by completions)
* `03bec42` [git] Adds completions for `git remote update`
* `2ea5f33` [git] Close packed-refs after reading
* `e92d5a2` [git] Complete non-checked local branches based on remote ones.
* `a68ed47` [git] List remote branches based on packed-refs file.
## 0.2.1 (Oct 21, 2015)
Minor bugfix release for 0.2.0. This release mostly fixes various bugs, found after 0.2.0 is out.
* `1cea322` [npm] Fix npm prompt failure when parsing malformed package.json
* `cfaf17d` [git] Remove ugly error message when trying to complete git aliases without git in PATH
* `d2ac838` [git] Fixes broken 'git add'. This closes #34
* `e09a9b0` [git] Adds user.name and user.email to known options
* `6999fdf` [npm] Fixes issue with completing 'npm run' in non-npm directory. This fixes #33
* `46fd830` [npm] Handle package scripts with quotes properly
* `c20e421` [common] Merge npm prompt into regular 'npm' module
* `4050dc9` [npm] Complete global packages and local dirs for npm link
## 0.2.0 (Oct 05, 2015)
#### Git
* `b9a80e8` [git] Complete remotes using gitconfig
* `c8e1ac5` [git] Adds local branches to git checkout (was broken by 751ed21)
* `2f1ea08` [git] Improves branches completion for git push
* `751ed21` [git] Fixes checkout completion to list branches correctly.
* `33a086a` [git] Adds completion for git config
* `822e92e` [git] Adds git stash completion
* `b9be7d8` [git] Adds completion of nested branches (prefix/branch)
* `c7e4f3d` [git] Refactors git completions logic
* `5c589fd` [git] Fixes matchers usage
* `9eb775f` [git] Refactors git completions logic, adds git reset completion
* `94b6a71` [git] Adds alias autocompletion
* `7f1ea3b` [git] Adds autcompletion for remote branches
* `579ff78` [git] Adds git-svn autocompletion
* `dea2c04` [git] Adds completions for git remote command
* `f692cd4` [git] Removes unexistent commands like rebase--*
#### Chocolatey
* `e6efea2` [choco] Adds feature parser
* `2fbb271` [choco] Updates choco completions according to v0.9.9
#### Cordova
* `524b88e` [coho] Adds more commands
* `57762ef` [cordova] Adds --browserify flag
* `a1caddb` [coho] Complete repo names
* `2258ff9` [coho] Adds merge-pr command
* `04d46e9` [coho] Adds npm-link
#### NPM
* `f9af8fe` [npm] Adds support for 'npm publish'
* `5875a6e` [npm] Fixes module loading when Node is not installed
* `7132894` [npm] Adds npm update and npm cache completions
#### Common
* `3e4c88d` [common] Refactor to reuse table wrapper where possible
* `f2ba478` [common] Fixes problem with dirs matchers
* `7869df4` [common] Implements tables wrapper
* `eafc11b` [common] Removes unwanted . and .. directories in some completions
* `3f8cd6b` [common] Adds development/contribution notes
* `7920243` [common] Slightly updates funclib, adds luadoc
* `f66b0c2` Remove outdated info about extended branch.
* `3c023d3` Fix for Nil needle value when calling clink.is_match()
* `2491d21` [common] Updates completions to depend on shared modules
* `d91ba44` [common] Factors various util functions into modules system
* `1b48a48` [common] Merges extended completions into master
* `eaefce3` [common] Adds link to Clink to README
## 0.1.0 (Mar 20, 2015)
Initial release. No changelog until this moment.

View File

@@ -0,0 +1,194 @@
local parser = clink.arg.new_parser
local addon_parser = parser({
"--dry-run", "-d",
"--verbose", "-v",
"--blueprint", "-b",
"--skip-npm", "-sn",
"--skip-bower", "-sb",
"--skip-git", "-sg",
"--directory", "-dir"
})
local asset_sizes_parser = parser({
"--output-path", "-o"
})
local build_parser = parser({
"--environment=", "-e",
"--environment=dev", "-dev",
"--environment=prod", "-prod",
"--output-path", "-o",
"--watch", "-w",
"--watcher",
"--suppress-sizes",
"--target", "-t",
"--target=development", "-dev",
"--target=production", "-prod",
"--base-href", "-bh",
"--aot"
})
local destroy_parser = parser({
"--dry-run", "-d",
"--verbose", "-v",
"--pod", "-p",
"--classic", "-c",
"--dummy", "-dum", "-id",
"--in-repo-addon", "--in-repo", "-ir"
})
local generate_parser = parser({
"class", "cl",
"component", "c",
"directive", "d",
"enum", "e",
"module", "m",
"pipe", "p",
"route", "r",
"service", "s"
},{
"--dry-run", "-d",
"--verbose", "-v",
"--pod", "-p",
"--classic", "-c",
"--dummy", "-dum", "-id",
"--in-repo-addon", "--in-repo", "-ir"
})
local help_parser = parser({
"--verbose", "-v",
"--json"
})
local init_parser = parser({
"--dry-run", "-d",
"--verbose", "-v",
"--blueprint", "-b",
"--skip-npm", "-sn",
"--skip-bower", "-sb",
"--name", "-n",
"--link-cli", "-lc",
"--source-dir", "-sd",
"--style", "--style=sass", "--style=scss", "--style=less", "--style=stylus",
"--prefix", "-p",
"--mobile",
"--routing",
"--inline-style", "-is",
"--inline-template", "-it"
})
local new_parser = parser({
"--dry-run", "-d",
"--verbose", "-v",
"--blueprint", "-b",
"--skip-npm", "-sn",
"--skip-git", "-sg",
"--directory", "-dir",
"--link-cli", "-lc",
"--source-dir", "-sd",
"--style",
"--prefix", "-p",
"--mobile",
"--routing",
"--inline-style", "-is",
"--inline-template", "-it"
})
local serve_parser = parser({
"--port", "-p",
"--host", "-H",
"--proxy", "-pr", "-pxy",
"--proxy-config", "-pc",
"--insecure-proxy", "--inspr",
"--watcher", "-w",
"--live-reload", "-lr",
"--live-reload-host", "-lrh",
"--live-reload-base-url", "-lrbu",
"--live-reload-port", "-lrp",
"--live-reload-live-css",
"--environment", "-e",
"--environment=development", "-dev",
"--environment=production", "-prod",
"--output-path", "-op", "-out",
"--ssl",
"--ssl-key",
"--ssl-cert",
"--target", "-t",
"--target=development", "-dev",
"--target=production", "-prod",
"--aot",
"--open", "-o"
})
local get_parser = parser({
"--global"
})
local set_parser = parser({
"--global", "-g"
})
local github_pages_parser = parser({
"--message",
"--environment",
"--branch",
"--skip-build",
"--gh-token",
"--gh-username",
"--user-page"
})
local test_parser = parser({
"--environment", "-e",
"--config-file", "-c", "-cf",
"--server", "-s",
"--host", "-H",
"--test-port", "-tp",
"--filter", "-f",
"--module", "-m",
"--watch", "--watcher", "-w",
"--launch",
"--reporter", "-r",
"--silent",
"--test-page",
"--page",
"--query",
"--code-coverage", "-cc",
"--lint", "-l",
"--browsers",
"--colors",
"--log-levevl",
"--port",
"--reporters",
"--build"
})
local version_parser = parser({
"--verbose"
})
local ng_parser = parser({
"addon"..addon_parser,
"asset-sizes"..asset_sizes_parser,
"build"..build_parser, "b"..build_parser,
"destroy"..destroy_parser, "d"..destroy_parser,
"generate"..generate_parser, "g"..generate_parser,
"help"..help_parser, "h"..help_parser, "--help"..help_parser, "-h"..help_parser,
"init"..init_parser,
"install", "i",
"new"..new_parser,
"serve"..serve_parser, "server"..serve_parser, "s"..serve_parser,
"test"..test_parser, "t"..test_parser,
"e2e",
"lint",
"version"..version_parser, "v"..version_parser, "--version"..version_parser, "-v"..version_parser,
"completion",
"doc",
"make-this-awesome",
"set"..set_parser,
"get"..get_parser,
"github-pages:deploy"..github_pages_parser
})
clink.arg.register_parser("ng", ng_parser)

View File

@@ -0,0 +1,118 @@
local w = require('tables').wrap
local path = require('path')
local packages = function (token)
return w(clink.find_dirs(clink.get_env('chocolateyinstall')..'/lib/*'))
:filter(function(dir)
return path.is_real_dir(dir) and clink.is_match(token, dir)
end)
:map(function (dir)
local package_name = dir:match("^(%w%.*)%.")
return package_name or dir
end)
end
local parser = clink.arg.new_parser
local clist_parser = parser(
"-a", "--all", "--allversions", "--all-versions",
"-i", "--includeprograms", "--include-programs",
"-l", "--lo", "--localonly", "--local-only",
"-s", "--source".. parser({"windowsfeatures", "webpi"}),
"-u", "--user",
"-p", "--password")
local cinst_parser = parser(
-- TODO: Path to packages config.
-- See https://github.com/chocolatey/choco/wiki/CommandsInstall
{"all", "packages.config"},
"--ia", "--installargs", "--installarguments", "--install-arguments",
"-i", "--ignoredependencies", "--ignore-dependencies",
"-x", "--forcedependencies", "--force-dependencies",
"-m", "--sxs", "--sidebyside", "--side-by-side",
"--allowmultiple", "--allow-multiple", "--allowmultipleversions", "--allow-multiple-versions",
"-n", "--skippowershell", "--skip-powershell",
"--notsilent", "--not-silent",
"-o", "--override", "--overrideargs", "--overridearguments", "--override-arguments",
"--params", "--parameters", "--pkgparameters", "--packageparameters", "--package-parameters",
"--pre", "--prerelease",
"-s" .. parser({"ruby", "webpi", "cygwin", "windowsfeatures", "python"}),
"--source" .. parser({"ruby", "webpi", "cygwin", "windowsfeatures", "python"}),
"--version",
"--x86", "--forcex86",
"-u", "--user",
"-p", "--password")
local cuninst_parser = parser({packages},
"-a", "--all", "--allversions", "--all-versions",
"-x", "--forcedependencies", "--force-dependencies",
"--ia", "--installargs", "--installarguments", "--install-arguments",
"-n", "--skippowershell", "--skip-powershell",
"--notsilent", "--not-silent",
"-o", "--override", "--overrideargs", "--overridearguments", "--override-arguments",
"--params", "--parameters", "--pkgparameters", "--packageparameters", "--package-parameters",
"--version")
local cup_parser = parser(
--TODO: complete locally installed packages
{packages, "all"},
"--ia", "--installargs", "--installarguments", "--install-arguments",
"-i", "--ignoredependencies", "--ignore-dependencies",
"-m", "--sxs", "--sidebyside", "--side-by-side",
"--allowmultiple", "--allow-multiple", "--allowmultipleversions", "--allow-multiple-versions",
"-n", "--skippowershell", "--skip-powershell",
"--notsilent", "--not-silent",
"-o", "--override", "--overrideargs", "--overridearguments", "--override-arguments",
"--params", "--parameters", "--pkgparameters", "--packageparameters", "--package-parameters",
"--pre", "--prerelease",
"-s" .. parser({"ruby", "webpi", "cygwin", "windowsfeatures", "python"}),
"--source" .. parser({"ruby", "webpi", "cygwin", "windowsfeatures", "python"}),
"--version",
"--x86", "--forcex86",
"-u", "--user",
"-p", "--password"):loop(1)
local sources_parser = parser({
"add"..parser(
"-n", "--name",
"-u", "--user",
"-p", "--password",
"-s", "-source"),
"disable"..parser("-n", "--name"),
"enable"..parser("-n", "--name"),
"list",
"remove"..parser("-n", "--name")})
local chocolatey_parser = parser({
--TODO: https://github.com/chocolatey/choco/wiki/CommandsReference
-- Default Options and Switches
-- new - generates files necessary for a Chocolatey package
-- pack - packages up a nuspec to a compiled nupkg
-- push - pushes a compiled nupkg
"apikey"..parser("-s", "--source", "-k", "--key", "--apikey", "--api-key"),
"setapikey"..parser("-s", "--source", "-k", "--key", "--apikey", "--api-key"),
"feature"..parser({
"list",
"disable"..parser("-n", "--name"),
"enable"..parser("-n", "--name")
}),
"install"..cinst_parser,
"list"..clist_parser,
"outdated"..parser(
"-s", "--source",
"-u", "--user",
"-p", "--password"),
"pin"..parser({"add", "remove", "list"}, "-n", "--name", "--version"),
"source"..sources_parser,
"sources"..sources_parser,
"search"..clist_parser,
"upgrade"..cup_parser,
"uninstall"..cuninst_parser
}, "/?")
clink.arg.register_parser("choco", chocolatey_parser)
clink.arg.register_parser("chocolatey", chocolatey_parser)
clink.arg.register_parser("cinst", cinst_parser)
clink.arg.register_parser("clist", clist_parser)
clink.arg.register_parser("cuninst", cuninst_parser)
clink.arg.register_parser("cup", cup_parser)

View File

@@ -0,0 +1,95 @@
local parser = clink.arg.new_parser
local repos = {
-- repos names
-- platforms
"android", "ios", "blackberry", "windows", "wp8", "firefoxos", "osx","ubuntu",
"amazon-fireos", "bada", "bada-wac", "webos", "qt", "tizen",
-- plugins
"plugin-battery-status", "plugin-camera", "plugin-console", "plugin-contacts",
"plugin-device-motion", "plugin-device-orientation", "plugin-device",
"plugin-dialogs", "plugin-file-transfer", "plugin-file", "plugin-geolocation",
"plugin-globalization", "plugin-inappbrowser", "plugin-media",
"plugin-media-capture", "plugin-network-information", "plugin-splashscreen",
"plugin-vibration", "plugin-statusbar", "cordova-plugins",
--tools
"docs", "mobile-spec", "js","app-hello-world", "cli", "plugman", "lib", "common",
"coho", "medic", "app-harness", "labs", "registry-web", "registry",
"dist", "dist/dev", "private-pmc", "website",
--repos groups
"active-platform", "all", "auto", "cadence", "platform", "plugins",
"release-repos", "tools"
}
local coho_parser = parser(
{
"repo-clone" .. parser(
"-r" .. parser(repos),
"--repo" .. parser(repos),
"--chdir", "--no-chdir",
"--depth"
),
"repo-update" .. parser(
"--chdir", "--no-chdir",
"-b", "--branch",
"-r" .. parser(repos),
"--repo" .. parser(repos),
"--fetch",
"--depth",
"-h", "--help"
),
"repo-reset" .. parser(
"--chdir",
"-b", "--branch",
"-r" .. parser(repos),
"--repo" .. parser(repos),
"-h", "--help"
),
"repo-status" .. parser(
"--chdir",
"-b", "--branch",
"-r" .. parser(repos),
"--repo" .. parser(repos),
"--branch2",
"--diff",
"-h", "--help"
),
"repo-push",
"list-repos",
-- release management
"prepare-release-branch",
"tag-release",
"audit-license-headers",
"check-license",
"create-archive"..parser(
'-r'..parser(repos),
'--repo'..parser(repos),
'--dest'
),
"verify-archive",
"print-tags"..parser(
'-r'..parser(repos),
'--repo'..parser(repos),
'--tag' -- TODO: get tags based on dir and functionality from git.lua
),
"verify-tags",
"list-release-urls",
"nightly",
"npm-publish-tag",
"update-release-notes",
"npm-unpublish-nightly",
-- other commands
"list-pulls",
"last-week",
"shortlog",
"for-each",
"npm-link",
"create-pr",
"merge-pr"..parser("--pr")
},
"--chdir",
"--no-chdir",
"-h"
)
clink.arg.register_parser("coho", coho_parser)

View File

@@ -0,0 +1,99 @@
--preamble: common routines
local matchers = require('matchers')
local platforms = matchers.create_dirs_matcher('platforms/*')
local plugins = matchers.create_dirs_matcher('plugins/*')
-- end preamble
local parser = clink.arg.new_parser
local platform_add_parser = parser({
"wp8",
"windows",
"android",
"blackberry10",
"firefoxos",
matchers.dirs
}, "--usegit", "--save", "--link"):loop(1)
local plugin_add_parser = parser({matchers.dirs,
"cordova-plugin-battery-status",
"cordova-plugin-camera",
"cordova-plugin-contacts",
"cordova-plugin-device",
"cordova-plugin-device-motion",
"cordova-plugin-device-orientation",
"cordova-plugin-dialogs",
"cordova-plugin-file",
"cordova-plugin-file-transfer",
"cordova-plugin-geolocation",
"cordova-plugin-globalization",
"cordova-plugin-inappbrowser",
"cordova-plugin-media",
"cordova-plugin-media-capture",
"cordova-plugin-network-information",
"cordova-plugin-splashscreen",
"cordova-plugin-statusbar",
"cordova-plugin-test-framework",
"cordova-plugin-vibration"
},
"--searchpath" ..parser({matchers.dirs}),
"--noregistry",
"--link",
"--save",
"--shrinkwrap"
):loop(1)
local platform_rm_parser = parser({platforms}, "--save"):loop(1)
local plugin_rm_parser = parser({plugins}, "-f", "--force", "--save"):loop(1)
local cordova_parser = parser(
{
-- common commands
"create" .. parser(
"--copy-from", "--src",
"--link-to"
),
"help",
-- project-level commands
"info",
"platform" .. parser({
"add" .. platform_add_parser,
"remove" .. platform_rm_parser,
"rm" .. platform_rm_parser,
"list", "ls",
"up" .. parser({platforms}):loop(1),
"update" .. parser({platforms}, "--usegit", "--save"):loop(1),
"check"
}),
"plugin" .. parser({
"add" .. plugin_add_parser,
"remove" .. plugin_rm_parser,
"rm" .. plugin_rm_parser,
"list", "ls",
"search"
}, "--browserify"),
"prepare" .. parser({platforms}, "--browserify"):loop(1),
"compile" .. parser({platforms},
"--browserify",
"--debug", "--release",
"--device", "--emulator", "--target="):loop(1),
"build" .. parser({platforms},
"--browserify",
"--debug", "--release",
"--device", "--emulator", "--target="):loop(1),
"run" .. parser({platforms},
"--browserify",
"--nobuild",
"--debug", "--release",
"--device", "--emulator", "--target="),
"emulate" .. parser({platforms}),
"serve",
}, "-h",
"-v", "--version",
"-d", "--verbose")
clink.arg.register_parser("cordova", cordova_parser)
clink.arg.register_parser("cordova-dev", cordova_parser)

View File

@@ -0,0 +1,218 @@
local matchers = require('matchers')
local parser = clink.arg.new_parser
local runtime_parser = parser({
-- Windows
"win-x64", "win-x86", "win-arm", "win-arm64", "win7-x64", "win7-x86",
"win81-x64", "win81-x86", "win81-arm", "win10-x64", "win10-x86", "win10-arm",
"win10-arm64",
-- Linux
"linux-x64", "linux-musl-x64", "linux-arm", "rhel-x64", "rhel.6-x64", "tizen",
"tizen.4.0.0", "tizen.5.0.0",
-- macOS
"osx-x64", "osx.10.10-x64", "osx.10.11-x64", "osx.10.12-x64", "osx.10.13-x64",
"osx.10.14-x64"
})
local framework_parser = parser({
"netstandard1.0", "netstandard1.1", "netstandard1.2", "netstandard1.3",
"netstandard1.4", "netstandard1.5", "netstandard1.6", "netstandard2.0",
"netstandard2.1",
"netcoreapp1.0", "netcoreapp1.1", "netcoreapp2.0", "netcoreapp2.1",
"netcoreapp2.2", "netcoreapp3.0", "netcoreapp3.1",
"net11", "net20", "net35", "net40", "net403", "net45", "net451", "net452",
"net46", "net461", "net462", "net47", "net471", "net472", "net48"
})
local verbosity_parser = parser({"quiet", "minimal", "normal", "detailed", "diagnostic"})
local configuration_parser = parser({"Debug", "Release"})
local build_parser = parser({matchers.files})
build_parser:add_flags(
"--configuration"..configuration_parser,
"--force",
"--framework"..framework_parser,
"--help",
"--interactive",
"--nologo",
"--no-dependencies",
"--no-incremental",
"--no-restore",
"--output",
"--runtime"..runtime_parser,
"--verbosity"..verbosity_parser,
"--version-suffix"
)
local publish_parser = parser({matchers.files})
publish_parser:add_flags({
"--configuration"..configuration_parser,
"--force",
"--framework"..framework_parser,
"--help",
"--manifest",
"--no-build",
"--no-dependencies",
"--no-restore",
"--output",
"--runtime"..runtime_parser,
"--self-contained",
"--verbosity"..verbosity_parser,
"--version-suffix",
}):loop(1)
local clean_parser = parser({matchers.files})
clean_parser:add_flags(
"--configuration"..configuration_parser,
"--framework"..framework_parser,
"--help",
"--interactive",
"--nologo",
"--output",
"--runtime",
"--verbosity"..verbosity_parser
)
local mvc_webapp_parser = parser({
"--auth"..parser({"None", "Individual", "IndividualB2C", "SingleOrg", "MultiOrg", "Windows"}),
"--aad-b2c-instance",
"--susi-policy-id",
"--reset-password-policy-id",
"--edit-profile-policy-id",
"--aad-instance",
"--client-id",
"--domain",
"--tenant-id",
"--callback-path",
"--org-read-access",
"--exclude-launch-settings",
"--no-https",
"--use-local-db",
"--no-restore"
}):loop(1)
local new_parser = parser({
"angular", "react", "reactredux",
"blazorserver",
"classlib"..parser({"--framework"..framework_parser, "--langVersion", "--no-restore"}),
"console"..parser({"--langVersion", "--no-restore"}),
"gitignore",
"globaljson"..parser({"--sdk-version"}),
"grpc",
"mstest",
"mvc"..mvc_webapp_parser,
"nugetconfig",
"nunit-test",
"nunit",
"page"..parser({"--namespace", "--no-pagemodel"}),
"razorclasslib",
"razorcomponent",
"sln",
"tool-manifest",
"viewimports"..parser({"--namespace"}),
"viewstart",
"web"..parser({"--exclude-launch-settings", "--no-restore", "--no-https"}),
"webapi",
"webapp"..mvc_webapp_parser,
"webconfig",
"wpf", "wpflib", "wpfcustomcontrollib", "wpfusercontrollib", "winforms", "winformslib",
"worker",
"xunit"
})
new_parser:add_flags(
"--dry-run", "--force", "--help", "--install", "--list", "--language", "--name",
"--nuget-source", "--output", "--type", "--update-check", "--update-apply"
)
local run_parser = parser({matchers.files})
run_parser:add_flags(
"--configuration"..configuration_parser,
"--force",
"--framework"..framework_parser,
"--help",
"--launch-profile",
"--no-restore",
"--project",
"--runtime"..runtime_parser,
"--verbosity"..verbosity_parser
)
local ef_parser = parser({
"database"..parser({
"drop"..parser("--force", "--dry-run"),
"update"
}),
"dbcontext"..parser({
"info",
"list",
"scaffold"..parser(
"--data-annotations",
"--context",
"--context-dir",
"--force",
"--output-dir",
"--schema",
"--table",
"--use-database-names"
),
}),
"migrations"..parser({
"add"..parser("--output-dir"),
"list",
"remove"..parser("--force"),
"script"..parser("--output-dir", "--idempotent")
})
})
ef_parser:add_flags(
"--context", -- <DbContext>
"--project", -- <Project>
"--startup-project", -- <Project>
"--framework"..framework_parser,
"--configuration"..configuration_parser,
"--runtime"..runtime_parser,
"--json", "--help", "--verbose", "--no-color", "--prefix-output"
)
local dotnet_parser = parser({
"add"..parser({"reference", "package"}),
"build"..build_parser,
"build-server",
"clean"..clean_parser,
"help",
"list"..parser({"reference", "package"}),
"msbuild",
"new"..new_parser,
"nuget",
"pack",
"publish"..publish_parser,
"remove"..parser({"reference", "package"}),
"restore",
"run"..run_parser,
"sln"..parser({"add", "remove", "list"}),
"store",
"test",
"tool",
"vstest",
-- Tools:
"ef"..ef_parser
})
dotnet_parser:add_flags(
"--help", "--info", "--list-sdks", "--list-runtimes"
)
clink.arg.register_parser("dotnet", dotnet_parser)

View File

@@ -0,0 +1,966 @@
-- preamble: common routines
local path = require('path')
local git = require('gitutil')
local matchers = require('matchers')
local w = require('tables').wrap
local clink_version = require('clink_version')
local color = require('color')
local parser = clink.arg.new_parser
if clink_version.supports_color_settings then
settings.add('color.git.star', 'bright green', 'Color for preferred branch completions')
end
---
-- Lists remote branches based on packed-refs file from git directory
-- @param string [dir] Directory where to search file for
-- @return table List of remote branches
local function list_packed_refs(dir)
local result = w()
local git_dir = dir or git.get_git_common_dir()
if not git_dir then return result end
local packed_refs_file = io.open(git_dir..'/packed-refs')
if packed_refs_file == nil then return {} end
for line in packed_refs_file:lines() do
-- SHA is 40 char length + 1 char for space
if #line > 41 then
local match = line:sub(41):match('refs/remotes/(.*)')
if match then table.insert(result, match) end
end
end
packed_refs_file:close()
return result
end
local function list_remote_branches(dir)
local git_dir = dir or git.get_git_common_dir()
if not git_dir then return w() end
return w(path.list_files(git_dir..'/refs/remotes', '/*',
--[[recursive=]]true, --[[reverse_separator=]]true))
:concat(list_packed_refs(git_dir))
:sort():dedupe()
end
---
-- Lists local branches for git repo in git_dir directory.
--
-- @param string [dir] Git directory, where to search for remote branches
-- @return table List of branches.
local function list_local_branches(dir)
local git_dir = dir or git.get_git_common_dir()
if not git_dir then return w() end
local result = w(path.list_files(git_dir..'/refs/heads', '/*',
--[[recursive=]]true, --[[reverse_separator=]]true))
return result
end
local branches = function (token)
local git_dir = git.get_git_common_dir()
if not git_dir then return w() end
return list_local_branches(git_dir)
:filter(function(branch)
return clink.is_match(token, branch)
end)
end
local function alias(token)
local res = w()
-- Try to resolve .git directory location
local git_dir = git.get_git_dir()
if git_dir == nil then return res end
local f = io.popen("git config --get-regexp alias 2>nul")
if f == nil then return {} end
for line in f:lines() do
local s = line:find(" ", 1, true)
local alias_name = line:sub(7, s - 1)
local start = alias_name:find(token, 1, true)
if start and start == 1 then
table.insert(res, alias_name)
end
end
f:close()
return res
end
local function remotes(token) -- luacheck: no unused args
local result = w()
local git_dir = git.get_git_common_dir()
if not git_dir then return result end
local git_config = io.open(git_dir..'/config')
-- if there is no gitconfig file (WAT?!), return empty list
if git_config == nil then return result end
for line in git_config:lines() do
local remote = line:match('%[remote "(.*)"%]')
if (remote) then
table.insert(result, remote)
end
end
git_config:close()
return result
end
local function local_or_remote_branches(token)
-- Try to resolve .git directory location
local git_dir = git.get_git_common_dir()
if not git_dir then return w() end
return list_local_branches(git_dir)
:concat(list_remote_branches(git_dir))
:filter(function(branch)
return clink.is_match(token, branch)
end)
end
local function checkout_spec_generator(token)
local files = matchers.files(token)
:filter(function(file)
return path.is_real_dir(file)
end)
local git_dir = git.get_git_common_dir()
local local_branches = branches(token)
local remote_branches = list_remote_branches(git_dir)
:filter(function(branch)
return clink.is_match(token, branch)
end)
local predicted_branches = list_remote_branches(git_dir)
:map(function (remote_branch)
return remote_branch:match('.-/(.+)')
end)
:filter(function(branch)
return branch
and clink.is_match(token, branch)
-- Filter out those predictions which are already exists as local branches
and not local_branches:contains(branch)
end)
if (#local_branches + #remote_branches + #predicted_branches) == 0 then return files end
-- if there is any refspec that matches token then:
-- * disable readline's filename completion, otherwise we'll get a list of these specs
-- threaten as list of files (without 'path' part), ie. 'some_branch' instead of 'my_remote/some_branch'
-- * create display filter for completion table to append path separator to each directory entry
-- since it is not added automatically by readline (see previous point)
clink.matches_are_files(0)
clink.match_display_filter = function ()
local star = '*'
if clink_version.supports_query_rl_var and rl.isvariabletrue('colored-stats') then
star = color.get_clink_color('color.git.star')..star..color.get_clink_color('color.filtered')
end
return files:map(function(file)
return clink.is_dir(file) and file..'\\' or file
end)
:concat(local_branches)
:concat(predicted_branches:map(function(branch) return star..branch end))
:concat(remote_branches)
end
return files
:concat(local_branches)
:concat(predicted_branches)
:concat(remote_branches)
end
local function push_branch_spec(token)
local git_dir = git.get_git_common_dir()
if not git_dir then return w() end
local plus_prefix = token:sub(0, 1) == '+'
-- cut out leading '+' symbol as it is a part of branch spec
local branch_spec = plus_prefix and token:sub(2) or token
-- check if there a local/remote branch separator
local s, e = branch_spec:find(':')
-- starting from here we have 2 options:
-- * if there is no branch separator complete word with local branches
if not s then
local b = branches(branch_spec)
-- setup display filter to prevent display '+' symbol in completion list
clink.match_display_filter = function ()
return b
end
return b:map(function(branch)
-- append '+' to results if it was specified
return plus_prefix and '+'..branch or branch
end)
else
-- * if there is ':' separator then we need to complete remote branch
local local_branch_spec = branch_spec:sub(1, s - 1)
local remote_branch_spec = branch_spec:sub(e + 1)
-- TODO: show remote branches only for remote that has been specified as previous argument
local b = w(clink.find_dirs(git_dir..'/refs/remotes/*'))
:filter(function(remote) return path.is_real_dir(remote) end)
:reduce({}, function(result, remote)
return w(path.list_files(git_dir..'/refs/remotes/'..remote, '/*',
--[[recursive=]]true, --[[reverse_separator=]]true))
:filter(function(remote_branch)
return clink.is_match(remote_branch_spec, remote_branch)
end)
:concat(result)
end)
-- setup display filter to prevent display '+' symbol in completion list
clink.match_display_filter = function ()
return b
end
return b:map(function(branch)
return (plus_prefix and '+'..local_branch_spec or local_branch_spec)..':'..branch
end)
end
end
local stashes = function(token) -- luacheck: no unused args
local git_dir = git.get_git_dir()
if not git_dir then return w() end
local stash_file = io.open(git_dir..'/logs/refs/stash')
-- if there is no stash file, return empty list
if stash_file == nil then return w() end
local stashes = {}
-- make a dictionary of stash time and stash comment to
-- be able to sort stashes by date/time created
for stash in stash_file:lines() do
local stash_time, stash_name = stash:match('(%d%d%d%d%d%d%d%d%d%d) [+-]%d%d%d%d%s+(.*)')
if (stash_name and stash_name) then
stashes[stash_time] = stash_name
end
end
stash_file:close()
-- get times for available stashes into separate table and sort it
-- from newest to oldest. This is required because of stash@{0}
-- represents _latest_ stash, not the last one in file
local stash_times = {}
for k in pairs(stashes) do
table.insert(stash_times, k)
end
table.sort(stash_times, function (a, b)
return a > b
end)
-- generate matches and match filter table
local ret = {}
local ret_filter = {}
for i,v in ipairs(stash_times) do
local match = "stash@{"..(i-1).."}"
table.insert(ret, match)
if clink_version.supports_display_filter_description then
-- Clink now has a richer match interface. By returning a table,
-- the script is able to provide the stash name separately from the
-- description. If the script does so, then the popup completion
-- window is able to show the stash name plus a dimmed description,
-- but only insert the stash name.
table.insert(ret_filter, { match=match, type="word", description=stashes[v] })
else
table.insert(ret_filter, match.." "..stashes[v])
end
end
local function filter()
return ret_filter
end
if clink_version.supports_display_filter_description then
clink.ondisplaymatches(filter)
else
clink.match_display_filter = filter
end
return ret
end
local color_opts = parser({"true", "false", "always"})
local git_options = {
"core.editor",
"core.pager",
"core.excludesfile",
"core.autocrlf"..parser({"true", "false", "input"}),
"core.trustctime"..parser({"true", "false"}),
"core.whitespace"..parser({
"cr-at-eol",
"-cr-at-eol",
"indent-with-non-tab",
"-indent-with-non-tab",
"space-before-tab",
"-space-before-tab",
"trailing-space",
"-trailing-space"
}),
"commit.template",
"color.ui"..color_opts, "color.*"..color_opts, "color.branch"..color_opts,
"color.diff"..color_opts, "color.interactive"..color_opts, "color.status"..color_opts,
"help.autocorrect",
"merge.tool", "mergetool.*.cmd", "mergetool.trustExitCode"..parser({"true", "false"}), "diff.external",
"user.name", "user.email", "user.signingkey",
}
local config_parser = parser(
"--system", "--global", "--local", "--file"..parser({matchers.files}),
"--int", "--bool", "--path",
"-z", "--null",
"--add",
"--replace-all",
"--get", "--get-all", "--get-regexp", "--get-urlmatch",
"--unset", "--unset-all",
"--rename-section", "--remove-section",
"-l", "--list",
"--get-color", "--get-colorbool",
"-e", "--edit",
{git_options}
)
local merge_recursive_options = parser({
"ours",
"theirs",
"renormalize",
"no-renormalize",
"diff-algorithm="..parser({
"patience",
"minimal",
"histogram",
"myers"
}),
"patience",
"ignore-space-change",
"ignore-all-space",
"ignore-space-at-eol",
"rename-threshold=",
-- "subtree="..parser(),
"subtree"
})
local merge_strategies = parser({
"resolve",
"recursive",
"ours",
"octopus",
"subtree"
})
local git_parser = parser(
{
{alias},
"add" .. parser({matchers.files},
"-n", "--dry-run",
"-v", "--verbose",
"-f", "--force",
"-i", "--interactive",
"-p", "--patch",
"-e", "--edit",
"-u", "--update",
"-A", "--all",
"--no-all",
"--ignore-removal",
"--no-ignore-removal",
"-N", "--intent-to-add",
"--refresh",
"--ignore-errors",
"--ignore-missing"
),
"add--interactive",
"am",
"annotate" .. parser({matchers.files},
"-b",
"--root",
"--show-stats",
"-L",
"-l",
"-t",
"-S",
"--reverse",
"-p",
"--porcelain",
"--line-porcelain",
"--incremental",
"--encoding=",
"--contents",
"--date",
"-M",
"-C",
"-h"
),
"apply" .. parser(
"--stat",
"--numstat",
"--summary",
"--check",
"--index",
"--cached",
"-3", "--3way",
"--build-fake-ancestor=",
"-R", "--reverse",
"--reject",
"-z",
"-p",
"-C",
"--unidiff-zero",
"--apply",
"--no-add",
"--allow-binary-replacement", "--binary",
"--exclude=",
"--include=",
"--ignore-space-change", "--ignore-whitespace",
"--whitespace=",
"--inaccurate-eof",
"-v", "--verbose",
"--recount",
"--directory="
),
"archive",
"bisect",
"bisect--helper",
"blame",
"branch" .. parser(
"-v", "--verbose",
"-q", "--quiet",
"-t", "--track",
"--set-upstream",
"-u", "--set-upstream-to",
"--unset-upstream",
"--color",
"-r", "--remotes",
"--contains" ,
"--abbrev",
"-a", "--all",
"-d" .. parser({branches}):loop(1),
"--delete" .. parser({branches}):loop(1),
"-D" .. parser({branches}):loop(1),
"-m", "--move",
"-M",
"--list",
"-l", "--create-reflog",
"--edit-description",
"-f", "--force",
"--no-merged",
"--merged",
"--column"
),
"bundle",
"cat-file",
"check-attr",
"check-ignore",
"check-mailmap",
"check-ref-format",
"checkout" .. parser({checkout_spec_generator},
"-q", "--quiet",
"-b",
"-B",
"-l",
"--detach",
"-t", "--track",
"--orphan",
"-2", "--ours",
"-3", "--theirs",
"-f", "--force",
"-m", "--merge",
"--overwrite-ignore",
"--conflict",
"-p", "--patch",
"--ignore-skip-worktree-bits"
),
"checkout-index",
"cherry",
"cherry-pick"..parser(
"-e", "--edit",
"-m", "--mainline ",
"-n", "--no-commit",
"-r",
"-x",
"--ff",
"-s", "-S", "--gpg-sign",
"--allow-empty",
"--allow-empty-message",
"--keep-redundant-commits",
"--strategy"..parser({merge_strategies}),
"-X"..parser({merge_recursive_options}),
"--strategy-option"..parser({merge_recursive_options}),
"--continue",
"--quit",
"--abort"
),
"citool",
"clean",
"clone" .. parser(
"--template",
"-l", "--local",
"-s", "--shared",
"--no-hardlinks",
"-q", "--quiet",
"-n", "--no-checkout",
"--bare",
"--mirror",
"-o", "--origin",
"-b", "--branch",
"-u", "--upload-pack",
"--reference",
"--dissociate",
"--separate-git-dir",
"--depth",
"--single-branch", "--no-single-branch",
"--no-tags",
"--recurse-submodules", "--shallow-submodules", "--no-shallow-submodules",
"--jobs"
),
"column",
"commit" .. parser(
"-a", "--all",
"-p", "--patch",
"-C", "--reuse-message=",
"-c", "--reedit-message=",
"--fixup=",
"--squash=",
"--reset-author",
"--short",
"--branch",
"--porcelain",
"--long",
"-z",
"--null",
"-F", "--file=",
"--author=",
"--date=",
"-m", "--message=",
"-t", "--template=",
"-s", "--signoff",
"-n", "--no-verify",
"--allow-empty",
"--allow-empty-message",
"--cleanup", -- .. parser({"strip", "whitespace", "verbatim", "default"}),
"-e", "--edit",
"--no-edit",
"--amend",
"--no-post-rewrite",
"-i", "--include",
"-o", "--only",
"-u", "--untracked-files", "--untracked-files=", -- .. parser({"no", "normal", "all"}),
"-v", "--verbose",
"-q", "--quiet",
"--dry-run",
"--status",
"--no-status",
"-S", "--gpg-sign", "--gpg-sign=",
"--"
),
"commit-tree",
"config"..config_parser,
"count-objects",
"credential",
"credential-store",
"credential-wincred",
"daemon",
"describe",
"diff" .. parser({local_or_remote_branches, matchers.files}),
"diff-files",
"diff-index",
"diff-tree",
"difftool"..parser(
"-d", "--dir-diff",
"-y", "--no-prompt", "--prompt",
"-t", "--tool=" -- TODO: complete tool (take from config)
),
"difftool--helper",
"fast-export",
"fast-import",
"fetch" .. parser({remotes},
"--all",
"--prune",
"--tags"
),
"fetch-pack",
"filter-branch",
"fmt-merge-msg",
"for-each-ref",
"format-patch",
"fsck",
"fsck-objects",
"gc",
"get-tar-commit-id",
"grep",
"gui",
"gui--askpass",
"gui--askyesno",
"gui.tcl",
"hash-object",
"help",
"http-backend",
"http-fetch",
"http-push",
"imap-send",
"index-pack",
"init",
"init-db",
"log",
"lost-found",
"ls-files",
"ls-remote",
"ls-tree",
"mailinfo",
"mailsplit",
"merge" .. parser({branches},
"--commit", "--no-commit",
"--edit", "-e", "--no-edit",
"--ff", "--no-ff", "--ff-only",
"--log", "--no-log",
"--stat", "-n", "--no-stat",
"--squash", "--no-squash",
"-s" .. merge_strategies,
"--strategy" .. merge_strategies,
"-X" .. merge_recursive_options,
"--strategy-option" .. merge_recursive_options,
"--verify-signatures", "--no-verify-signatures",
"-q", "--quiet", "-v", "--verbose",
"--progress", "--no-progress",
"-S", "--gpg-sign",
"-m",
"--rerere-autoupdate", "--no-rerere-autoupdate",
"--abort"
),
"merge-base",
"merge-file",
"merge-index",
"merge-octopus",
"merge-one-file",
"merge-ours",
"merge-recursive",
"merge-resolve",
"merge-subtree",
"merge-tree",
"mergetool",
"mergetool--lib",
"mktag",
"mktree",
"mv",
"name-rev",
"notes",
"p4",
"pack-objects",
"pack-redundant",
"pack-refs",
"parse-remote",
"patch-id",
"peek-remote",
"prune",
"prune-packed",
"pull" .. parser(
{remotes}, {branches},
"-q", "--quiet",
"-v", "--verbose",
"--recurse-submodules", --[no-]recurse-submodules[=yes|on-demand|no]
"--no-recurse-submodules",
"--commit", "--no-commit",
"-e", "--edit", "--no-edit",
"--ff", "--no-ff", "--ff-only",
"--log", "--no-log",
"--stat", "-n", "--no-stat",
"--squash", "--no-squash",
"-s"..merge_strategies,
"--strategy"..merge_strategies,
"-X"..merge_recursive_options,
"--strategy-option"..merge_recursive_options,
"--verify-signatures", "--no-verify-signatures",
"--summary", "--no-summary",
"-r", "--rebase", "--no-rebase",
"--all",
"-a", "--append",
"--depth", "--unshallow", "--update-shallow",
"-f", "--force",
"-k", "--keep",
"--no-tags",
"-u", "--update-head-ok",
"--upload-pack",
"--progress"
),
"push" .. parser(
{remotes},
{push_branch_spec},
"-v", "--verbose",
"-q", "--quiet",
"--repo",
"--all",
"--mirror",
"--delete",
"--tags",
"-n", "--dry-run",
"--porcelain",
"-f", "--force",
"--force-with-lease",
"--recurse-submodules",
"--thin",
"--receive-pack",
"--exec",
"-u", "--set-upstream",
"--progress",
"--prune",
"--no-verify",
"--follow-tags"
),
"quiltimport",
"read-tree",
"rebase" .. parser({local_or_remote_branches}, {branches},
"-i", "--interactive",
"--onto" .. parser({branches}),
"--continue",
"--abort",
"--keep-empty",
"--skip",
"--edit-todo",
"-m", "--merge",
"-s" .. merge_strategies,
"--strategy"..merge_strategies,
"-X" .. merge_recursive_options,
"--strategy-option"..merge_recursive_options,
"-S", "--gpg-sign",
"-q", "--quiet",
"-v", "--verbose",
"--stat", "-n", "--no-stat",
"--no-verify", "--verify",
"-C",
"-f", "--force-rebase",
"--fork-point", "--no-fork-point",
"--ignore-whitespace", "--whitespace",
"--committer-date-is-author-date", "--ignore-date",
"-i", "--interactive",
"-p", "--preserve-merges",
"-x", "--exec",
"--root",
"--autosquash", "--no-autosquash",
"--autostash", "--no-autostash",
"--no-ff"
),
"receive-pack",
"reflog",
"remote"..parser({
"add" ..parser(
"-t"..parser({branches}),
"-m",
"-f",
"--mirror",
"--tags", "--no-tags"
),
"rename"..parser({remotes}),
"remove"..parser({remotes}),
"rm"..parser({remotes}),
"set-head"..parser({remotes}, {branches},
"-a", "--auto",
"-d", "--delete"
),
"set-branches"..parser("--add", {remotes}, {branches}),
"set-url"..parser(
"--add"..parser("--push", {remotes}),
"--delete"..parser("--push", {remotes})
),
"get-url"..parser({remotes}, "--push", "--all"),
"show"..parser("-n", {remotes}),
"prune"..parser("-n", "--dry-run", {remotes}),
"update"..parser({remotes}, "-p", "--prune")
}, "-v", "--verbose"),
"remote-ext",
"remote-fd",
"remote-ftp",
"remote-ftps",
"remote-hg",
"remote-http",
"remote-https",
"remote-testsvn",
"repack",
"replace",
"repo-config",
"request-pull",
"rerere",
-- TODO: Add commit completions
"reset"..parser({local_or_remote_branches},
"-q",
"-p", "--patch",
"--soft", "--mixed", "--hard",
"--merge", "--keep"
),
"restore"..parser({matchers.files},
"-s", "--source",
"-p", "--patch",
"-W", "--worktree",
"-S", "--staged",
"-q", "--quiet",
"--progress", "--no-progress",
"--ours", "--theirs",
"-m", "--merge",
"--conflict",
"--ignore-unmerged",
"--ignore-skip-worktree-bits",
"--overlay", "--no-overlay"
),
"rev-list",
"rev-parse",
"revert",
"rm",
"send-email",
"send-pack",
"sh-i18n",
"sh-i18n--envsubst",
"sh-setup",
"shortlog",
"show",
"show-branch",
"show-index",
"show-ref",
"stage",
"stash"..parser({
"list", -- TODO: The command takes options applicable to the git log
-- command to control what is shown and how it's done
"show"..parser({stashes}),
"drop"..parser({stashes}, "-q", "--quiet"),
"pop"..parser({stashes}, "--index", "-q", "--quiet"),
"apply"..parser({stashes}, "--index", "-q", "--quiet"),
"branch"..parser({branches}, {stashes}),
"save"..parser(
"-p", "--patch",
"-k", "--no-keep-index", "--keep-index",
"-q", "--quiet",
"-u", "--include-untracked",
"-a", "--all"
),
"clear"
}),
"status",
"stripspace",
"submodule"..parser({
"add",
"init",
"deinit",
"foreach",
"status"..parser("--cached", "--recursive"),
"summary",
"sync",
"update"
}, '--quiet'),
"subtree",
"switch"..parser({local_or_remote_branches},
"-c", "-C", "--create",
"--force-create",
"-d", "--detach",
"--guess", "--no-guess",
"-f", "--force", "--discard-changes",
"-m", "--merge",
"--conflict",
"-q", "--quiet",
"--progress", "--no-progress",
"-t", "--track",
"--no-track",
"--orphan",
"--ignore-other-worktrees",
"--recurse-submodules", "--no-recurse-submodules"
),
"svn"..parser({
"init"..parser("-T", "--trunk", "-t", "--tags", "-b", "--branches", "-s", "--stdlayout",
"--no-metadata", "--use-svm-props", "--use-svnsync-props", "--rewrite-root",
"--rewrite-uuid", "--username", "--prefix"..parser({"origin"}), "--ignore-paths",
"--include-paths", "--no-minimize-url"),
"fetch"..parser({remotes}, "--localtime", "--parent", "--ignore-paths", "--include-paths",
"--log-window-size"),
"clone"..parser("-T", "--trunk", "-t", "--tags", "-b", "--branches", "-s", "--stdlayout",
"--no-metadata", "--use-svm-props", "--use-svnsync-props", "--rewrite-root",
"--rewrite-uuid", "--username", "--prefix"..parser({"origin"}), "--ignore-paths",
"--include-paths", "--no-minimize-url", "--preserve-empty-dirs",
"--placeholder-filename"),
"rebase"..parser({local_or_remote_branches}, {branches}),
"dcommit"..parser("--no-rebase", "--commit-url", "--mergeinfo", "--interactive"),
"branch"..parser("-m","--message","-t", "--tags", "-d", "--destination",
"--username", "--commit-url", "--parents"),
"log"..parser("-r", "--revision", "-v", "--verbose", "--limit",
"--incremental", "--show-commit", "--oneline"),
"find-rev"..parser("--before", "--after"),
"reset"..parser("-r", "--revision", "-p", "--parent"),
"tag",
"blame",
"set-tree",
"create-ignore",
"show-ignore",
"mkdirs",
"commit-diff",
"info",
"proplist",
"propget",
"show-externals",
"gc"
}),
"symbolic-ref",
"tag",
"tar-tree",
"unpack-file",
"unpack-objects",
"update-index",
"update-ref",
"update-server-info",
"upload-archive",
"upload-pack",
"var",
"verify-pack",
"verify-tag",
"web--browse",
"whatchanged",
"worktree"..parser({
"add"..parser(
{matchers.dirs},
{branches},
"-f", "--force",
"--detach",
"--checkout",
"--lock",
"-b"..parser({branches})
),
"list"..parser("--porcelain"),
"lock"..parser("--reason"),
"move",
"prune"..parser(
"-n", "--dry-run",
"-v", "--verbose",
"--expire"
),
"remove"..parser("-f"),
"unlock"
}),
"write-tree",
},
"--version",
"--help",
"-c",
"--exec-path",
"--html-path",
"--man-path",
"--info-path",
"-p", "--paginate", "--no-pager",
"--no-replace-objects",
"--bare",
"--git-dir=",
"--work-tree=",
"--namespace="
)
clink.arg.register_parser("git", git_parser)

View File

@@ -0,0 +1,93 @@
local gitutil = require('gitutil')
-- TODO: cache config based on some modification indicator (system mtime, hash)
-- this code is stolen from https://github.com/Dynodzzo/Lua_INI_Parser/blob/master/LIP.lua
-- Resolve licensing issues before exposing
local function load_ini(fileName)
assert(type(fileName) == 'string', 'Parameter "fileName" must be a string.')
local file = io.open(fileName, 'r')
if not file then return nil end
local data = {};
local section;
for line in file:lines() do
local tempSection = line:match('^%[([^%[%]]+)%]$');
if tempSection then
section = tonumber(tempSection) and tonumber(tempSection) or tempSection;
data[section] = data[section] or {}
end
local param, value = line:match('^%s-([%w|_]+)%s-=%s+(.+)$')
if(param and value ~= nil)then
if(tonumber(value))then
value = tonumber(value);
elseif(value == 'true')then
value = true;
elseif(value == 'false')then
value = false;
end
if(tonumber(param))then
param = tonumber(param);
end
data[section][param] = value
end
end
file:close();
return data;
end
---
-- Escapes every non-alphanumeric character in string with % symbol. This is required
-- because string.gsub treats plain strings with some symbols (e.g. dashes) as regular
-- expressions (taken from http://stackoverflow.com/a/34953646)
-- @param {string} text Text to escape
-- @returns {string} Escaped text
---
local function escape(text)
return text and text:gsub("([^%w])", "%%%1") or ""
end
local git = {}
git.get_config = function (git_dir, section, param)
if not git_dir then return nil end
if (not param) or (not section) then return nil end
local git_config = load_ini(git_dir..'/config')
if not git_config then return nil end
return git_config[section] and git_config[section][param] or nil
end
local function git_prompt_filter()
-- Check for Cmder configured Git Status Opt In/Out - See: https://github.com/cmderdev/cmder/issues/2484
if cmderGitStatusOptIn == false then return false end -- luacheck: globals cmderGitStatusOptIn
local git_dir = gitutil.get_git_dir()
if not git_dir then return false end
-- if we're inside of git repo then try to detect current branch
local branch = gitutil.get_git_branch(git_dir)
if not branch then return false end
-- for remote and ref resolution algorithm see https://git-scm.com/docs/git-push
local remote_to_push = git.get_config(git_dir, 'branch "'..branch..'"', 'remote') or ''
local remote_ref = git.get_config(git_dir, 'remote "'..remote_to_push..'"', 'push') or
git.get_config(git_dir, 'push', 'default')
local text = remote_to_push
if (remote_ref) then text = text..'/'..remote_ref end
if (text == '') then
clink.prompt.value = clink.prompt.value:gsub(escape('('..branch), '%1'..text)
else
clink.prompt.value = clink.prompt.value:gsub(escape('('..branch), '%1 -> '..text)
end
return false
end
-- Register filter with priority 60 which is greater than
-- Cmder's git prompt filters to override them
clink.prompt.register_filter(git_prompt_filter, 60)

View File

@@ -0,0 +1,81 @@
local w = require('tables').wrap
local parser = clink.arg.new_parser
local function exec_kubectl(arguments, template)
local f = io.popen("kubectl "..arguments.." -o template --template=\""..template.."\"")
if not f then return w({}) end
local output = f:read('*all')
f:close()
local res = w({})
for element in output:gmatch("%S+") do table.insert(res, element) end
return res
end
local function get_config(config)
return exec_kubectl("config view", "{{ range ."..config.." }}{{ .name }} {{ end }}")
end
local function get_config_func(config)
return function()
return get_config(config)
end
end
local function get_resources(noun)
return exec_kubectl("get "..noun, "{{ range .items }}{{ .metadata.name }} {{ end }}")
end
local function get_resources_func(noun)
return function()
return get_resources(noun)
end
end
local resource_parser = parser(
{
"all" .. parser({get_resources_func("all")}),
"node" .. parser({get_resources_func("node")}),
"service" .. parser({get_resources_func("service")}),
"pod" .. parser({get_resources_func("pod")}),
"deployment" .. parser({get_resources_func("deployment")})
}
)
local scale_parser = parser(
{
"deployment" .. parser({get_resources_func("deployment")}, parser({"--replicas"}))
}
)
local config_parser = parser(
{
"current-context",
"delete-cluster",
"delete-context",
"get-clusters",
"get-contexts",
"rename-context",
"set",
"set-cluster",
"set-context",
"set-credentials",
"unset",
"use-context" .. parser({get_config_func("contexts")}),
"view"
}
)
local kubectl_parser = parser(
{
"apply",
"exec" .. parser({get_resources_func("pod")}, parser({ "-it"})),
"get" .. resource_parser,
"describe" .. resource_parser,
"logs" .. parser({get_resources_func("pod")}),
"port-forward" .. parser({get_resources_func("pod")}),
"scale" .. scale_parser,
"config" .. config_parser
}
)
clink.arg.register_parser("kubectl", kubectl_parser)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
local exports = {}
-- Busted runs these modules scripts *outside* of Clink.
-- So these Clink scripts have to work without any Clink APIs being available.
clink = clink or {}
local clink_version_encoded = clink.version_encoded or 0
exports.supports_display_filter_description = (clink_version_encoded >= 10010012)
exports.supports_color_settings = (clink_version_encoded >= 10010009)
exports.supports_query_rl_var = (clink_version_encoded >= 10010009)
return exports

View File

@@ -0,0 +1,41 @@
local clink_version = require('clink_version')
local exports = {}
exports.BLACK = 0
exports.RED = 1
exports.GREEN = 2
exports.YELLOW = 3
exports.BLUE = 4
exports.MAGENTA = 5
exports.CYAN = 6
exports.WHITE = 7
exports.DEFAULT = 9
exports.BOLD = 1
exports.set_color = function (fore, back, bold)
local err_message = "All arguments must be either nil or numbers between 0-9"
assert(fore == nil or (type(fore) == "number" and fore >= 0 and fore <=9), err_message)
assert(back == nil or (type(back) == "number" and back >= 0 and back <=9), err_message)
fore = fore or exports.DEFAULT
back = back or exports.DEFAULT
bold = bold and exports.BOLD or 22
return "\x1b[3"..fore..";"..bold..";".."4"..back.."m"
end
exports.get_clink_color = function (setting_name)
-- Clink's settings.get() returns SGR parameters for a CSI SGR escape code.
local sgr = clink_version.supports_color_settings and settings.get(setting_name) or ""
if sgr ~= "" then
sgr = "\x1b["..sgr.."m"
end
return sgr
end
exports.color_text = function (text, fore, back, bold)
return exports.set_color(fore, back, bold)..text..exports.set_color()
end
return exports

View File

@@ -0,0 +1,100 @@
local exports = {}
--- Implementation of table.filter function. Applies filter function to each
-- element of table and returns a new table with values for which filter
-- returns 'true'.
--
-- @param tbl a table to filter. Default is an empty table.
-- @param filter function that accepts an element of table, specified in the
-- first argument and returns either 'true' or 'false'. If not specified,
-- then default function is used that returns its argument.
--
-- @return a new table with values that are not filtered out by 'filter' function.
exports.filter = function (tbl, filter)
if not tbl then return {} end
if not filter then filter = function(v) return v end end
local ret = {}
for _,v in ipairs(tbl) do
if filter(v) then table.insert(ret, v) end
end
return ret
end
--- Implementation of table.map function. Applies filter function to each
-- element of table and returns a new table with values returned by mapper
-- function.
--
-- @param tbl a table to filter. Default is an empty table.
-- @param map_func function that accepts an element of table, specified in the
-- first argument and returns a new value for resultant table. If not
-- specified, then 'map' function returns it input table.
--
-- @return a new table with values produced by 'map_func'.
exports.map = function (tbl, map_func)
assert(tbl == nil or type(tbl) == "table",
"First argument must be either table or nil")
assert(map_func == nil or type(map_func) == "function",
"Second argument must be either function or nil")
if tbl == nil then return {} end
if not map_func then return tbl end
local ret = {}
for _,v in ipairs(tbl) do
table.insert(ret, map_func(v))
end
return ret
end
--- Implementation of table.reduce function. Iterates through table and calls
-- 'func' function passing an accumulator and an entry from the original
-- table. The result of table is stored in accumulator and passed to next
-- 'func' call.
--
-- @param accum an accumulator, initial value that will be passed to first
-- 'func' call.
-- @param tbl a table to reduce. Default is an empty table.
-- @param func function that accepts two params: an accumulator and an element
-- of table, specified in the first argument and returns a new value for
-- accumulator.
--
-- @return a resultant accumulator value.
exports.reduce = function (accum, tbl, func)
assert(type(func) == "function",
"Third argument must be a function")
if not tbl then return accum end
for _,v in ipairs(tbl) do
accum = func(accum, v)
end
return accum
end
--- Concatenates any number of input values into one table. If input parameter is
-- a table then its values is copied to the end of resultant table. If the
-- parameter is single value, then it is appended to the resultant table. If
-- the input value is 'nil', then it is omitted.
--
-- @return a result of concatenation. The result is always a table.
exports.concat = function (...)
local input = {...}
local ret = {}
local i = 1
while i <= #input do
local arg = input[i]
if type(arg) == 'table' then
for _,v in ipairs(arg) do
table.insert(ret, v)
end
elseif arg ~= nil then
table.insert(ret, arg)
end
i = i + 1
end
return ret
end
return exports

View File

@@ -0,0 +1,83 @@
local path = require('path')
local exports = {}
---
-- Resolves closest .git directory location.
-- Navigates subsequently up one level and tries to find .git directory
-- @param {string} path Path to directory will be checked. If not provided
-- current directory will be used
-- @return {string} Path to .git directory or nil if such dir not found
exports.get_git_dir = function (start_dir)
-- Checks if provided directory contains '.git' directory
-- and returns path to that directory
local function has_git_dir(dir)
return #clink.find_dirs(dir..'/.git') > 0 and dir..'/.git'
end
-- checks if directory contains '.git' _file_ and if it does
-- parses it and returns a path to git directory from that file
local function has_git_file(dir)
local gitfile = io.open(dir..'/.git')
if not gitfile then return false end
local git_dir = gitfile:read():match('gitdir: (.*)')
gitfile:close()
if not git_dir then return false end
-- If found path is absolute don't prepend initial
-- directory - return absolute path value
return path.is_absolute(git_dir) and git_dir
or dir..'/'..git_dir
end
-- Set default path to current directory
if not start_dir or start_dir == '.' then start_dir = clink.get_cwd() end
-- Calculate parent path now otherwise we won't be
-- able to do that inside of logical operator
local parent_path = path.pathname(start_dir)
return has_git_dir(start_dir)
or has_git_file(start_dir)
-- Otherwise go up one level and make a recursive call
or (parent_path ~= start_dir and exports.get_git_dir(parent_path) or nil)
end
exports.get_git_common_dir = function (start_dir)
local git_dir = exports.get_git_dir(start_dir)
if not git_dir then return git_dir end
local commondirfile = io.open(git_dir..'/commondir')
if commondirfile then
-- If there's a commondir file, we're in a git worktree
local commondir = commondirfile:read()
commondirfile.close()
return path.is_absolute(commondir) and commondir
or git_dir..'/'..commondir
end
return git_dir
end
---
-- Find out current branch
-- @return {nil|git branch name}
---
exports.get_git_branch = function (dir)
local git_dir = dir or exports.get_git_dir()
-- If git directory not found then we're probably outside of repo
-- or something went wrong. The same is when head_file is nil
local head_file = git_dir and io.open(git_dir..'/HEAD')
if not head_file then return end
local HEAD = head_file:read()
head_file:close()
-- if HEAD matches branch expression, then we're on named branch
-- otherwise it is a detached commit
local branch_name = HEAD:match('ref: refs/heads/(.+)')
return branch_name or 'HEAD detached at '..HEAD:sub(1, 7)
end
return exports

View File

@@ -0,0 +1,80 @@
local exports = {}
local path = require('path')
local w = require('tables').wrap
exports.dirs = function(word)
-- Strip off any path components that may be on text.
local prefix = ""
local i = word:find("[\\/:][^\\/:]*$")
if i then
prefix = word:sub(1, i)
end
local include_dots = word:find("%.+$") ~= nil
-- Find matches.
local matches = w(clink.find_dirs(word.."*", true))
:filter(function (dir)
return clink.is_match(word, prefix..dir) and
(include_dots or path.is_real_dir(dir))
end)
:map(function(dir)
return prefix..dir
end)
-- If there was no matches but word is a dir then use it as the single match.
-- Otherwise tell readline that matches are files and it will do magic.
if #matches == 0 and clink.is_dir(rl_state.text) then
return {rl_state.text}
end
clink.matches_are_files()
return matches
end
exports.files = function (word)
-- Strip off any path components that may be on text.
local prefix = ""
local i = word:find("[\\/:][^\\/:]*$")
if i then
prefix = word:sub(1, i)
end
-- Find matches.
local matches = w(clink.find_files(word.."*", true))
:filter(function (file)
return clink.is_match(word, prefix..file)
end)
:map(function(file)
return prefix..file
end)
-- Tell readline that matches are files and it will do magic.
if #matches ~= 0 then
clink.matches_are_files()
end
return matches
end
exports.create_dirs_matcher = function (dir_pattern, show_dotfiles)
return function (token)
return w(clink.find_dirs(dir_pattern))
:filter(function(dir)
return clink.is_match(token, dir) and (path.is_real_dir(dir) or show_dotfiles)
end )
end
end
exports.create_files_matcher = function (file_pattern)
return function (token)
return w(clink.find_files(file_pattern))
:filter(function(file)
-- Filter out '.' and '..' entries as well
return clink.is_match(token, file) and path.is_real_dir(file)
end )
end
end
return exports

View File

@@ -0,0 +1,69 @@
local exports = {}
local w = require('tables').wrap
exports.list_files = function (base_path, glob, recursive, reverse_separator)
local mask = glob or '/*'
local entries = w(clink.find_files(base_path..mask))
:filter(function(entry)
return exports.is_real_dir(entry)
end)
local files = entries:filter(function(entry)
return not clink.is_dir(base_path..'/'..entry)
end)
-- if 'recursive' flag is not set, we don't need to iterate
-- through directories, so just return files found
if not recursive then return files end
local sep = reverse_separator and '/' or '\\'
return entries
:filter(function(entry)
return clink.is_dir(base_path..'/'..entry)
end)
:reduce(files, function(accum, dir)
-- iterate through directories and call list_files recursively
return exports.list_files(base_path..'/'..dir, mask, recursive, reverse_separator)
:map(function(entry)
return dir..sep..entry
end)
:concat(accum)
end)
end
exports.basename = function (path)
local prefix = path
local i = path:find("[\\/:][^\\/:]*$")
if i then
prefix = path:sub(i + 1)
end
return prefix
end
exports.pathname = function (path)
local prefix = ""
local i = path:find("[\\/:][^\\/:]*$")
if i then
prefix = path:sub(1, i-1)
end
return prefix
end
exports.is_absolute = function (path)
local drive = path:find("^%s?[%l%a]:[\\/]")
if drive then return true else return false end
end
exports.is_metadir = function (dirname)
return exports.basename(dirname) == '.'
or exports.basename(dirname) == '..'
end
exports.is_real_dir = function (dirname)
return not exports.is_metadir(dirname)
end
return exports

View File

@@ -0,0 +1,74 @@
local concat = require('funclib').concat
local filter = require('funclib').filter
local map = require('funclib').map
local reduce = require('funclib').reduce
local exports = {}
local wrap_filter = function (tbl, filter_func)
return exports.wrap(filter(tbl, filter_func))
end
local wrap_map = function (tbl, map_func)
return exports.wrap(map(tbl, map_func))
end
local wrap_reduce = function (tbl, accum, reduce_func)
local res = reduce(accum, tbl, reduce_func)
return (type(res) == "table" and exports.wrap(res) or res)
end
local wrap_concat = function (tbl, ...)
return exports.wrap(concat(tbl, ...))
end
local wrap_print = function (tbl)
return exports.wrap(filter(tbl, function (item)
print(item)
return true
end))
end
exports.wrap = function (tbl)
if tbl == nil then tbl = {} end
if type(tbl) ~= "table" then tbl = {tbl} end
local mt = getmetatable(tbl) or {}
mt.__index = mt.__index or {}
mt.__index.filter = wrap_filter
mt.__index.map = wrap_map
mt.__index.reduce = wrap_reduce
mt.__index.concat = wrap_concat
mt.__index.print = wrap_print
mt.__index.keys = function (arg)
local res = {}
for k,_ in pairs(arg) do
table.insert(res, k)
end
return exports.wrap(res)
end
mt.__index.sort = function (arg)
table.sort(arg)
return arg
end
mt.__index.dedupe = function (arg)
local res, hash = {}, {}
for _,v in ipairs(arg) do
if not hash[v] then
hash[v] = true
table.insert(res, v)
end
end
return exports.wrap(res)
end
mt.__index.contains = function (arg, value)
for _,v in ipairs(arg) do
if v == value then return true, _ end
end
return false
end
return setmetatable(tbl, mt)
end
return exports

View File

@@ -0,0 +1,36 @@
local parser = clink.arg.new_parser
local net_parser = parser(
{
"accounts" .. parser("/forcelogoff:", "/forcelogoff:no", "/domain",
"/maxpwage:", "/maxpwage:unlimited", "/minpwage:",
"/minpwlen:","/uniquepw:"),
"computer" .. parser({"*" .. parser("/add", "/del")}),
"config" .. parser({"server", "workstation"}),
"continue",
"file",
"group",
"helpmsg",
"localgroup",
"pause",
"session" .. parser({parser("/delete", "/list")}),
"share",
"start",
"statistics" .. parser({"server", "workstation"}),
"stop",
"time" .. parser("/domain", "/rtsdomain", "/set"),
"use" .. parser("/user:", "/smartcard", "/savecred", "/delete",
"/persistent:yes", "/persistent:no"),
"user",
"view" .. parser("/cache", "/all", "/domain")
},
"/?"
)
local help_parser = parser(
{
"help" .. parser({net_parser:flatten_argument(1), "names", "services", "syntax"})
}
)
clink.arg.register_parser("net", net_parser)
clink.arg.register_parser("net", help_parser)

View File

@@ -0,0 +1,238 @@
-- preamble: common routines
local JSON = require("JSON")
-- silence JSON parsing errors
function JSON:assert () end -- luacheck: no unused args
local color = require('color')
local w = require('tables').wrap
local matchers = require('matchers')
---
-- Queries config options value using 'npm config' call
-- @param {string} config_entry Config option name
-- @return {string} Config value for specific option or
-- empty string in case of any error
---
local function get_npm_config_value (config_entry)
assert(config_entry and type(config_entry) == "string" and #config_entry > 0,
"get_npm_config_value: config_entry param should be non-empty string")
local proc = io.popen("npm config get "..config_entry.." 2>nul")
if not proc then return "" end
local value = proc:read()
proc:close()
return value or nil
end
local modules = matchers.create_dirs_matcher('node_modules/*')
local cache_location = nil
local cached_modules_matcher = nil
local function cached_modules(token)
-- If we already have matcher then just return it
if cached_modules_matcher then return cached_modules_matcher(token) end
-- otherwise try to get cache location and return empty table if failed
cache_location = cache_location or get_npm_config_value("cache")
if not cache_location then return {} end
-- Create a new matcher, save it in module's variable for further usage and return it
cached_modules_matcher = matchers.create_dirs_matcher(cache_location..'/*')
return cached_modules_matcher(token)
end
local globals_location = nil
local global_modules_matcher = nil
local function global_modules(token)
-- If we already have matcher then just return it
if global_modules_matcher then return global_modules_matcher(token) end
-- If token starts with . or .. or has path delimiter then return empty
-- result and do not create a matcher so only fs paths will be completed
if (token:match('^%.(%.)?') or token:match('[%\\%/]+')) then return {} end
-- otherwise try to get cache location and return empty table if failed
globals_location = globals_location or get_npm_config_value("prefix")
if not globals_location then return {} end
-- Create a new matcher, save it in module's variable for further usage and return it
global_modules_matcher = matchers.create_dirs_matcher(globals_location..'/node_modules/*')
return global_modules_matcher(token)
end
-- Reads package.json in current directory and extracts all "script" commands defined
local function scripts(token) -- luacheck: no unused args
-- Read package.json first
local package_json = io.open('package.json')
-- If there is no such file, then close handle and return
if package_json == nil then return w() end
-- Read the whole file contents
local package_contents = package_json:read("*a")
package_json:close()
local package_scripts = JSON:decode(package_contents).scripts
return w(package_scripts):keys()
end
local parser = clink.arg.new_parser
-- end preamble
local install_parser = parser({matchers.dirs},
"--force",
"-g", "--global",
"--link",
"--no-bin-links",
"--no-optional",
"--no-shrinkwrap",
"--nodedir=/",
"--production",
"--save", "--save-dev", "--save-optional",
"--tag"
):loop(1)
-- TODO: list only global modules with -g
local remove_parser = parser({modules}, "-g", "--global"):loop(1)
local search_parser = parser("--long")
local script_parser = parser({scripts})
local list_parser = parser(
{modules},
"--prod", "--production",
"--dev", "--development",
"--only"..parser({"dev", "prod"}),
"--json",
"--long",
"--parseable",
"--global", "-g",
"--depth",
"--link"
)
local npm_parser = parser({
"add-user",
"adduser",
"apihelp",
"audit"..parser({
"fix"..parser("--force", "--package-lock-only", "--dry-run", "--production", "--only=dev"),
"--json",
"--parseable"
}),
"author",
"bin",
"bugs",
"c",
"cache"..parser({
"add"..parser({matchers.dirs}),
"clean"..parser({cached_modules}),
"ls"
}),
"completion",
"config",
"ddp",
"dedupe",
"deprecate",
"docs",
"edit",
"explore",
"faq",
"find" .. search_parser,
"find-dupes",
"get",
"help",
"help-search",
"home",
"info",
"init",
"install" .. install_parser,
"issues",
"la",
"link"..parser({matchers.files, global_modules}),
"list"..list_parser,
"ll"..list_parser,
"ln"..parser({matchers.files, global_modules}),
"login",
"ls"..list_parser,
"outdated"..parser(
"--json",
"--long",
"--parseable",
"--global",
"--depth"
),
"owner",
"pack",
"prefix",
"prune",
"publish"..parser(
"--tag",
"--access"..parser({"public", "restricted"})
),
"r",
"rb",
"rebuild",
"rm" .. remove_parser,
"remove" .. remove_parser,
"repo",
"restart",
"root",
"run"..script_parser,
"run-script"..script_parser,
"search" .. search_parser,
"set",
"show",
"shrinkwrap",
"star",
"stars",
"start",
"stop",
"submodule",
"tag",
"test",
"un",
"uninstall" .. remove_parser,
"unlink",
"unpublish",
"unstar",
"up"..parser({modules}),
"update"..parser({modules}),
"v",
"version",
"view",
"whoami"
},
"-h", "--version"
)
clink.arg.register_parser("npm", npm_parser)
local function npm_prompt_filter()
local package_file = io.open('package.json')
if not package_file then return false end
local package_data = package_file:read('*a')
package_file:close()
local package = JSON:decode(package_data)
-- Bail out if package.json is malformed
if not package then return false end
-- Don't print package info when the package is private or both version and name are missing
if package.private or (not package.name and not package.version) then return false end
local package_name = package.name or "<no name>"
local package_version = package.version and "@"..package.version or ""
local package_string = color.color_text("("..package_name..package_version..")", color.YELLOW)
clink.prompt.value = clink.prompt.value:gsub('{git}', '{git} '..package_string)
return false
end
clink.prompt.register_filter(npm_prompt_filter, 40)

View File

@@ -0,0 +1,46 @@
local path = require('path')
local w = require('tables').wrap
local parser = clink.arg.new_parser
local NVM_ROOT
local function get_nvm_root()
if NVM_ROOT then return NVM_ROOT end
local proc = io.popen("nvm root")
if not proc then
NVM_ROOT = ""
return NVM_ROOT
end
local lines = proc:read('*all')
NVM_ROOT = lines:match("Current Root:%s(.*)%s*\n$") or ""
proc:close()
return NVM_ROOT
end
local installed = function ()
return w(clink.find_dirs(get_nvm_root().."/*"))
:filter(path.is_real_dir)
:map(function (dir)
return dir:match("v(.*)")
end)
end
local archs = parser({"64", "32"})
local nvm_parser = parser({
"arch"..archs,
"install"..parser({"latest"}, archs),
"list"..parser({installed, "available"}),
"ls"..parser({installed, "available"}),
"on", "off",
"proxy"..parser({"none"}),
"uninstall"..parser({installed}),
"use"..parser({installed}, archs),
"root",
"version", "v"
}, "-h", "--help", "-v", "--version")
clink.arg.register_parser("nvm", nvm_parser)

View File

@@ -0,0 +1,240 @@
-- -*- coding: utf-8 -*-
-- preamble: common routines
local matchers = require("matchers")
local w = require("tables").wrap
local parser = clink.arg.new_parser
local function pip_libs_list(token)
local handle = io.popen('python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"')
local python_lib_path = handle:read("*a")
handle:close()
-- trim spaces
python_lib_path = python_lib_path:gsub("^%s*(.-)%s*$", "%1")
local finder = matchers.create_files_matcher(python_lib_path .. "\\*.dist-info")
local list = w(finder(token))
list =
list:map(
function(package)
package = package:gsub("-[%d%.]+dist%-info$", "")
return package
end
)
return list
end
local pip_default_flags = {
"--help",
"-h",
"--isolated",
"--verbose",
"-v",
"--version",
"-V",
"--quiet",
"-q",
"--log",
"--proxy",
"--retries",
"--timeout",
"--exists-action",
"--trusted-host",
"--cert",
"--client-cert",
"--cache-dir",
"--no-cache-dir",
"--disable-pip-version-check",
"--no-color"
}
local pip_requirement_flags = {
"--requirement" .. parser({clink.matches_are_files}),
"-r" .. parser({clink.matches_are_files})
}
local pip_index_flags = {
"--index-url",
"-i",
"--extra-index-url",
"--no-index",
"--find-links",
"-f"
}
local pip_install_download_wheel_flags = {
pip_requirement_flags,
"--no-binary",
"--only-binary",
"--prefer-binary",
"--no-build-isolation",
"--use-pep517",
"--constraint",
"-c",
"--src",
"--no-deps",
"--progress-bar" .. parser({"off", "on", "ascii", "pretty", "emoji"}),
"--global-option",
"--pre",
"--no-clean",
"--requires-hashes"
}
local pip_install_download_flags = {
pip_install_download_wheel_flags,
"--platform",
"--python-version",
"--implementation" .. parser({"pp", "jy", "cp", "ip"}),
"--abi"
}
local pip_install_parser =
parser(
{},
"--editable",
"-e",
"--target",
"-t",
"--user",
"--root",
"--prefix",
"--build",
"-b",
"--upgrade",
"-U",
"--upgrade-strategy" .. parser({"eager", "only-if-needed"}),
"--force-reinstall",
"--ignore-installed",
"-I",
"--ignore-requires-python",
"--install-option",
"--compile",
"--no-compile",
"--no-warn-script-location",
"--no-warn-conflicts"
):loop(1)
pip_install_parser:add_flags(pip_install_download_flags)
pip_install_parser:add_flags(pip_index_flags)
pip_install_parser:add_flags(pip_default_flags)
local pip_download_parser = parser({}, "--build", "-b", "--dest", "-d"):loop(1)
pip_download_parser:add_flags(pip_install_download_flags)
pip_download_parser:add_flags(pip_index_flags)
pip_download_parser:add_flags(pip_default_flags)
local pip_uninstall_parser =
parser({pip_libs_list}, "--yes", "-y"):add_flags(pip_default_flags, pip_requirement_flags):loop(1)
local pip_freeze_parser = parser({}, "--find-links", "--local", "-l", "--user", "--all", "--exclude-editable")
pip_freeze_parser:add_flags(pip_default_flags, pip_requirement_flags)
local pip_list_parser =
parser(
{},
"--outdated",
"-o",
"--uptodate",
"-u",
"--editable",
"-e",
"--local",
"-l",
"--user",
"--pre",
"--format" .. parser({"columns", "freeze", "json"}),
"--not-required",
"--exclude-editable",
"--include-editable"
)
pip_list_parser:add_flags(pip_default_flags)
local pip_config_parser =
parser(
{
"list",
"edit",
"get",
"set",
"unset"
},
"--editor",
"--global",
"--user",
"--venv",
pip_default_flags
)
pip_config_parser:add_flags(pip_default_flags)
local pip_search_parser = parser({}, "--index", "-i"):add_flags(pip_default_flags)
local pip_wheel_parser =
parser(
{},
"--wheel-dir",
"-w",
"--build-option",
"--editable",
"-e",
"--ignore-requires-python",
"--build",
"-b"
):loop(1)
pip_wheel_parser:add_flags(pip_install_download_flags)
pip_wheel_parser:add_flags(pip_index_flags)
pip_wheel_parser:add_flags(pip_default_flags)
local pip_hash_parser =
parser(
{},
"--algorithm" .. parser({"sha256", "sha384", "sha512"}),
"-a" .. parser({"sha256", "sha384", "sha512"}),
pip_default_flags
)
pip_hash_parser:add_flags(pip_default_flags)
local pip_completion_parser = parser({}, "--bash", "-b", "--zsh", "-z", "--fish", "-f"):add_flags(pip_default_flags)
local pip_help_parser =
parser(
{
"install",
"download",
"uninstall",
"freeze",
"list",
"show",
"config",
"search",
"wheel",
"hash",
"completion",
"help"
}
)
pip_help_parser:add_flags(pip_default_flags)
local pip_parser =
parser(
{
"install" .. pip_install_parser,
"download" .. pip_download_parser,
"uninstall" .. pip_uninstall_parser,
"freeze" .. pip_freeze_parser,
"list" .. pip_list_parser,
"show" .. parser({pip_libs_list}, pip_default_flags),
"config" .. pip_config_parser,
"search" .. pip_search_parser,
"wheel" .. pip_wheel_parser,
"hash" .. pip_hash_parser,
"completion" .. pip_completion_parser,
"help" .. pip_help_parser
}
)
pip_parser:add_flags(pip_default_flags)
clink.arg.register_parser("pip", pip_parser)

View File

@@ -0,0 +1,163 @@
-- -*- coding: utf-8 -*-
-- preamble: common routines
local matchers = require("matchers")
local w = require("tables").wrap
local concat = require("funclib").concat
local parser = clink.arg.new_parser
local function pipenv_libs_list(token)
local handle = io.popen('python -c "import sys; print(\\";\\".join(sys.path))"')
local result = handle:read("*a")
handle:close()
-- trim spaces
result = clink.get_cwd() .. result:gsub("^%s*(.-)%s*$", "%1")
local lib_paths = clink.split(result, ";")
local list = w()
for lib_path in lib_paths do
local finder = matchers.create_files_matcher(lib_path)
local libs = finder(token)
libs =
libs:filter(
function(v)
return clink.is_dir(lib_path .. "/" .. v) or string.find(v, "%.py$")
end
)
list = w(concat(list, libs))
end
-- remove ".py" and "-1.2.3-dist-info" of file name
for k, v in pairs(list) do
list[k] = v:gsub(".py", ""):gsub("-[%d%.]+dist%-info$", "")
end
return list
end
local pipenv_default_flags = {
"--python",
"--three",
"--two",
"--clear",
"--verbose",
"-v",
"--pypi-mirror",
"--help",
"-h"
}
local pipenv_check_parser = parser():add_flags(pipenv_default_flags, "--unused", "--ignore", "-i", "--system"):loop(1)
local pipenv_clean_parser = parser():add_flags(pipenv_default_flags, "--bare", "--dry-run")
local pipenv_graph_parser = parser():add_flags(pipenv_default_flags, "--bare", "--json", "--json-tree", "--reverse")
local pipenv_install_parser =
parser():add_flags(
pipenv_default_flags,
"--system",
"--code",
"-c",
"--deploy",
"--skip-lock",
"--editable",
"-e",
"--ignore-pipfile",
"--selective-upgrade",
"--pre",
"--requirements" .. parser({clink.matches_are_files}),
"-r" .. parser({clink.matches_are_files}),
"--extra-index-url",
"--index",
"-i",
"--sequential",
"--keep-outdated",
"--dev",
"-d"
):loop(1)
local pipenv_lock_parser =
parser():add_flags(pipenv_default_flags, "--requirements", "-r", "--keep-outdated", "--pre", "--dev", "-d")
local pipenv_open_parser = parser({pipenv_libs_list}):add_flags(pipenv_default_flags)
local pipenv_run_parser = parser():add_flags(pipenv_default_flags)
local pipenv_shell_parser = parser():add_flags("--fancy", "--anyway", pipenv_default_flags)
local pipenv_sync_parser =
parser():add_flags("--bare", "--sequential", "--keep-outdated", "--pre", "--dev", "-d", pipenv_default_flags)
local pipenv_uninstall_parser =
parser():add_flags(
"--skip-lock",
"--lock",
"--all-dev",
"--all",
"--editable",
"-e",
"--keep-outdated",
"--pre",
"--dev",
"-d",
pipenv_default_flags
)
local pipenv_update_parser =
parser():add_flags(
"--bare",
"--outdated",
"--dry-run",
"--editable",
"-e",
"--ignore-pipfile",
"--selective-upgrade",
"--pre",
"--requirements",
"-r",
"--extra-index-url",
"--index",
"-i",
"--sequential",
"--keep-outdated",
"--dev",
"-d",
pipenv_default_flags
)
local pipenv_parser =
parser(
{
"check" .. pipenv_check_parser,
"clean" .. pipenv_clean_parser,
"graph" .. pipenv_graph_parser,
"install" .. pipenv_install_parser,
"lock" .. pipenv_lock_parser,
"open" .. pipenv_open_parser,
"run" .. pipenv_run_parser,
"shell" .. pipenv_shell_parser,
"sync" .. pipenv_sync_parser,
"uninstall" .. pipenv_uninstall_parser,
"update" .. pipenv_update_parser
}
):add_flags(
pipenv_default_flags,
"--where",
"--venv",
"--py",
"--envs",
"--rm",
"--bare",
"--completion",
"--man",
"--support",
"--site-packages",
"--version"
)
clink.arg.register_parser("pipenv", pipenv_parser)

View File

@@ -0,0 +1,343 @@
-- -*- coding: utf-8 -*-
-- preamble: common routines
local JSON = require("JSON")
local matchers = require("matchers")
local path = require("path")
local w = require("tables").wrap
local concat = require("funclib").concat
local parser = clink.arg.new_parser
local profile = os.getenv("home") or os.getenv("USERPROFILE")
local function scoop_folder()
local folder = os.getenv("SCOOP")
if not folder then
folder = profile .. "\\scoop"
end
return folder
end
local function scoop_global_folder()
local folder = os.getenv("SCOOP_GLOBAL")
if not folder then
folder = os.getenv("ProgramData") .. "\\scoop"
end
return folder
end
local function scoop_load_config() -- luacheck: no unused args
local file = io.open(profile .. "\\.config\\scoop\\config.json")
-- If there is no such file, then close handle and return
if file == nil then
return w()
end
-- Read the whole file contents
local contents = file:read("*a")
file:close()
-- strip UTF-8-BOM
local utf8_len = contents:len()
local pat_start, _ = string.find(contents, "{")
contents = contents:sub(pat_start, utf8_len)
local data = JSON:decode(contents)
if data == nil then
return w()
end
return data
end
local function scoop_alias_list(token) -- luacheck: no unused args
local data = scoop_load_config()
return w(data.alias):keys()
end
local function scoop_config_list(token) -- luacheck: no unused args
local data = scoop_load_config()
return w(data):keys()
end
local function scoop_bucket_known_list(token) -- luacheck: no unused args
local file = io.open(scoop_folder() .. "\\apps\\scoop\\current\\buckets.json")
-- If there is no such file, then close handle and return
if file == nil then
return w()
end
-- Read the whole file contents
local contents = file:read("*a")
file:close()
local data = JSON:decode(contents)
return w(data):keys()
end
local function scoop_bucket_list(token)
local finder = matchers.create_files_matcher(scoop_folder() .. "\\buckets\\*")
local list = finder(token)
return list:filter(path.is_real_dir)
end
local function scoop_apps_list(token)
local folders = {scoop_folder(), scoop_global_folder()}
local list = w()
for _, folder in pairs(folders) do
local finder = matchers.create_files_matcher(folder .. "\\apps\\*")
local new_list = finder(token)
list = w(concat(list, new_list))
end
return list:filter(path.is_real_dir)
end
local function scoop_available_apps_list(token)
-- search in default bucket
local finder = matchers.create_files_matcher(scoop_folder() .. "\\apps\\scoop\\current\\bucket\\*.json")
local list = finder(token)
-- search in each installed bucket
local buckets = scoop_bucket_list("")
for _, bucket in pairs(buckets) do
local bucket_folder = scoop_folder() .. "\\buckets\\" .. bucket
-- check the bucket folder exists
if clink.is_dir(bucket_folder .. "\\bucket") then
bucket_folder = bucket_folder .. "\\bucket"
end
local b_finder = matchers.create_files_matcher(bucket_folder .. "\\*.json")
local b_list = b_finder(token)
list = w(concat(list, b_list))
end
-- remove ".json" of file name
for k, v in pairs(list) do
list[k] = v:gsub(".json", "")
end
return list
end
local function scoop_cache_apps_list(token)
local cache_folder = os.getenv("SCOOP_CACHE")
if not cache_folder then
cache_folder = scoop_folder() .. "\\cache"
end
local finder = matchers.create_files_matcher(cache_folder .. "\\*")
local list = finder(token)
list = w(list:filter(path.is_real_dir))
-- get name before "#" from cache list (name#version#url)
for k, v in pairs(list) do
list[k] = v:gsub("#.*$", "")
end
return list
end
local scoop_default_flags = {
"--help",
"-h"
}
local scoop_alias_parser =
parser(
{
"add",
"list" .. parser("-v", "--verbose"),
"rm" .. parser({scoop_alias_list})
}
)
local scoop_bucket_parser =
parser(
{
"add" .. parser({scoop_bucket_known_list}),
"list",
"known",
"rm" .. parser({scoop_bucket_list})
}
)
local scoop_cache_parser =
parser(
{
"show" .. parser({scoop_cache_apps_list, scoop_apps_list, "*"}),
"rm" .. parser({scoop_cache_apps_list, "*"})
}
)
local scoop_cleanup_parser =
parser(
{
scoop_apps_list,
"*"
},
"--global",
"-g",
"--cache",
"-k"
):loop(1)
local scoop_config_parser =
parser(
{
"rm" .. parser({scoop_config_list}),
scoop_config_list,
"aria2-enabled" .. parser({"true", "false"}),
"aria2-max-connection-per-server",
"aria2-min-split-size",
"aria2-options",
"aria2-retry-wait",
"aria2-split",
"debug" .. parser({"true", "false"}),
"proxy",
"show_update_log" .. parser({"true", "false"}),
"virustotal_api_key"
}
)
local scoop_uninstall_parser =
parser(
{
scoop_apps_list
},
"--global",
"-g",
"--purge",
"-p"
):loop(1)
local scoop_update_parser =
parser(
{
scoop_apps_list,
"*"
},
"--force",
"-f",
"--global",
"-g",
"--independent",
"-i",
"--no-cache",
"-k",
"--skip",
"-s",
"--quiet",
"-q"
):loop(1)
local scoop_install_parser =
parser(
{scoop_available_apps_list},
"--global",
"-g",
"--independent",
"-i",
"--no-cache",
"-k",
"--skip",
"-s",
"--arch" .. parser({"32bit", "64bit"}),
"-a" .. parser({"32bit", "64bit"})
):loop(1)
local scoop_help_parser =
parser(
{
"alias",
"bucket",
"cache",
"checkup",
"cleanup",
"config",
"create",
"depends",
"export",
"help",
"home",
"hold",
"info",
"install",
"list",
"prefix",
"reset",
"search",
"status",
"unhold",
"uninstall",
"update",
"virustotal",
"which"
},
"/?",
"--help",
"-h",
"--version"
)
local scoop_parser = parser()
scoop_parser:set_flags(scoop_default_flags)
scoop_parser:set_arguments(
{
scoop_alias_list,
"alias" .. scoop_alias_parser,
"bucket" .. scoop_bucket_parser,
"cache" .. scoop_cache_parser,
"checkup",
"cleanup" .. scoop_cleanup_parser,
"config" .. scoop_config_parser,
"create",
"depends" ..
parser(
{scoop_available_apps_list, scoop_apps_list},
"--arch" .. parser({"32bit", "64bit"}),
"-a" .. parser({"32bit", "64bit"})
),
"export",
"help" .. scoop_help_parser,
"hold" .. parser({scoop_apps_list}),
"home" .. parser({scoop_available_apps_list, scoop_apps_list}),
"info" .. parser({scoop_available_apps_list, scoop_apps_list}),
"install" .. scoop_install_parser,
"list",
"prefix" .. parser({scoop_apps_list}),
"reset" .. parser({scoop_apps_list}):loop(1),
"search",
"status",
"unhold" .. parser({scoop_apps_list}),
"uninstall" .. scoop_uninstall_parser,
"update" .. scoop_update_parser,
"virustotal" ..
parser(
{scoop_apps_list, "*"},
"--arch" .. parser({"32bit", "64bit"}),
"-a" .. parser({"32bit", "64bit"}),
"--scan",
"-s",
"--no-depends",
"-n"
):loop(1),
"which"
}
)
clink.arg.register_parser("scoop", scoop_parser)

View File

@@ -0,0 +1,84 @@
local color = require('color')
describe("color module", function()
it("should define color constants", function()
assert.are.equals(color.BLACK, 0)
assert.are.equals(color.RED, 1)
assert.are.equals(color.GREEN, 2)
assert.are.equals(color.YELLOW, 3)
assert.are.equals(color.BLUE, 4)
assert.are.equals(color.MAGENTA, 5)
assert.are.equals(color.CYAN, 6)
assert.are.equals(color.WHITE, 7)
assert.are.equals(color.DEFAULT, 9)
assert.are.equals(color.BOLD, 1)
end)
it("should export methods", function()
assert.are.equal(type(color.set_color), 'function')
assert.are.equal(type(color.get_clink_color), 'function')
assert.are.equal(type(color.color_text), 'function')
end)
describe("'set_color' method", function ()
local VALID_COLOR_STRING = "^\x1b%[(3%d);(%d%d?);(4%d)m$"
it("should accept numeric arguments and return string", function ()
assert.are.equal(type(color.set_color(1, 2, 3)), "string")
end)
it("should accept nil arguments and still return string", function ()
assert.are.equal(type(color.set_color()), "string")
end)
it("should throw if first two arguments are not a numbers or nil", function ()
assert.has.error(function() color.set_color('a', 2, 3) end)
assert.has.error(function() color.set_color(1, 'a', 3) end)
end)
it("should throw if arguments is out of range", function ()
assert.has.error(function() color.set_color(100, 1, 1) end)
assert.has.error(function() color.set_color(1, 200, 1) end)
end)
it("should return valid ANSI color code", function ()
-- TODO: either find appropriate assert or invent custom one
-- assert_match(VALID_COLOR_STRING, color.set_color(3, 2, 1))
end)
it("should set color to DEFAULT if no corresponding argument was passed", function ()
local _, _, fore, bold, back = string.find(color.set_color(), VALID_COLOR_STRING)
assert.are.equals(fore, "39");
assert.are.equals(back, "49");
assert.are.equals(bold, "22");
end)
end)
describe("'get_clink_color' method", function ()
it("should do nothing since Clink support is only available in actual Clink", function ()
assert.are.equals(color.get_clink_color('color.git.star'), "")
end)
end)
describe("'color_text' method", function ()
local TEST_STRING = "abc"
local VALID_COLOR_STRING = "\x1b%[3%d;%d%d?;4%dm"
it("should wrap string into valid ANSI codes", function ()
-- TODO: either find appropriate assert or invent custom one
-- assert_match("^"..VALID_COLOR_STRING..TEST_STRING..VALID_COLOR_STRING.."$",
-- color.color_text(TEST_STRING, 1, 2, 3))
end)
it("should reset color to default", function ()
local _,_, color_suffix = string.find(color.color_text(TEST_STRING, 1, 2, 3),
"^"..VALID_COLOR_STRING..TEST_STRING.."("..VALID_COLOR_STRING..")$")
assert.are.equals(color_suffix, color.set_color())
end)
end)
end)

View File

@@ -0,0 +1,146 @@
local map = require('funclib').map
local concat = require('funclib').concat
local filter = require('funclib').filter
local reduce = require('funclib').reduce
describe("funclib module", function()
it("should export some methods", function()
local methods_count = 0
-- iterate through table to count keys rather than `use #... notation
for _,_ in pairs(require("funclib")) do
methods_count = methods_count + 1 end
assert.are.equals(methods_count, 4)
end)
describe("'filter' function", function ()
local test_table = {"a", "b", nil, false}
it("should exist", function()
assert.are.equals(type(filter), "function")
end)
it("should accept nil arguments", function()
assert.has_no.errors(filter)
end)
it("should return empty table if input table is not specified", function()
assert.are.same(filter(), {})
end)
it("should throw if first argument is not a table", function()
assert.has_error(function() filter("aaa") end)
end)
it("should throw if second argument is not a function", function()
assert.has_error(function() filter({"a", "b"}, "a") end)
-- TODO: uncomment this
-- assert.has_error(function() filter({}, "a") end)
end)
it("should filter out falsy values if no filter function specified", function()
assert.are.same(filter(test_table), {"a", "b"})
end)
it("should filter out values which doesn't satisfy filter function", function()
local function test_filter1(a) return a == "a" end
local function test_filter2(a) return a == nil end
assert.are.same(filter(test_table, test_filter1), {"a"})
assert.are.same(filter(test_table, test_filter2), {nil})
end)
end)
describe("'map' function", function ()
local test_table = {"a", "b", "c"}
it("should exist", function()
assert.are.equals(type(map), "function")
end)
it("should accept nil arguments", function()
assert.has_no.errors(map)
end)
it("should return empty table if input table is not specified", function()
assert.are.same(map(), {})
end)
it("should throw if first argument is not a table", function()
assert.has_error(function() map("aaa") end)
end)
it("should throw if second argument is not a function", function()
assert.has_error(function() map(test_table, "a") end)
end)
it("should return original table if no map function specified", function()
assert.are.same(map(test_table), test_table)
end)
it("should apply map function to all values", function()
local function test_map(a) return a == "a" end
assert.are.same(map(test_table, test_map), {true, false, false})
end)
end)
describe("'reduce' function", function ()
local test_table = {1, 2, 3}
local _noop = function() end
it("should exist", function()
assert.are.equals(type(reduce), "function")
end)
it("should accept nil arguments (except reduce func)", function()
assert.has_no.errors(function() reduce(nil, nil, _noop) end)
end)
it("should return accumulator if input table is not specified", function()
assert.are.equals(reduce("accum", nil, _noop), "accum")
end)
it("should throw if second argument (source table) is not a table", function()
assert.has_error(function() reduce({}, "aaa", _noop) end)
end)
it("should throw if third argument (reduce func) is not a function", function()
assert.has_error(function() reduce({}, {}, "a") end)
-- TODO: uncomment this
-- assert.has_error(reduce)
end)
it("should apply reduce func to each element of source table", function()
local function test_reduce(a, v) table.insert(a, v+1) return a end
assert.are.same(reduce({}, test_table, test_reduce), {2, 3, 4})
end)
end)
describe("'concat' function", function ()
it("should exist", function()
assert.are.equals(type(concat), "function")
end)
it("should accept nil arguments", function()
assert.has_no.errors(concat)
end)
it("should return empty table if no input arguments specified", function()
assert.are.same(concat(), {})
end)
it("should wrap non-table parameter into a table", function()
local ret = concat("a")
assert.is_not.equals(ret, {})
assert.are.equals(type(ret), "table")
end)
it("should omit nil arguments", function()
assert.are.same(concat("a", nil, "b"), {"a", "b"})
end)
it("should copy values from table params into result", function()
assert.are.same(concat("a", {nil}, {"b"}), {"a", "b"})
end)
end)
end)

View File

@@ -0,0 +1,24 @@
local path = require('path')
describe("path module", function()
describe("is_absolute", function ()
it("should return true for absolute paths", function ()
assert.is_true(path.is_absolute("c:/foo.bar"))
assert.is_true(path.is_absolute("c:/foo.bar/baz"))
assert.is_true(path.is_absolute("c:\\foo.bar"))
assert.is_true(path.is_absolute("c:\\foo.bar\\baz"))
assert.is_true(path.is_absolute("z:/baz\\foo.bar"))
assert.is_true(path.is_absolute("z:\\baz/foo.bar"))
assert.is_true(path.is_absolute("c:/quux/..\\baz/foo.bar"))
end)
it("should return false for relative paths", function ()
assert.is_false(path.is_absolute("./foo.bar"))
assert.is_false(path.is_absolute(".\\baz"))
assert.is_false(path.is_absolute("foo.bar"))
assert.is_false(path.is_absolute(".\\foo.bar\\baz"))
assert.is_false(path.is_absolute("./baz\\foo.bar"))
assert.is_false(path.is_absolute("..\\baz/foo.bar"))
end)
end)
end)

View File

@@ -0,0 +1,39 @@
local w = require('tables').wrap
local parser = clink.arg.new_parser
local function read_lines (filename)
local lines = w({})
local f = io.open(filename)
if not f then return lines end
for line in f:lines() do table.insert(lines, line) end
f:close()
return lines
end
-- read all Host entries in the user's ssh config file
local function list_ssh_hosts()
return read_lines(clink.get_env("userprofile") .. "/.ssh/config")
:map(function (line)
return line:match('^Host%s+(.*)$')
end)
:filter()
end
local function list_known_hosts()
return read_lines(clink.get_env("userprofile") .. "/.ssh/known_hosts")
:map(function (line)
return line:match('^([%w-.]*).*')
end)
:filter()
end
local hosts = function (token) -- luacheck: no unused args
return list_ssh_hosts()
:concat(list_known_hosts())
end
local ssh_hosts_parser = parser({hosts})
clink.arg.register_parser("ssh", ssh_hosts_parser)

View File

@@ -0,0 +1,3 @@
@echo off
chcp 65001 1>nul
luacheck . && busted

View File

@@ -0,0 +1,141 @@
local matchers = require('matchers')
local path = require('path')
local parser = clink.arg.new_parser
local boxes = matchers.create_dirs_matcher(clink.get_env("userprofile") .. "/.vagrant.d/boxes/*")
local function is_empty(s)
return s == nil or s == ''
end
local function find_vagrantfile(start_dir)
local vagrantfile_name = clink.get_env("VAGRANT_VAGRANTFILE")
if is_empty(vagrantfile_name) then vagrantfile_name = "Vagrantfile" end
local function has_vagrantfile(dir)
return #clink.find_files(dir .. "./" .. vagrantfile_name .. "*") > 0
end
if not start_dir or start_dir == '.' then start_dir = clink.get_cwd() end
if has_vagrantfile(start_dir) then return io.open(start_dir.."\\"..vagrantfile_name) end
local parent_path = path.pathname(start_dir)
if parent_path ~= start_dir then return find_vagrantfile(parent_path) end
end
local function get_vagrantfile()
local vagrant_cwd = clink.get_env("VAGRANT_CWD")
if not is_empty(vagrant_cwd) then
return find_vagrantfile(vagrant_cwd)
else
return find_vagrantfile()
end
end
local function delete_ruby_comment(line)
if line == nil then return nil end
local index = string.find(line, '#')
if (not (index == nil) and index > 0) then
return string.sub(line, 0, index-1)
end
return line
end
local get_provisions = function ()
local vagrant_file = get_vagrantfile()
if vagrant_file == nil then return {} end
local provisions = {}
for line in vagrant_file:lines() do
line = delete_ruby_comment(line)
if not is_empty(line) then
local provision_name = line:match('.vm.provision[ \r\t]+[\"|\']([A-z]+[A-z0-9|-]*)[\"|\']')
if not is_empty(provision_name) then
table.insert(provisions, provision_name)
end
end
end
vagrant_file:close()
return provisions
end
local vagrant_parser = parser({
"box" .. parser({
"add" .. parser(
"--checksum",
"--checksum-type" .. parser({"md5", "sha1", "sha256"}),
"-c", "--clean",
"-f", "--force",
"--insecure",
"--cacert",
"--cert",
"--provider"
),
"list" .. parser("-i", "--box-info"),
"outdated"..parser("--global", "-h", "--help"),
"remove" .. parser({boxes}),
"repackage" .. parser({boxes}),
"update"
}),
"connect",
"destroy" .. parser("-f", "--force"),
"global-status",
"halt" .. parser("-f", "--force"),
"init" .. parser({boxes}, {}, "--output"),
"package" .. parser("--base", "--output", "--include", "--vagrantfile"),
"plugin" .. parser({
"install" .. parser(
"--entry-point",
"--plugin-prerelease",
"--plugin-source",
"--plugin-version"
),
"license",
"list",
"uninstall",
"update" .. parser(
"--entry-point",
"--plugin-prerelease",
"--plugin-source",
"--plugin-version"
)
}),
"provision" .. parser("--provision-with" .. parser({get_provisions}), "--no-parallel", "--parallel"),
"reload" .. parser("--provision-with" .. parser({get_provisions}), "--no-parallel", "--parallel"),
"resume",
"ssh" .. parser("-c", "--command", "-p", "--plain") ,
"ssh-config",
"snapshot" .. parser({
"push",
"pop" .. parser(
"--provision",
"--no-provision",
"--no-delete"),
"save",
"restore" .. parser(
"--provision",
"--no-provision"),
"list",
"delete"}),
"status",
"suspend",
"up" .. parser(
"--provision",
"--no-provision",
"--provision-with" .. parser({get_provisions}),
"--destroy-on-error",
"--no-destroy-on-error",
"--parallel",
"--no-parallel",
"--provider"
)
}, "-h", "--help", "-v", "--version")
local help_parser = parser({
"help" .. parser(vagrant_parser:flatten_argument(1))
})
clink.arg.register_parser("vagrant", vagrant_parser)
clink.arg.register_parser("vagrant", help_parser)

View File

@@ -0,0 +1,173 @@
-- preamble: common routines
local JSON = require("JSON")
-- silence JSON parsing errors
function JSON:assert () end -- luacheck: no unused args
local w = require('tables').wrap
local matchers = require('matchers')
---
-- Queries config options value using 'yarn config get' call
-- @param {string} config_entry Config option name
-- @return {string} Config value for specific option or
-- empty string in case of any error
---
local function get_yarn_config_value (config_entry)
assert(config_entry and type(config_entry) == "string" and #config_entry > 0,
"get_yarn_config_value: config_entry param should be non-empty string")
local proc = io.popen("yarn config get "..config_entry.." 2>nul")
if not proc then return "" end
local value = proc:read()
proc:close()
return value or nil
end
local modules = matchers.create_dirs_matcher('node_modules/*')
local globals_location = nil
local global_modules_matcher = nil
local function global_modules(token)
-- If we already have matcher then just return it
if global_modules_matcher then return global_modules_matcher(token) end
-- If token starts with . or .. or has path delimiter then return empty
-- result and do not create a matcher so only fs paths will be completed
if (token:match('^%.(%.)?') or token:match('[%\\%/]+')) then return {} end
-- otherwise try to get cache location and return empty table if failed
globals_location = globals_location or get_yarn_config_value("prefix")
if not globals_location then return {} end
-- Create a new matcher, save it in module's variable for further usage and return it
global_modules_matcher = matchers.create_dirs_matcher(globals_location..'/node_modules/*')
return global_modules_matcher(token)
end
-- A function that matches all files in bin folder. See #74 for rationale
local bins = matchers.create_files_matcher('node_modules/.bin/*.')
-- Reads package.json in current directory and extracts all "script" commands defined
local function scripts(token) -- luacheck: no unused args
-- Read package.json first
local package_json = io.open('package.json')
-- If there is no such file, then close handle and return
if package_json == nil then return w() end
-- Read the whole file contents
local package_contents = package_json:read("*a")
package_json:close()
local package_scripts = JSON:decode(package_contents).scripts
return w(package_scripts):keys()
end
local parser = clink.arg.new_parser
-- end preamble
local add_parser = parser(
"--dev", "-D",
"--exact", "-E",
"--optional", "-O",
"--peer", "-P",
"--tilde", "-T"
)
local yarn_parser = parser({
"add"..add_parser,
"bin",
"cache"..parser({
"clean",
"dir",
"ls"
}),
"check"..parser("--integrity"),
"clean",
"config"..parser({
"delete",
"get",
"list",
"set"
}),
"generate-lock-entry",
"global"..parser({
"add"..add_parser,
"bin",
"ls",
"remove"..parser({modules}),
"upgrade"..parser({modules})
}),
"help",
"info",
"init"..parser("--yes", "-y"),
"install",
"licenses"..parser({"generate-disclaimer", "ls"}),
"link"..parser({matchers.files, global_modules}),
"login",
"logout",
"ls"..parser("--depth"),
"outdated"..parser({modules}),
"owner"..parser({"add", "ls", "rm"}),
"pack"..parser("--filename", "-f"),
"publish"..parser(
"--access"..parser({"public", "restricted"}),
"--message",
"--new-version",
"--no-git-tag-version",
"--tag"
),
"remove"..parser({modules}),
"run"..parser({bins, scripts}),
"self-update",
"tag"..parser({"add", "ls", "rm"}),
"team"..parser({"add", "create", "destroy", "ls", "rm"}),
"test",
"unlink"..parser({modules}),
"upgrade"..parser({modules}, "--ignore-engines"),
"upgrade-interactive",
"version"..parser(
"--message",
"--new-version",
"--no-git-tag-version"
),
"versions",
"why"..parser({modules})
},
"-h",
"-v",
"--cache-folder",
"--flat",
"--force",
"--global-folder",
"--har",
"--help",
"--https-proxy",
"--ignore-engines",
"--ignore-optional",
"--ignore-platform",
"--ignore-scripts",
"--json",
"--modules-folder",
"--mutex",
"--no-bin-links",
"--no-lockfile",
"--offline",
"--no-emoji",
"--no-progress",
"--prefer-offline",
"--proxy",
"--pure-lockfile",
"--prod",
"--production",
"--strict-semver",
"--version"
)
clink.arg.register_parser("yarn", yarn_parser)