Tu'ufa'atasia o fa'atonuga Linux i totonu o Windows e fa'aaoga ai le PowerShell ma le WSL

O se fesili masani mai Windows developers: “Aisea ua leai ai <ВСТАВЬТЕ ТУТ ЛЮБИМУЮ КОМАНДУ LINUX>?. Pe o se swipe malosi less po o meafaigaluega masani grep poʻo sed, e mana'omia e le au atia'e Windows le avanoa faigofie i nei poloaiga ia latou galuega i aso taitasi.

Windows Subsystem mo Linux (WSL) ua faia se laasaga tele i luma i lea tulaga. E fa'atagaina oe e vala'au fa'atonuga Linux mai le Windows e ala i le suiina i latou wsl.exe (eg. wsl ls). E ui lava o se faʻaleleia tele lea, o lenei filifiliga e mafatia i le tele o faʻaletonu.

  • Fa'aopoopoga i soo se mea wsl e fiu ma e le masani ai.
  • O auala Windows i finauga e le aoga i taimi uma ona o fa'ailoga pito i tua o lo'o faauigaina o ni tagata e sola ese nai lo le vavaeeseina o le lisi.
  • O ala Windows i finauga e le'o fa'aliliuina i le tulaga fa'amau i le WSL.
  • E le fa'aaloalogia tulaga fa'aletonu i fa'amatalaga WSL fa'atasi ai ma igoa fa'aigoa ma suiga o le si'osi'omaga.
  • E le lagolagoina le fa'amae'aina o ala Linux.
  • E le lagolagoina le fa'amae'aina o poloaiga.
  • E le lagolagoina le fa'amae'aina o finauga.

O le iʻuga, o tulafono a Linux e faʻaogaina e pei o tagatanuu lona lua i lalo o Windows-ma e sili atu ona faigata ona faʻaoga nai lo tulafono faʻale-aganuʻu. Ina ia tutusa a latou aia tatau, e tatau ona foia faafitauli o loʻo lisiina.

PowerShell afifi galuega

Faatasi ai ma PowerShell galuega afifi, e mafai ona tatou faʻaopoopoina le faʻamaeʻaina o poloaiga ma faʻaumatia le manaʻoga mo prefixes wsl, fa'aliliuina ala Windows i ala WSL. Manaoga autu mo atigi:

  • Mo fa'atonuga uma a Linux e tatau ona i ai se afifi galuega e tasi ma le igoa tutusa.
  • E tatau ona iloa e le atigi ala Windows na pasia e fai ma finauga ma liliu i latou i ala WSL.
  • E tatau ona valaau le atigi wsl fa'atasi ai ma le fa'atonuga Linux talafeagai i so'o se fa'aoga paipa ma tu'uina atu so'o se fa'atonuga laina fa'atonuga na pasia i le galuega.

Talu ai o lenei mamanu e mafai ona faʻaoga i soʻo se poloaiga, e mafai ona tatou faʻamalamalamaina le faʻamatalaga o nei afifi ma faʻamalosia malosi mai se lisi o poloaiga e faʻaulufale mai.

# 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 ' ')
    }
}
"@
}

Lisi o $command fa'amatala tulafono fa'aulufale mai. Ona matou faia lea ma le malosi se afifi galuega mo i latou taʻitasi e faʻaaoga ai le poloaiga Invoke-Expression (e ala i le aveeseina muamua o soʻo se igoa e feteʻenaʻi ma le galuega).

O le galuega e faʻaauau i luga o finauga laina laina, fuafua auala Windows e faʻaaoga ai tulafono Split-Path и Test-Pathona faaliliu lea o nei auala i auala WSL. Matou te taufetuli ala i se galuega fesoasoani Format-WslArgument, lea o le a tatou faamatalaina mulimuli ane. E sola ese mai mataitusi faapitoa e pei o avanoa ma puipui semanu e faauigaseseina.

Mulimuli ane, matou te momoli atu wsl fa'aoga paipa ma so'o se fa'aupuga o laina fa'atonu.

