Iji PowerShell na WSL jikọọ iwu Linux n'ime Windows

Ajụjụ a na-ahụkarị sitere na ndị nrụpụta Windows: “Gịnị kpatara enweghị <ВСТАВЬТЕ ТУТ ЛЮБИМУЮ КОМАНДУ LINUX>?. Ma ọ bụ swipe dị ike less ma ọ bụ ngwaọrụ ndị ama ama grep ma ọ bụ sed, Ndị mmepe Windows chọrọ ịnweta iwu ndị a n'ụzọ dị mfe na ọrụ ha kwa ụbọchị.

Sistemụ Windows maka Linux (WSL) emeela nnukwu nzọụkwụ na nke a. Ọ na-enye gị ohere ịkpọ iwu Linux site na Windows site na proxying ha wsl.exe (wdg. wsl ls). Ọ bụ ezie na nke a bụ mmụba dị ịrịba ama, nhọrọ a na-enwe ọtụtụ adịghị ike.

  • Mgbakwụnye ebe niile wsl na-agwụ ike na-ekwekọghị n'okike.
  • Ụzọ Windows na arụmụka anaghị arụ ọrụ mgbe niile n'ihi na a na-atụgharị azụ azụ dị ka mkpụrụedemede mgbapụ kama ịbụ ndị na-ekewa akwụkwọ ndekọ aha.
  • Atụgharịghị ụzọ Windows na arụmụka gaa na ebe ugwu kwekọrọ na WSL.
  • A naghị asọpụrụ ntọala akpaghị aka na profaịlụ WSL nwere utu aha na mgbanwe gburugburu.
  • Anaghị akwado imecha ụzọ Linux.
  • Anaghị akwado mmecha iwu.
  • Anaghị akwado mmecha arụmụka.

N'ihi ya, a na-emeso iwu Linux dị ka ụmụ amaala nke abụọ n'okpuru Windows-ma na-esikwa ike iji karịa iwu obodo. Iji mee ka ikike ha nhata, ọ dị mkpa iji dozie nsogbu ndị edepụtara.

Ihe mkpuchi ọrụ PowerShell

Site na ihe mkpuchi ọrụ PowerShell, anyị nwere ike ịgbakwunye mmecha iwu wee kpochapụ mkpa prefixes wsl, ịsụgharị ụzọ Windows ka ọ bụrụ ụzọ WSL. Ihe ndị bụ isi chọrọ maka shells:

  • Maka iwu Linux ọ bụla a ga-enwerịrị otu ihe mkpuchi ọrụ nwere otu aha.
  • Shei ahụ ga-amata ụzọ Windows gafere dị ka arụmụka wee tụgharịa ha na ụzọ WSL.
  • Shei kwesịrị ịkpọ wsl na iwu Linux kwesịrị ekwesị na ntinye pipeline ọ bụla ma na-agafe arụmụka ahịrị iwu ọ bụla gafere na ọrụ ahụ.

Ebe ọ bụ na enwere ike itinye ụkpụrụ a n'iwu ọ bụla, anyị nwere ike ịkọwa nkọwa nke ihe mkpuchi ndị a ma mepụta ha na-enweghị atụ site na ndepụta iwu ibubata.

# The commands to import.
$commands = "awk", "emacs", "grep", "head", "less", "ls", "man", "sed", "seq", "ssh", "tail", "vim"
 
