Skip to content

Commit

Permalink
Add shell completions
Browse files Browse the repository at this point in the history
  • Loading branch information
cestef committed Mar 12, 2024
1 parent 84513f8 commit a147dc2
Show file tree
Hide file tree
Showing 9 changed files with 649 additions and 7 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ tokio = { version = "1.34.0", features = [
"macros",
"rt-multi-thread",
] }
toml = "0.8.10"
toml = "0.8.11"
url = "2.4.1"
clap_complete = "4.5.1"
clap_complete_nushell = "4.5.1"

# Strip the debug symbols from the binary
[profile.release]
Expand Down
98 changes: 98 additions & 0 deletions completions/_rwalk
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#compdef rwalk

autoload -U is-at-least

_rwalk() {
typeset -A opt_args
typeset -a _arguments_options
local ret=1

if is-at-least 5.2; then
_arguments_options=(-s -S -C)
else
_arguments_options=(-s -C)
fi

local context curcontext="$curcontext" state line
_arguments "${_arguments_options[@]}" \
'-m+[Crawl mode]:MODE:(recursive recursion r classic c)' \
'--mode=[Crawl mode]:MODE:(recursive recursion r classic c)' \
'-t+[Number of threads to use]:THREADS: ' \
'--threads=[Number of threads to use]:THREADS: ' \
'-d+[Crawl recursively until given depth]:DEPTH: ' \
'--depth=[Crawl recursively until given depth]:DEPTH: ' \
'-o+[Output file]:FILE: ' \
'--output=[Output file]:FILE: ' \
'--timeout=[Request timeout in seconds]:TIMEOUT: ' \
'--to=[Request timeout in seconds]:TIMEOUT: ' \
'-u+[User agent]:USER_AGENT: ' \
'--user-agent=[User agent]:USER_AGENT: ' \
'-X+[HTTP method]:METHOD: ' \
'--method=[HTTP method]:METHOD: ' \
'-D+[Data to send with the request]:DATA: ' \
'--data=[Data to send with the request]:DATA: ' \
'*-H+[Headers to send]:key:value: ' \
'*--headers=[Headers to send]:key:value: ' \
'*-C+[Cookies to send]:key=value: ' \
'*--cookies=[Cookies to send]:key=value: ' \
'-R+[Follow redirects]:COUNT: ' \
'--follow-redirects=[Follow redirects]:COUNT: ' \
'-c+[Configuration file]:CONFIG: ' \
'--config=[Configuration file]:CONFIG: ' \
'--throttle=[Request throttling (requests per second) per thread]:THROTTLE: ' \
'-M+[Max time to run (will abort after given time) in seconds]:MAX_TIME: ' \
'--max-time=[Max time to run (will abort after given time) in seconds]:MAX_TIME: ' \
'*--show=[Show response additional body information]:SHOW:(length size hash md5 headers_length headers_hash body content text headers cookie cookies type)' \
'--save-file=[Custom save file]:FILE: ' \
'*-T+[Wordlist transformations\: "lower", "upper", "prefix", "suffix", "capitalize", "reverse", "remove", "replace"]:TRANSFORM: ' \
'*--transform=[Wordlist transformations\: "lower", "upper", "prefix", "suffix", "capitalize", "reverse", "remove", "replace"]:TRANSFORM: ' \
'*-w+[Wordlist filtering\: "contains", "starts", "ends", "regex", "length"]:KEY:FILTER: ' \
'*--wordlist-filter=[Wordlist filtering\: "contains", "starts", "ends", "regex", "length"]:KEY:FILTER: ' \
'*--wf=[Wordlist filtering\: "contains", "starts", "ends", "regex", "length"]:KEY:FILTER: ' \
'*-f+[Response filtering\: "time", "status", "contains", "starts", "end", "regex", "length", "hash", "header", "json", "depth"]:KEY:FILTER: ' \
'*--filter=[Response filtering\: "time", "status", "contains", "starts", "end", "regex", "length", "hash", "header", "json", "depth"]:KEY:FILTER: ' \
'--request-file=[Request file (.http, .rest)]:FILE: ' \
'--rf=[Request file (.http, .rest)]:FILE: ' \
'-P+[Proxy URL]:URL: ' \
'--proxy=[Proxy URL]:URL: ' \
'--proxy-auth=[Proxy username and password]:USER:PASS: ' \
'--force[Force scan even if the target is not responding]' \
'--hit-connection-errors[Consider connection errors as a hit]' \
'--hce[Consider connection errors as a hit]' \
'--no-color[Don'\''t use colors You can also set the NO_COLOR environment variable]' \
'-q[Quiet mode]' \
'--quiet[Quiet mode]' \
'-i[Interactive mode]' \
'--interactive[Interactive mode]' \
'--insecure[Insecure mode, disables SSL certificate validation]' \
'--unsecure[Insecure mode, disables SSL certificate validation]' \
'-r[Resume from a saved file]' \
'--resume[Resume from a saved file]' \
'--no-save[Don'\''t save the state in case you abort]' \
'--keep-save[Keep the save file after finishing when using --resume]' \
'--keep[Keep the save file after finishing when using --resume]' \
'--or[Treat filters as or instead of and]' \
'--force-recursion[Force the recursion over non-directories]' \
'--fr[Force the recursion over non-directories]' \
'--generate-markdown[Generate markdown help - for developers]' \
'--generate-completions[Generate shell completions - for developers]' \
'-h[Print help]' \
'--help[Print help]' \
'-V[Print version]' \
'--version[Print version]' \
'::url -- Target URL:' \
'*::wordlists -- Wordlist(s):' \
&& ret=0
}