Faatasi ai ma nei afifi e mafai ona e valaʻau i lau Linux e sili ona e fiafia i ai i se auala masani e aunoa ma le faʻaopoopoina o se prefix wsl ma e aunoa ma le popole pe faapefea ona liua ala:

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

O loʻo faʻaalia iinei le seti o faʻatonuga, ae e mafai ona e fatuina se atigi mo soʻo se faʻatonuga Linux e ala i le faʻaopoopoina i le lisi. Afai e te faʻaopoopoina lenei code i lau talaaga PowerShell, o nei poloaiga o le a avanoa mo oe i sauniga PowerShell uma, e pei lava o tulafono masani!

Fa'atonu Fa'atonu

I Linux, e masani lava ona faʻamatalaina igoa ma / poʻo suiga o le siosiomaga i faʻamatalaga saini, faʻatulagaina faʻamaufaʻailoga faʻaletonu mo tulafono faʻaaoga masani (mo se faʻataʻitaʻiga, alias ls=ls -AFh poʻo export LESS=-i). O se tasi o mea le lelei o le sui e ala i se atigi e le o fesoʻotaʻi wsl.exe - e le o utaina faʻamatalaga, o lea e le maua ai nei filifiliga ona o le faaletonu (ie. ls i le WSL ma wsl ls o le a ese le amio ma le alias ua faʻamatalaina i luga).

E maua ai e le PowerShell $PSDefaultParameterValues, o se faiga masani mo le faʻamalamalamaina o faʻamaufaʻailoga faʻaletonu, ae naʻo mo cmdlets ma galuega faʻalautele. O le mea moni, e mafai ona tatou faia ni galuega faʻapitoa mai a tatou atigi, ae o lenei mea e faʻaalia ai ni faʻalavelave le manaʻomia (mo se faʻataʻitaʻiga, PowerShell faʻamaopoopo igoa faʻailoga (mo se faʻataʻitaʻiga, -a fa'atasi ma -ArgumentList), lea o le a feteʻenaʻi ma tulafono Linux e faʻaaogaina igoa faʻapitoa e fai ma finauga), ma o le syntax mo le faʻamalamalamaina o tau le aoga o le a le sili ona talafeagai (faʻamatalaga faʻaletonu e manaʻomia ai le igoa o le parakalafa i le ki, ae le naʻo le igoa o le poloaiga) .

Ae ui i lea, faʻatasi ai ma sina suiga i a tatou atigi, e mafai ona tatou faʻatinoina se faʻataʻitaʻiga tutusa $PSDefaultParameterValues, ma fa'atagaina filifiliga fa'aletonu mo fa'atonuga 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 ' ')
    }
}

pasi $WslDefaultParameterValues i le laina o le poloaiga, matou te auina atu parakalafa e ala i wsl.exe. O lo'o fa'aalia i lalo le fa'aopoopoina o fa'atonuga i lau fa'amatalaga o le PowerShell e fa'atulaga ai tulaga fa'aletonu. Ua mafai nei ona tatou faia!

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

Talu ai ua fa'ata'ita'iina ia fa'asologa $PSDefaultParameterValues, E te mafaia e faigofie lava ona fa'agata le tumau e ala i le faapipiiina o le ki "Disabled" i le uiga $true. O se fa'amanuiaga fa'aopoopo o se isi laulau hash o le mafai lea ona fa'agata $WslDefaultParameterValues ese mai $PSDefaultParameterValues.

Fa'ai'uga finauga

E fa'atagaina oe e le PowerShell e resitalaina ta'avale finauga e fa'aaoga ai le fa'atonuga Register-ArgumentCompleter. Bash e malosi mea faigaluega fa'amae'a fa'apolokalame. Ua fa'atagaina oe e le WSL e vala'au le bash mai le PowerShell. Afai e mafai ona matou resitalaina faʻamaeʻaina finauga mo a matou PowerShell galuega afifi ma valaʻau bash e faʻatupu ai faʻamaeʻaina, matou te maua atoa finauga faʻamaeʻaina ma le saʻo tutusa e pei o le bash lava ia!