# Register a function for each command.
$commands | ForEach-Object { Invoke-Expression @"
Remove-Alias $_ -Force -ErrorAction Ignore
function global:$_() {
    for (`$i = 0; `$i -lt `$args.Count; `$i++) {
        # If a path is absolute with a qualifier (e.g. C:), run it through wslpath to map it to the appropriate mount point.
        if (Split-Path `$args[`$i] -IsAbsolute -ErrorAction Ignore) {
            `$args[`$i] = Format-WslArgument (wsl.exe wslpath (`$args[`$i] -replace "", "/"))
        # If a path is relative, the current working directory will be translated to an appropriate mount point, so just format it.
        } elseif (Test-Path `$args[`$i] -ErrorAction Ignore) {
            `$args[`$i] = Format-WslArgument (`$args[`$i] -replace "", "/")
        }
    }
 
    if (`$input.MoveNext()) {
        `$input.Reset()
        `$input | wsl.exe $_ (`$args -split ' ')
    } else {
        wsl.exe $_ (`$args -split ' ')
    }
}
"@
}

Ndepụta nke $command na-akọwa iwu mbubata. Mgbe ahụ, anyị na-emepụta ihe mkpuchi ọrụ maka onye ọ bụla n'ime ha site na iji iwu ahụ Invoke-Expression (site na ibu ụzọ wepụ aha aha ọ bụla ga-emegide ọrụ ahụ).

Ọrụ ahụ na-atụgharị karịa arụmụka ahịrị iwu, na-ekpebi ụzọ Windows site na iji iwu Split-Path и Test-Pathwee tụgharịa ụzọ ndị a na ụzọ WSL. Anyị na-agba ọsọ ụzọ site na ọrụ enyemaka Format-WslArgument, nke anyị ga-akọwa ma emechaa. Ọ na-agbanarị mkpụrụedemede pụrụ iche dị ka oghere na akara aka nke a ga-atụgharịrịrị na-ezighi ezi.

N'ikpeazụ, anyị na-ebuga wsl ntinye pipeline na arụmụka ahịrị iwu ọ bụla.

Site na ihe mkpuchi ndị a ị nwere ike ịkpọ iwu Linux kachasị amasị gị n'ụzọ eke karịa na-agbakwunyeghị prefix wsl na-enweghị nchegbu banyere otú ụzọ ndị a na-atụgharị:

  • man bash
  • less -i $profile.CurrentUserAllHosts
  • ls -Al C:Windows | less
  • grep -Ein error *.log
  • tail -f *.log

E gosipụtara usoro iwu isi ebe a, mana ị nwere ike ịmepụta shei maka iwu Linux ọ bụla site na ịgbakwunye ya na listi ahụ. Ọ bụrụ na ị gbakwunye koodu a na gị profaịlụ PowerShell, iwu ndị a ga-adịrị gị na nnọkọ PowerShell ọ bụla, dịka iwu obodo!

Ntọala mbụ

Na Linux, a na-akọwakarị utu aha na/ma ọ bụ mgbanwe gburugburu ebe obibi na profaịlụ nbanye, ịtọ ntọala ndabara maka iwu ndị a na-ejikarị (dịka ọmụmaatụ, alias ls=ls -AFh ma ọ bụ export LESS=-i). Otu n'ime ọghọm dị na proxying site na shei na-adịghị emekọrịta ihe wsl.exe - na anaghị ebu profaịlụ, yabụ na nhọrọ ndị a adịghị na ndabara (ya bụ. ls na WSL na wsl ls ga-akpa àgwà dị iche iche na utu aha akọwapụtara n'elu).

PowerShell na-enye $PSDefaultParameterValues, usoro ọkọlọtọ maka ịkọwapụta paramita ndabara, mana naanị maka cmdlets na ọrụ dị elu. N'ezie, anyị nwere ike ịrụ ọrụ dị elu site na shells anyị, mana nke a na-ewebata nsogbu ndị na-adịghị mkpa (dịka ọmụmaatụ, PowerShell na-ejikọta aha akụkụ akụkụ (dịka ọmụmaatụ, -a kwekọrọ na -ArgumentList), nke ga-emegide iwu Linux nke na-ewere aha akụkụ dị ka arụmụka), na syntax maka ịkọwa ụkpụrụ ndabara agaghị abụ nke kachasị mma (arụmụka ndabara chọrọ aha paramita dị na igodo, ọ bụghị naanị aha iwu) .

Otú ọ dị, na a nta mgbanwe anyị shells, anyị nwere ike mejuputa a nlereanya yiri $PSDefaultParameterValues, ma mee ka nhọrọ ndabara maka iwu Linux!

function global:$_() {
    …
 
    `$defaultArgs = ((`$WslDefaultParameterValues.$_ -split ' '), "")[`$WslDefaultParameterValues.Disabled -eq `$true]
    if (`$input.MoveNext()) {
        `$input.Reset()
        `$input | wsl.exe $_ `$defaultArgs (`$args -split ' ')
    } else {
        wsl.exe $_ `$defaultArgs (`$args -split ' ')
    }
}

Na-agafe $WslDefaultParameterValues na ahịrị iwu, anyị na-eziga parameters site na wsl.exe. Ihe ndị a na-egosi otu esi etinye ntuziaka na profaịlụ PowerShell gị iji hazie ntọala ndabara. Ugbu a, anyị nwere ike ime ya!

$WslDefaultParameterValues["grep"] = "-E"
$WslDefaultParameterValues["less"] = "-i"
$WslDefaultParameterValues["ls"] = "-AFh --group-directories-first"

Ebe ọ bụ na a na-emepụta paramita ahụ $PSDefaultParameterValues, Ị nwere ike ọ dị mfe iji gbanyụọ ha nwa oge site na ịtinye igodo "Disabled" n'ime ihe pụtara $true. Uru ọzọ nke tebụl hash dị iche bụ ike gbanyụọ $WslDefaultParameterValues iche si $PSDefaultParameterValues.

Mmecha arụmụka

