From 1b5017a88667c5af7a4afd4311d4861eb540b1bb Mon Sep 17 00:00:00 2001 From: OpportunityLiu Date: Wed, 5 Jun 2019 14:17:11 +0800 Subject: tab completion --- scripts/get.ps1 | 249 ++++++++++++++++++++++++-------------- scripts/get.sh | 36 ++++++ scripts/register-completions.bash | 16 +++ scripts/register-completions.ps1 | 8 ++ scripts/register-completions.zsh | 10 ++ 5 files changed, 225 insertions(+), 94 deletions(-) create mode 100644 scripts/register-completions.bash create mode 100644 scripts/register-completions.ps1 create mode 100644 scripts/register-completions.zsh (limited to 'scripts') diff --git a/scripts/get.ps1 b/scripts/get.ps1 index fc35a9023..4b186c23f 100644 --- a/scripts/get.ps1 +++ b/scripts/get.ps1 @@ -9,105 +9,166 @@ param ( & { -Function myExit($code){ - if($code -is [int] -and $code -ne 0){ - throw $Error[0] - }else{ - break + function myExit($code) { + if ($code -is [int] -and $code -ne 0) { + throw $Error[0] + } else { + break + } } -} -Function writeErrorTip($msg){ - Write-Host $msg -BackgroundColor Red -ForegroundColor White -} + function writeErrorTip($msg) { + Write-Host $msg -BackgroundColor Red -ForegroundColor White + } -Function writeLogoLine($msg){ - Write-Host $msg -BackgroundColor White -ForegroundColor DarkBlue -} + function writeLogoLine($msg) { + Write-Host $msg -BackgroundColor White -ForegroundColor DarkBlue + } -writeLogoLine ' _ ' -writeLogoLine ' __ ___ __ __ __ _| | ______ ' -writeLogoLine ' \ \/ / | \/ |/ _ | |/ / __ \ ' -writeLogoLine ' > < | \__/ | /_| | < ___/ ' -writeLogoLine ' /_/\_\_|_| |_|\__ \|_|\_\____| getter ' -writeLogoLine ' ' -writeLogoLine ' ' + function registerTabCompletion { -if($PSVersionTable.PSVersion.Major -lt 5){ - writeErrorTip 'Sorry but PowerShell v5+ is required' - throw 'PowerShell''s version too low' -} -$temppath=($env:TMP,$env:TEMP,'.' -ne $null)[0] -$outfile=$temppath+"\$pid-xmake-installer.exe" -try{ - Write-Output "$pid"|Out-File -FilePath "$outfile" - Remove-Item "$outfile" -}catch{ - writeErrorTip 'Cannot write to temp path' - writeErrorTip 'Please set environment var "TMP" to another path' - myExit 1 -} -Write-Host "Start downloading https://github.com/xmake-io/xmake/releases/download/$version/xmake-$branch.exe .." -try{ - [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" - Invoke-Webrequest "https://github.com/xmake-io/xmake/releases/download/$version/xmake-$branch.exe" -OutFile "$outfile" -}catch{ - writeErrorTip 'Download failed!' - writeErrorTip 'Check your network or... the news of S3 break' - myExit 1 -} -Write-Host 'Start installation... Hope your antivirus doesn''t trouble' -$installdir=$HOME+'\xmake' -Write-Host "Install to $installdir" -try{ - Start-Process -FilePath "$outfile" -ArgumentList "/S /D=$installdir" -Wait -}catch{ + function writeDataToFile($file) { + $encoding = [text.encoding]::UTF8 + if (Test-Path $file -PathType Leaf) { + #Create a stream reader to get the file's encoding and contents. + $sr = New-Object System.IO.StreamReader($file, $true) + [char[]] $buffer = new-object char[] 3 + $sr.Read($buffer, 0, 3) | Out-Null + $encoding = $sr.CurrentEncoding + $sr.Close() | Out-Null + + if ($(Get-Content $file) -imatch "Register-ArgumentCompleter -Native -CommandName xmake -ScriptBlock") { + Write-Host "Seems the tab completion of xmake has installed here..." + return + } + } + + try { + [IO.File]::AppendAllText($file, "`n", $encoding) + } catch { + writeErrorTip "Failed to append to profile!" + writeErrorTip "Please try again as administrator" + return + } + try { + $content = (Invoke-Webrequest 'https://raw.githubusercontent.com/xmake-io/xmake/master/scripts/register-completions.ps1' -UseBasicParsing).Content + } catch { + writeErrorTip 'Download failed!' + writeErrorTip 'Check your network or... the news of S3 break' + return + } + [IO.File]::AppendAllText($file, $content, $encoding) + [IO.File]::AppendAllText($file, "`n", $encoding) + } + $message = 'Tab completion service' + $question = 'Would you like to install tab completion service of xmake to your profile?' + + $choices = @( + (New-Object Management.Automation.Host.ChoiceDescription -ArgumentList @( + 'For &all users', + "Install for all users, writes to $($PROFILE.AllUsersAllHosts), admin privilege is needed.")), + (New-Object Management.Automation.Host.ChoiceDescription -ArgumentList @( + 'Just for &me', + "Install for current user, writes to $($PROFILE.CurrentUserAllHosts).")), + (New-Object Management.Automation.Host.ChoiceDescription -ArgumentList @( + 'Just for this &host', + "Install for current user current host, writes to $($PROFILE.CurrentUserCurrentHost).")), + (New-Object Management.Automation.Host.ChoiceDescription -ArgumentList @( + '&No', + "Do not install xmake's tab completion service.")) + ) + switch ($Host.UI.PromptForChoice($message, $question, $choices, 1)) { + 0 { writeDataToFile($PROFILE.AllUsersAllHosts) } + 1 { writeDataToFile($PROFILE.CurrentUserAllHosts) } + 2 { writeDataToFile($PROFILE.CurrentUserCurrentHost) } + } + } + + writeLogoLine ' _ ' + writeLogoLine ' __ ___ __ __ __ _| | ______ ' + writeLogoLine ' \ \/ / | \/ |/ _ | |/ / __ \ ' + writeLogoLine ' > < | \__/ | /_| | < ___/ ' + writeLogoLine ' /_/\_\_|_| |_|\__ \|_|\_\____| getter ' + writeLogoLine ' ' + writeLogoLine ' ' + + if ($PSVersionTable.PSVersion.Major -lt 5) { + writeErrorTip 'Sorry but PowerShell v5+ is required' + throw 'PowerShell''s version too low' + } + $temppath = ($env:TMP, $env:TEMP, '.' -ne $null)[0] + $outfile = $temppath + "\$pid-xmake-installer.exe" + try { + Write-Output "$pid" | Out-File -FilePath "$outfile" + Remove-Item "$outfile" + } catch { + writeErrorTip 'Cannot write to temp path' + writeErrorTip 'Please set environment var "TMP" to another path' + myExit 1 + } + Write-Host "Start downloading https://github.com/xmake-io/xmake/releases/download/$version/xmake-$branch.exe .." + try { + [Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" + Invoke-Webrequest "https://github.com/xmake-io/xmake/releases/download/$version/xmake-$branch.exe" -OutFile "$outfile" + } catch { + writeErrorTip 'Download failed!' + writeErrorTip 'Check your network or... the news of S3 break' + myExit 1 + } + Write-Host 'Start installation... Hope your antivirus doesn''t trouble' + $installdir = $HOME + '\xmake' + Write-Host "Install to $installdir" + try { + Start-Process -FilePath "$outfile" -ArgumentList "/S /D=$installdir" -Wait + } catch { + Remove-Item "$outfile" + writeErrorTip 'Install failed!' + writeErrorTip 'Close your antivirus then try again' + myExit 1 + } Remove-Item "$outfile" - writeErrorTip 'Install failed!' - writeErrorTip 'Close your antivirus then try again' - myExit 1 -} -Remove-Item "$outfile" -Write-Host 'Adding to PATH... almost done' -$env:Path+=";$installdir" -[Environment]::SetEnvironmentVariable("Path",[Environment]::GetEnvironmentVariable("Path",[System.EnvironmentVariableTarget]::User)+";$installdir",[System.EnvironmentVariableTarget]::User) # this step is optional because installer writes path to regedit -try{ - xmake --version -}catch{ - writeErrorTip 'Everything is showing installation has finished' - writeErrorTip 'But xmake could not run... Why?' - myExit 1 -} -Write-Host "Pulling xmake from branch $branch" -$outfile=$temppath+"\$pid-xmake-repo.zip" -try{ - Invoke-Webrequest "https://github.com/xmake-io/xmake/archive/$branch.zip" -OutFile "$outfile" -}catch{ - writeErrorTip 'Pull Failed!' - writeErrorTip 'xmake is now available but may not be newest' - myExit -} -Write-Host 'Expanding archive...' -New-Item -Path "$temppath" -Name "$pid-xmake-repo" -ItemType "directory" -Force -$oldpwd=$pwd -$repodir=$temppath+"\$pid-xmake-repo" -try{ - Expand-Archive "$outfile" "$repodir" -Force - Write-Host 'Self-building...' - Set-Location ($repodir+"\xmake-$branch\core") - xmake - Write-Host 'Copying new files...' - Copy-Item 'build\xmake.exe' "$installdir" -Force - Set-Location '..\xmake' - Copy-Item * "$installdir" -Recurse -Force - xmake --version -}catch{ - writeErrorTip 'Update Failed!' - writeErrorTip 'xmake is now available but may not be newest' -}finally{ - Set-Location "$oldpwd" -ErrorAction SilentlyContinue - Remove-Item "$outfile" -ErrorAction SilentlyContinue - Remove-Item "$repodir" -Recurse -Force -ErrorAction SilentlyContinue -} + Write-Host 'Adding to PATH... almost done' + $env:Path += ";$installdir" + [Environment]::SetEnvironmentVariable("Path", [Environment]::GetEnvironmentVariable("Path", [System.EnvironmentVariableTarget]::User) + ";$installdir", [System.EnvironmentVariableTarget]::User) # this step is optional because installer writes path to regedit + try { + xmake --version + } catch { + writeErrorTip 'Everything is showing installation has finished' + writeErrorTip 'But xmake could not run... Why?' + myExit 1 + } + Write-Host "Pulling xmake from branch $branch" + $outfile = $temppath + "\$pid-xmake-repo.zip" + try { + Invoke-Webrequest "https://github.com/xmake-io/xmake/archive/$branch.zip" -OutFile "$outfile" + } catch { + writeErrorTip 'Pull Failed!' + writeErrorTip 'xmake is now available but may not be newest' + myExit + } + Write-Host 'Expanding archive...' + New-Item -Path "$temppath" -Name "$pid-xmake-repo" -ItemType "directory" -Force + $oldpwd = $pwd + $repodir = $temppath + "\$pid-xmake-repo" + try { + Expand-Archive "$outfile" "$repodir" -Force + Write-Host 'Self-building...' + Set-Location ($repodir + "\xmake-$branch\core") + xmake + Write-Host 'Copying new files...' + Copy-Item 'build\xmake.exe' "$installdir" -Force + Set-Location '..\xmake' + Copy-Item * "$installdir" -Recurse -Force + xmake --version + } catch { + writeErrorTip 'Update Failed!' + writeErrorTip 'xmake is now available but may not be newest' + } finally { + Set-Location "$oldpwd" -ErrorAction SilentlyContinue + Remove-Item "$outfile" -ErrorAction SilentlyContinue + Remove-Item "$repodir" -Recurse -Force -ErrorAction SilentlyContinue + } + + registerTabCompletion } diff --git a/scripts/get.sh b/scripts/get.sh index 98a59ec2a..164ec9c48 100755 --- a/scripts/get.sh +++ b/scripts/get.sh @@ -147,6 +147,42 @@ install_profile() { if [ ! -d ~/.xmake ]; then mkdir ~/.xmake; fi echo "export PATH=$prefix/bin:\$PATH" > ~/.xmake/profile + echo ' +if [[ "$SHELL" = */zsh ]]; then + + # zsh parameter completion for xmake + + _xmake_zsh_complete() + { + local completions=("$(xmake lua private.utils.complete 0 "$words")") + + reply=( "${(ps:\n:)completions}" ) + } + + compctl -K _xmake_zsh_complete xmake + +elif [[ "$SHELL" = */bash ]]; then + +# bash parameter completion for xmake + + _xmake_bash_complete() + { + local word=${COMP_WORDS[COMP_CWORD]} + + local completions + completions="$(xmake lua private.utils.complete "${COMP_POINT}" "${COMP_LINE}" 2>/dev/null)" + if [ $? -ne 0 ]; then + completions="" + fi + + COMPREPLY=( $(compgen -W "$completions" -- "$word") ) + } + + complete -f -F _xmake_bash_complete xmake + +fi +' >> ~/.xmake/profile + if [[ "$SHELL" = */zsh ]]; then write_profile ~/.zshrc elif [[ "$SHELL" = */ksh ]]; then write_profile ~/.kshrc elif [[ "$SHELL" = */bash ]]; then write_profile ~/.bashrc diff --git a/scripts/register-completions.bash b/scripts/register-completions.bash new file mode 100644 index 000000000..11cadedf3 --- /dev/null +++ b/scripts/register-completions.bash @@ -0,0 +1,16 @@ +# bash parameter completion for xmake + +_xmake_bash_complete() +{ + local word=${COMP_WORDS[COMP_CWORD]} + + local completions + completions="$(xmake lua private.utils.complete "${COMP_POINT}" "${COMP_LINE}" 2>/dev/null)" + if [ $? -ne 0 ]; then + completions="" + fi + + COMPREPLY=( $(compgen -W "$completions" -- "$word") ) +} + +complete -f -F _xmake_bash_complete xmake diff --git a/scripts/register-completions.ps1 b/scripts/register-completions.ps1 new file mode 100644 index 000000000..58e11320a --- /dev/null +++ b/scripts/register-completions.ps1 @@ -0,0 +1,8 @@ +# PowerShell parameter completion shim for xmake + +Register-ArgumentCompleter -Native -CommandName xmake -ScriptBlock { + param($commandName, $wordToComplete, $cursorPosition) + xmake lua private.utils.complete "$cursorPosition" "$wordToComplete" | ForEach-Object { + [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) + } +} diff --git a/scripts/register-completions.zsh b/scripts/register-completions.zsh new file mode 100644 index 000000000..ff019569f --- /dev/null +++ b/scripts/register-completions.zsh @@ -0,0 +1,10 @@ +# zsh parameter completion for xmake + +_xmake_zsh_complete() +{ + local completions=("$(xmake lua private.utils.complete 0 "$words")") + + reply=( "${(ps:\n:)completions}" ) +} + +compctl -K _xmake_zsh_complete xmake -- cgit v1.3.1 From 2fc0ed7ad1d2af134d1b25334634f1050bb42376 Mon Sep 17 00:00:00 2001 From: OpportunityLiu Date: Wed, 5 Jun 2019 21:15:28 +0800 Subject: fix for powershell --- scripts/register-completions.ps1 | 7 ++++++- xmake/modules/private/utils/complete.lua | 10 +++++----- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/register-completions.ps1 b/scripts/register-completions.ps1 index 58e11320a..6295cf4fc 100644 --- a/scripts/register-completions.ps1 +++ b/scripts/register-completions.ps1 @@ -2,7 +2,12 @@ Register-ArgumentCompleter -Native -CommandName xmake -ScriptBlock { param($commandName, $wordToComplete, $cursorPosition) - xmake lua private.utils.complete "$cursorPosition" "$wordToComplete" | ForEach-Object { + $complete = "$wordToComplete" + if (-not $commandName) { + $complete = $complete + " " + } + xmake lua private.utils.complete "0" "$complete" | ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) } } + diff --git a/xmake/modules/private/utils/complete.lua b/xmake/modules/private/utils/complete.lua index 5c85482fb..df3e98e3f 100644 --- a/xmake/modules/private/utils/complete.lua +++ b/xmake/modules/private/utils/complete.lua @@ -95,9 +95,9 @@ end function main(position, ...) word = table.concat({...}, " ") or "" position = tonumber(position) or 0 - if position > #word then - word = word .. " " - end + local has_space = word:endswith(" ") or position > #word + word = word:trim() + if word:lower():startswith("xmake ") then word = word:sub(#"xmake " + 1) end @@ -107,7 +107,7 @@ function main(position, ...) local segs = word:split("%s") local task = table.remove(segs, 1) or "" - if #segs == 0 and not word:endswith(" ") then + if #segs == 0 and not has_space then if _complete_task(task) then return end end @@ -116,6 +116,6 @@ function main(position, ...) table.insert(segs, 1, task) task = "run" end - _complete_option(option.taskmenu(task).options, word:endswith(" ") and "" or segs[#segs]) + _complete_option(option.taskmenu(task).options, has_space and "" or segs[#segs]) return end \ No newline at end of file -- cgit v1.3.1