# 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]
    }
}

O le code e fai si mafiafia e aunoa ma le malamalama i nisi o galuega i totonu o le bash, ae o le mea tonu tatou te faia o lenei:

  • Le resitalaina o se fa'ai'uga fa'amae'a mo a matou mea fa'apipi'i uma e ala i le pasia o se lisi $commands i le parakalafa -CommandName mo Register-ArgumentCompleter.
  • Matou te faʻafanua taʻiala taʻitasi i le atigi galuega e faʻaaogaina e bash mo le faʻamaeʻaina (e faʻamalamalama ai faʻamatalaga faʻamaeʻaina, faʻaoga bash $F, faapuupuuga mo complete -F <FUNCTION>).
  • Suia le PowerShell Argument $wordToComplete, $commandAst и $cursorPosition i totonu o le faatulagaga o loʻo faʻamoemoeina e le bash's autocompletion galuega e tusa ai ma faʻamatalaga fa'ato'a fa'apolokalameina pa'u.
  • Matou te fatuina se laina faʻatonu e faʻafeiloaʻi i wsl.exe, e fa'amautinoa ai o lo'o fa'atulaga sa'o le si'osi'omaga, vala'au le galuega fa'amae'a fa'auma talafeagai, ma fa'ataunu'u fa'ai'uga i faiga fa'a-laina-laina.
  • Ona matou valaau lea wsl fa'atasi ai ma le laina fa'atonu, matou te tu'u'ese'ese le mea e fai i laina vavae ma fa'atupuina mo ta'itasi CompletionResults, fa'avasega ma sola ese mataitusi e pei o avanoa ma puipui e ono fa'aseseina.

O le iʻuga, o le a faʻaaogaina e le matou Linux shells le faʻaogaina tutusa e pei o le bash! Faataitaiga:

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

O faʻamaeʻaina taʻitasi e tuʻuina atu tau faʻapitoa i le finauga talu ai, faitau faʻamaumauga faʻamaumauga e pei o faʻamatalaga lauiloa mai le WSL!

<TAB> o le a faʻataʻamilomilo i faʻamaufaʻailoga. <Ctrl + пробел> o le a fa'aalia uma avanoa avanoa.

Ma le isi, talu ai o lea ua i ai le matou bash autocompletion, e mafai ona e faʻamaeʻaina auala Linux saʻo i le PowerShell!

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

I tulaga e le maua ai e le bash autocompletion ni faʻaiʻuga, e toe foʻi le PowerShell i le faʻaogaina o auala Windows. O le mea lea, i le faʻatinoga, e mafai ona e faʻaogaina auala uma e lua i lau pule faitalia.

iʻuga

I le fa'aaogaina o le PowerShell ma le WSL, e mafai ona matou tu'ufa'atasia fa'atonuga Linux i totonu o Windows e fai ma fa'aoga masani. E leai se mea e manaʻomia e suʻe ai Win32 builds poʻo Linux utilities poʻo le faʻalavelaveina o lau galuega e ala i le alu i se atigi Linux. Na'o fa'apipi'i le WSL, fetuutuunai Fa'amatalaga PowerShell и lisi poloaiga e te mana'o e fa'aulufale mai! O le fa'amae'aina o le autocompletion mo Linux ma Windows fa'atonuga fa'atonuga ma ala faila o galuega e le o maua i totonu o tulafono a le Windows i aso nei.

O lo'o avanoa le fa'ailoga fa'apogai atoa o lo'o fa'amatalaina i luga, fa'apea fo'i ma ta'iala fa'aopoopo mo le tu'ufa'atasia i lau galuega iinei.

O fea tulafono Linux e te maua e sili ona aoga? O a isi mea masani e misi pe a galue i Windows? Tusi i faʻamatalaga poʻo i luga ole GitHub!

puna: www.habr.com

Faaopoopo i ai se faamatalaga