PowerShell na-enye gị ohere ịdebanye aha trailers arụmụka site na iji iwu ahụ Register-ArgumentCompleter. Bash nwere ike ngwa ọrụ mmecha akpaaka nke mmemme. WSL na-enye gị ohere ịkpọ bash site na PowerShell. Ọ bụrụ na anyị nwere ike ịdebanye aha mmecha arụmụka maka ihe mkpuchi ọrụ PowerShell anyị wee kpọọ bash iji mepụta mmecha, anyị na-enweta mmecha arụmụka zuru oke na otu nkenke dị ka bash n'onwe ya!

# Register an ArgumentCompleter that shims bash's programmable completion.
Register-ArgumentCompleter -CommandName $commands -ScriptBlock {
    param($wordToComplete, $commandAst, $cursorPosition)
 
    # Map the command to the appropriate bash completion function.
    $F = switch ($commandAst.CommandElements[0].Value) {
        {$_ -in "awk", "grep", "head", "less", "ls", "sed", "seq", "tail"} {
            "_longopt"
            break
        }
 
        "man" {
            "_man"
            break
        }
 
        "ssh" {
            "_ssh"
            break
        }
 
        Default {
            "_minimal"
            break
        }
    }
 
    # Populate bash programmable completion variables.
    $COMP_LINE = "`"$commandAst`""
    $COMP_WORDS = "('$($commandAst.CommandElements.Extent.Text -join "' '")')" -replace "''", "'"
    for ($i = 1; $i -lt $commandAst.CommandElements.Count; $i++) {
        $extent = $commandAst.CommandElements[$i].Extent
        if ($cursorPosition -lt $extent.EndColumnNumber) {
            # The cursor is in the middle of a word to complete.
            $previousWord = $commandAst.CommandElements[$i - 1].Extent.Text
            $COMP_CWORD = $i
            break
        } elseif ($cursorPosition -eq $extent.EndColumnNumber) {
            # The cursor is immediately after the current word.
            $previousWord = $extent.Text
            $COMP_CWORD = $i + 1
            break
        } elseif ($cursorPosition -lt $extent.StartColumnNumber) {
            # The cursor is within whitespace between the previous and current words.
            $previousWord = $commandAst.CommandElements[$i - 1].Extent.Text
            $COMP_CWORD = $i
            break
        } elseif ($i -eq $commandAst.CommandElements.Count - 1 -and $cursorPosition -gt $extent.EndColumnNumber) {
            # The cursor is within whitespace at the end of the line.
            $previousWord = $extent.Text
            $COMP_CWORD = $i + 1
            break
        }
    }
 
    # Repopulate bash programmable completion variables for scenarios like '/mnt/c/Program Files'/<TAB> where <TAB> should continue completing the quoted path.
    $currentExtent = $commandAst.CommandElements[$COMP_CWORD].Extent
    $previousExtent = $commandAst.CommandElements[$COMP_CWORD - 1].Extent
    if ($currentExtent.Text -like "/*" -and $currentExtent.StartColumnNumber -eq $previousExtent.EndColumnNumber) {
        $COMP_LINE = $COMP_LINE -replace "$($previousExtent.Text)$($currentExtent.Text)", $wordToComplete
        $COMP_WORDS = $COMP_WORDS -replace "$($previousExtent.Text) '$($currentExtent.Text)'", $wordToComplete
        $previousWord = $commandAst.CommandElements[$COMP_CWORD - 2].Extent.Text
        $COMP_CWORD -= 1
    }
 
    # Build the command to pass to WSL.
    $command = $commandAst.CommandElements[0].Value
    $bashCompletion = ". /usr/share/bash-completion/bash_completion 2> /dev/null"
    $commandCompletion = ". /usr/share/bash-completion/completions/$command 2> /dev/null"
    $COMPINPUT = "COMP_LINE=$COMP_LINE; COMP_WORDS=$COMP_WORDS; COMP_CWORD=$COMP_CWORD; COMP_POINT=$cursorPosition"
    $COMPGEN = "bind `"set completion-ignore-case on`" 2> /dev/null; $F `"$command`" `"$wordToComplete`" `"$previousWord`" 2> /dev/null"
    $COMPREPLY = "IFS=`$'n'; echo `"`${COMPREPLY[*]}`""
    $commandLine = "$bashCompletion; $commandCompletion; $COMPINPUT; $COMPGEN; $COMPREPLY" -split ' '
 
    # Invoke bash completion and return CompletionResults.
    $previousCompletionText = ""
    (wsl.exe $commandLine) -split 'n' |
    Sort-Object -Unique -CaseSensitive |
    ForEach-Object {
        if ($wordToComplete -match "(.*=).*") {
            $completionText = Format-WslArgument ($Matches[1] + $_) $true
            $listItemText = $_
        } else {
            $completionText = Format-WslArgument $_ $true
            $listItemText = $completionText
        }
 
        if ($completionText -eq $previousCompletionText) {
            # Differentiate completions that differ only by case otherwise PowerShell will view them as duplicate.
            $listItemText += ' '
        }
 
        $previousCompletionText = $completionText
        [System.Management.Automation.CompletionResult]::new($completionText, $listItemText, 'ParameterName', $completionText)
    }
}
 