(( $+functions[_rwalk_commands] )) ||
_rwalk_commands() {
local commands; commands=()
_describe -t commands 'rwalk commands' commands "$@"
}

if [ "$funcstack[1]" = "_rwalk" ]; then
_rwalk "$@"
else
compdef _rwalk rwalk
fi
95 changes: 95 additions & 0 deletions completions/_rwalk.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@

using namespace System.Management.Automation
using namespace System.Management.Automation.Language

Register-ArgumentCompleter -Native -CommandName 'rwalk' -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)

$commandElements = $commandAst.CommandElements
$command = @(
'rwalk'
for ($i = 1; $i -lt $commandElements.Count; $i++) {
$element = $commandElements[$i]
if ($element -isnot [StringConstantExpressionAst] -or
$element.StringConstantType -ne [StringConstantType]::BareWord -or
$element.Value.StartsWith('-') -or
$element.Value -eq $wordToComplete) {
break
}
$element.Value
}) -join ';'

$completions = @(switch ($command) {
'rwalk' {
[CompletionResult]::new('-m', 'm', [CompletionResultType]::ParameterName, 'Crawl mode')
[CompletionResult]::new('--mode', 'mode', [CompletionResultType]::ParameterName, 'Crawl mode')
[CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Number of threads to use')
[CompletionResult]::new('--threads', 'threads', [CompletionResultType]::ParameterName, 'Number of threads to use')
[CompletionResult]::new('-d', 'd', [CompletionResultType]::ParameterName, 'Crawl recursively until given depth')
[CompletionResult]::new('--depth', 'depth', [CompletionResultType]::ParameterName, 'Crawl recursively until given depth')
[CompletionResult]::new('-o', 'o', [CompletionResultType]::ParameterName, 'Output file')
[CompletionResult]::new('--output', 'output', [CompletionResultType]::ParameterName, 'Output file')
[CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout in seconds')
[CompletionResult]::new('--to', 'to', [CompletionResultType]::ParameterName, 'Request timeout in seconds')
[CompletionResult]::new('-u', 'u', [CompletionResultType]::ParameterName, 'User agent')
[CompletionResult]::new('--user-agent', 'user-agent', [CompletionResultType]::ParameterName, 'User agent')
[CompletionResult]::new('-X', 'X ', [CompletionResultType]::ParameterName, 'HTTP method')
[CompletionResult]::new('--method', 'method', [CompletionResultType]::ParameterName, 'HTTP method')
[CompletionResult]::new('-D', 'D ', [CompletionResultType]::ParameterName, 'Data to send with the request')
[CompletionResult]::new('--data', 'data', [CompletionResultType]::ParameterName, 'Data to send with the request')
[CompletionResult]::new('-H', 'H ', [CompletionResultType]::ParameterName, 'Headers to send')
[CompletionResult]::new('--headers', 'headers', [CompletionResultType]::ParameterName, 'Headers to send')
[CompletionResult]::new('-C', 'C ', [CompletionResultType]::ParameterName, 'Cookies to send')
[CompletionResult]::new('--cookies', 'cookies', [CompletionResultType]::ParameterName, 'Cookies to send')
[CompletionResult]::new('-R', 'R ', [CompletionResultType]::ParameterName, 'Follow redirects')
[CompletionResult]::new('--follow-redirects', 'follow-redirects', [CompletionResultType]::ParameterName, 'Follow redirects')
[CompletionResult]::new('-c', 'c', [CompletionResultType]::ParameterName, 'Configuration file')
[CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'Configuration file')
[CompletionResult]::new('--throttle', 'throttle', [CompletionResultType]::ParameterName, 'Request throttling (requests per second) per thread')
[CompletionResult]::new('-M', 'M ', [CompletionResultType]::ParameterName, 'Max time to run (will abort after given time) in seconds')
[CompletionResult]::new('--max-time', 'max-time', [CompletionResultType]::ParameterName, 'Max time to run (will abort after given time) in seconds')
[CompletionResult]::new('--show', 'show', [CompletionResultType]::ParameterName, 'Show response additional body information')
[CompletionResult]::new('--save-file', 'save-file', [CompletionResultType]::ParameterName, 'Custom save file')
[CompletionResult]::new('-T', 'T ', [CompletionResultType]::ParameterName, 'Wordlist transformations: "lower", "upper", "prefix", "suffix", "capitalize", "reverse", "remove", "replace"')
[CompletionResult]::new('--transform', 'transform', [CompletionResultType]::ParameterName, 'Wordlist transformations: "lower", "upper", "prefix", "suffix", "capitalize", "reverse", "remove", "replace"')
[CompletionResult]::new('-w', 'w', [CompletionResultType]::ParameterName, 'Wordlist filtering: "contains", "starts", "ends", "regex", "length"')
[CompletionResult]::new('--wordlist-filter', 'wordlist-filter', [CompletionResultType]::ParameterName, 'Wordlist filtering: "contains", "starts", "ends", "regex", "length"')
[CompletionResult]::new('--wf', 'wf', [CompletionResultType]::ParameterName, 'Wordlist filtering: "contains", "starts", "ends", "regex", "length"')
[CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Response filtering: "time", "status", "contains", "starts", "end", "regex", "length", "hash", "header", "json", "depth"')
[CompletionResult]::new('--filter', 'filter', [CompletionResultType]::ParameterName, 'Response filtering: "time", "status", "contains", "starts", "end", "regex", "length", "hash", "header", "json", "depth"')
[CompletionResult]::new('--request-file', 'request-file', [CompletionResultType]::ParameterName, 'Request file (.http, .rest)')
[CompletionResult]::new('--rf', 'rf', [CompletionResultType]::ParameterName, 'Request file (.http, .rest)')
[CompletionResult]::new('-P', 'P ', [CompletionResultType]::ParameterName, 'Proxy URL')
[CompletionResult]::new('--proxy', 'proxy', [CompletionResultType]::ParameterName, 'Proxy URL')
[CompletionResult]::new('--proxy-auth', 'proxy-auth', [CompletionResultType]::ParameterName, 'Proxy username and password')
[CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force scan even if the target is not responding')
[CompletionResult]::new('--hit-connection-errors', 'hit-connection-errors', [CompletionResultType]::ParameterName, 'Consider connection errors as a hit')
[CompletionResult]::new('--hce', 'hce', [CompletionResultType]::ParameterName, 'Consider connection errors as a hit')
[CompletionResult]::new('--no-color', 'no-color', [CompletionResultType]::ParameterName, 'Don''t use colors You can also set the NO_COLOR environment variable')
[CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Quiet mode')
[CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Quiet mode')
[CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Interactive mode')
[CompletionResult]::new('--interactive', 'interactive', [CompletionResultType]::ParameterName, 'Interactive mode')
[CompletionResult]::new('--insecure', 'insecure', [CompletionResultType]::ParameterName, 'Insecure mode, disables SSL certificate validation')
[CompletionResult]::new('--unsecure', 'unsecure', [CompletionResultType]::ParameterName, 'Insecure mode, disables SSL certificate validation')
[CompletionResult]::new('-r', 'r', [CompletionResultType]::ParameterName, 'Resume from a saved file')
[CompletionResult]::new('--resume', 'resume', [CompletionResultType]::ParameterName, 'Resume from a saved file')
[CompletionResult]::new('--no-save', 'no-save', [CompletionResultType]::ParameterName, 'Don''t save the state in case you abort')
[CompletionResult]::new('--keep-save', 'keep-save', [CompletionResultType]::ParameterName, 'Keep the save file after finishing when using --resume')
[CompletionResult]::new('--keep', 'keep', [CompletionResultType]::ParameterName, 'Keep the save file after finishing when using --resume')
[CompletionResult]::new('--or', 'or', [CompletionResultType]::ParameterName, 'Treat filters as or instead of and')
[CompletionResult]::new('--force-recursion', 'force-recursion', [CompletionResultType]::ParameterName, 'Force the recursion over non-directories')
[CompletionResult]::new('--fr', 'fr', [CompletionResultType]::ParameterName, 'Force the recursion over non-directories')
[CompletionResult]::new('--generate-markdown', 'generate-markdown', [CompletionResultType]::ParameterName, 'Generate markdown help - for developers')
[CompletionResult]::new('--generate-completions', 'generate-completions', [CompletionResultType]::ParameterName, 'Generate shell completions - for developers')
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('-V', 'V ', [CompletionResultType]::ParameterName, 'Print version')
[CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version')
break
}
})

$completions.Where{ $_.CompletionText -like "$wordToComplete*" } |
Sort-Object -Property ListItemText
}
Loading

0 comments on commit a147dc2

Please sign in to comment.