# Helper function to escape characters in arguments passed to WSL that would otherwise be misinterpreted.
function global:Format-WslArgument([string]$arg, [bool]$interactive) {
    if ($interactive -and $arg.Contains(" ")) {
        return "'$arg'"
    } else {
        return ($arg -replace " ", " ") -replace "([()|])", ('$1', '`$1')[$interactive]
    }
}

Koodu ahụ dị ntakịrị na-aghọtaghị ụfọdụ ọrụ ime bash, mana ihe anyị na-eme bụ nke a:

  • Ịdenye nkọwa zuru oke maka ihe mkpuchi ọrụ anyị niile site na ịgafe ndepụta $commands na oke -CommandName n'ihi na Register-ArgumentCompleter.
  • Anyị na-edepụta iwu nke ọ bụla maka ọrụ shei nke bash na-eji maka mmecha akpaaka (iji kọwaa nkọwa akpaaka, bash na-eji. $F, ndebiri maka complete -F <FUNCTION>).
  • Ịtụgharị PowerShell Arguments $wordToComplete, $commandAst и $cursorPosition n'ime usoro a na-atụ anya ya site na ọrụ mmecha akpaaka bash dịka nkọwapụta siri dị programmable akpaaka-emecha bash.
  • Anyị na-edepụta ahịrị iwu ka ịnyefe na wsl.exe, nke na-eme ka e guzobe gburugburu ebe obibi n'ụzọ ziri ezi, na-akpọ ọrụ mmecha akpaaka kwesịrị ekwesị, ma na-emepụta ihe na-eme ka ọ bụrụ akara ejiji.
  • Mgbe ahụ, anyị na-akpọ wsl na ahịrị iwu, anyị na-ekewapụta mmepụta site na ndị na-ekesa ahịrị ma mepụta maka nke ọ bụla CompletionResults, nhazi ha na ịgbanarị agwa dị ka oghere na akara aka nke a ga-akọwahie ya.

N'ihi nke a, shells Linux anyị ga-eji otu mmecha ahụ dị ka bash! Ọmụmaatụ:

  • ssh -c <TAB> -J <TAB> -m <TAB> -O <TAB> -o <TAB> -Q <TAB> -w <TAB> -b <TAB>

Mmecha akpaaka ọ bụla na-enye ụkpụrụ akọwapụtara na arụmụka gara aga, na-agụ data nhazi dị ka ndị ọbịa ama ama sitere na WSL!

<TAB> ga okirikiri site parameters. <Ctrl + пробел> ga-egosi nhọrọ niile dị.

Na mgbakwunye, ebe anyị nwere bash autocompletion ugbu a, ị nwere ike mezue ụzọ Linux ozugbo na PowerShell!

  • less /etc/<TAB>
  • ls /usr/share/<TAB>
  • vim ~/.bash<TAB>

N'ọnọdụ ebe bash autocompletion anaghị arụpụta nsonaazụ ọ bụla, PowerShell na-alaghachi na usoro Windows ụzọ ndabara. Ya mere, na omume, ị nwere ike iji ụzọ abụọ ahụ mee ihe n'otu oge na ikike gị.

nkwubi

Iji PowerShell na WSL, anyị nwere ike iwekota iwu Linux n'ime Windows dị ka ngwa ala. Ọ dịghị mkpa ịchọ Win32 na-ewuli ma ọ bụ ọrụ Linux ma ọ bụ kwụsị ọrụ gị site na ịga na shei Linux. Naanị tinye WSL, hazie Profaịlụ PowerShell и depụta iwu ịchọrọ ibubata! Mmecha akpaaka bara ụba maka Linux na Windows parampat iwu yana ụzọ faịlụ bụ ọrụ na-adịghịdị na iwu Windows obodo taa.

Koodu isi mmalite zuru ezu akọwara n'elu, yana ntuziaka agbakwunyere maka itinye ya na usoro ọrụ gị, dị ebe a.

Kedu iwu Linux kacha baa uru? Kedu ihe ndị ọzọ a na-ahụkarị na-efu mgbe ị na-arụ ọrụ na Windows? Dee na nkọwa ma ọ bụ na GitHub!

isi: www.habr.com

Tinye a comment