Ukuhlanganisa imiyalo ye-Linux ku-Windows usebenzisa i-PowerShell ne-WSL

Umbuzo ojwayelekile ovela kubathuthukisi beWindows: “Kungani kungakabikho <ВСТАВЬТЕ ТУТ ЛЮБИМУЮ КОМАНДУ LINUX>?. Noma ngabe ukuswayipha okunamandla less noma amathuluzi ajwayelekile grep noma sed, Onjiniyela be-Windows bafuna ukufinyelela okulula kule miyalo emsebenzini wabo wansuku zonke.

I-Windows Subsystem ye-Linux (WSL) wenze igxathu elikhulu phambili mayelana nalokhu. Ikuvumela ukuthi ushayele imiyalo ye-Linux kusuka kuWindows ngokuyisebenzela wsl.exe (isb. wsl ls). Nakuba lokhu kuwukuthuthuka okuphawulekayo, le nketho inezinkinga eziningi.

  • Ukwengeza yonke indawo wsl eyisicefe futhi engeyona eyemvelo.
  • Izindlela zeWindows ezimpikiswaneni azisebenzi ngaso sonke isikhathi ngoba ama-backslash ahunyushwa njengezinhlamvu zokubalekela kunezihlukanisi zohla lwemibhalo.
  • Izindlela zeWindows kuma-agumenti azihunyushwa endaweni ehambisanayo yokukhweza ku-WSL.
  • Izilungiselelo ezizenzakalelayo azihlonishwa kumaphrofayela e-WSL aneziteketiso neziguquguqukayo zemvelo.
  • Ukuqedwa kwendlela ye-Linux ayisekelwe.
  • Ukuqedwa komyalo akusekelwe.
  • Ukuqedwa kwengxabano akusekelwe.

Ngenxa yalokho, imiyalo ye-Linux iphathwa njengezakhamuzi zesigaba sesibili ngaphansi kwe-Windows—futhi kunzima kakhulu ukuyisebenzisa kunemiyalo yomdabu. Ukulinganisa amalungelo abo, kuyadingeka ukuxazulula izinkinga ezibalwe.

Umsebenzi we-PowerShell wrappers

Ngama-wrappers omsebenzi we-PowerShell, singangeza ukuqedwa komyalo futhi sisuse isidingo seziqalo wsl, ukuhumusha izindlela zeWindows zibe izindlela ze-WSL. Izidingo eziyisisekelo zamagobolondo:

  • Kuwo wonke umyalo we-Linux kufanele kube ne-function wrapper eyodwa enegama elifanayo.
  • Igobolondo kufanele libone izindlela zeWindows ezidluliswe njengezimpikiswano futhi liziguqulele kuzindlela ze-WSL.
  • Igobolondo kufanele lishaye wsl ngomyalo ofanele we-Linux kunoma yikuphi okokufaka kwepayipi kanye nokudlulisa noma yiziphi izimpikiswano zomugqa womyalo ezidluliselwe kumsebenzi.

Njengoba le phethini ingasetshenziswa kunoma yimuphi umyalo, singakwazi ukukhipha incazelo yalezi zigoqa futhi sizikhiqize ngokushintshayo ohlwini lwemiyalo okufanele ingeniswe.

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

Uhla lwa $command ichaza imiyalo yokungenisa. Sibe sesikhiqiza i-function wrapper ngayinye yazo sisebenzisa umyalo Invoke-Expression (ngokuqala ngokususa noma yiziphi iziteketiso ezingangqubuzana nomsebenzi).

Umsebenzi uphindaphinda phezu kwezimpikiswano zomugqa womyalo, unquma izindlela zeWindows usebenzisa imiyalo Split-Path и Test-Pathbese uguqula lezi zindlela zibe izindlela ze-WSL. Sisebenzisa izindlela ngokusebenzisa umsebenzi womsizi Format-WslArgument, esizoyichaza kamuva. Ibalekela izinhlamvu ezikhethekile ezifana nezikhala nabakaki abebengahunyushwa ngokungeyikho.

Ekugcineni, sidlulisela wsl okokufaka kwepayipi nanoma yiziphi izimpikiswano zomugqa womyalo.

Ngalawa ma-wrappers ungabiza imiyalo yakho ye-Linux oyithandayo ngendlela engokwemvelo ngaphandle kokwengeza isiqalo wsl futhi ngaphandle kokukhathazeka ngokuthi izindlela ziguqulwa kanjani:

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

Isethi eyisisekelo yemiyalo iboniswa lapha, kodwa ungakha igobolondo lanoma yimuphi umyalo we-Linux ngokumane ulengeze ohlwini. Uma ungeza le khodi kweyakho iphrofayili I-PowerShell, le miyalo izotholakala kuwe kuso sonke isikhathi se-PowerShell, njengemiyalo yomdabu!

Izilungiselelo Ezizenzakalelayo

Ku-Linux, kuvamile ukuchaza iziteketiso kanye/noma okuguquguqukayo kwendawo kumaphrofayili wokungena, ukusetha imingcele emisiwe yemiyalo esetshenziswa njalo (isibonelo, alias ls=ls -AFh noma export LESS=-i). Okukodwa kokubi kokwenza ummeleli ngegobolondo elingasebenzisani wsl.exe - ukuthi amaphrofayili awalayishiwe, ngakho-ke lezi zinketho azitholakali ngokuzenzakalelayo (isb. ls ku-WSL kanye wsl ls izoziphatha ngendlela ehlukile nesibizo esichazwe ngenhla).

I-PowerShell ihlinzeka $PSDefaultParameterValues, indlela evamile yokuchaza amapharamitha amisiwe, kodwa ama-cmdlets nemisebenzi ethuthukisiwe kuphela. Yebo, singenza imisebenzi ethuthukisiwe ngamagobolondo ethu, kodwa lokhu kwethula izinkinga ezingadingekile (isibonelo, i-PowerShell ihlobanisa amagama epharamitha ngokwengxenye (isibonelo, -a ihambisana ne -ArgumentList), ezongqubuzana nemiyalo ye-Linux ethatha amagama ayingxenye njengezimpikiswano), futhi i-syntax yokuchaza amanani azenzakalelayo ngeke ifaneleke kakhulu (izimpikiswano ezizenzakalelayo zidinga igama lepharamitha kukhiye, hhayi nje igama lomyalo) .

Kodwa-ke, ngokuguqulwa okuncane kumagobolondo ethu, singakwazi ukusebenzisa imodeli efana ne $PSDefaultParameterValues, futhi unike amandla izinketho ezizenzakalelayo zemiyalo ye-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 ' ')
    }
}

Ukudlula $WslDefaultParameterValues emgqeni womyalo, sithumela imingcele nge wsl.exe. Okulandelayo kubonisa indlela yokwengeza imiyalelo kuphrofayela yakho ye-PowerShell ukuze ulungiselele izilungiselelo ezizenzakalelayo. Manje singakwenza!

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

Njengoba amapharamitha amodela ngemuva $PSDefaultParameterValues, Ungakwazi kulula ukuwakhubaza okwesikhashana ngokufaka ukhiye "Disabled" ibe yincazelo $true. Inzuzo eyengeziwe yetafula le-hashi elihlukile yikhono lokukhubaza $WslDefaultParameterValues ngokwehlukana $PSDefaultParameterValues.

Ukuqedwa kwengxabano

I-PowerShell ikuvumela ukuthi ubhalise ama-trailer engxabano usebenzisa umyalo Register-ArgumentCompleter. I-Bash inamandla amathuluzi okuqedela ngokuzenzakalela ahlelekayo. I-WSL ikuvumela ukuthi ushayele i-bash kusuka ku-PowerShell. Uma singabhalisa ukuqedwa kokuphikisana kokugoqa kwethu kwe-PowerShell futhi sishayele i-bash ukuze sikhiqize ukuqedwa, sithola ukuphothulwa kwempikiswano egcwele ngokunemba okufanayo ne-bash ngokwayo!

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

Ikhodi iminyene kancane ngaphandle kokuqonda eminye yemisebenzi yangaphakathi ye-bash, kodwa ngokuyisisekelo esikwenzayo yilokhu:

  • Ukubhalisa isigcwalisi sokungqubuzana kwawo wonke ama-func wrappers ethu ngokudlulisa uhlu $commands kupharamitha -CommandName ngoba Register-ArgumentCompleter.
  • Senza imephu umyalo ngamunye kumsebenzi wegobolondo u-bash awusebenzisela ukuqedela ngokuzenzakalela (ukuchaza imininingwane yokuqedela ngokuzenzakalela, ukusetshenziswa kwe-bash $F, isifinyezo sokuthi complete -F <FUNCTION>).
  • Ukuguqula Izimpikiswano ze-PowerShell $wordToComplete, $commandAst и $cursorPosition kufomethi elindelwe imisebenzi ye-bash yokuqedela ngokuzenzakalela ngokuya ngokucaciswa ukuqedela okuzenzakalelayo okuhlelekayo bash.
  • Sibhala umugqa womyalo esizodlulisela kuwo wsl.exe, okuqinisekisa ukuthi indawo ezungezile imiswe ngendlela efanele, ibiza umsebenzi ofanele wokuqedela ngokuzenzakalela, futhi ikhiphe imiphumela ngemfashini yomugqa nomugqa.
  • Bese siyafona wsl ngomugqa womyalo, sihlukanisa okukhiphayo ngezihlukanisi zemigqa futhi sikhiqizele ngakunye CompletionResults, ukuzihlunga kanye nezinhlamvu ezibalekayo njengezikhala nabakaki ebezingahunyushwa ngokungeyikho.

Njengomphumela, amagobolondo ethu omyalo we-Linux azosebenzisa ukuqedela okuzenzakalelayo okufanayo ne-bash! Ngokwesibonelo:

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

Ukuqedela ngokuzenzakalela ngakunye kunikeza amanani aqondile ku-agumenti yangaphambilini, ukufunda idatha yokumisa njengabasingathi abaziwayo abavela ku-WSL!

<TAB> izojikeleza kumapharamitha. <Ctrl + пробел> izobonisa zonke izinketho ezitholakalayo.

Futhi, njengoba manje sinokuqedela okuzenzakalelayo kwe-bash, ungakwazi ukuqedela ngokuzenzakalela izindlela ze-Linux ku-PowerShell!

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

Ezimeni lapho ukuqedelwa ngokuzenzakalela kwe-bash kungakhiqizi noma yimiphi imiphumela, i-PowerShell ibuyela ezindleleni ezizenzakalelayo zesistimu. Ngakho-ke, ekusebenzeni, ungasebenzisa kanyekanye izindlela zombili ngokubona kwakho.

isiphetho

Ngokusebenzisa i-PowerShell ne-WSL, singahlanganisa imiyalo ye-Linux ku-Windows njengezinhlelo zokusebenza zomdabu. Asikho isidingo sokucinga i-Win32 builds noma izinsiza ze-Linux noma uphazamise ukuhamba kwakho komsebenzi ngokuya kugobolondo le-Linux. Nje faka i-WSL, lungiselela Iphrofayili ye-PowerShell и klelisa imiyalo ofuna ukuyingenisa! Ukuqedela ngokuzenzakalela okucebile kwe-Linux kanye nemingcele yomyalo we-Windows nezindlela zefayela kuwukusebenza okungatholakali ngisho nasemiyalweni yomdabu ye-Windows namuhla.

Ikhodi yomthombo egcwele echazwe ngenhla, kanye nemihlahlandlela eyengeziwe yokuyihlanganisa ekuhambeni kwakho komsebenzi, iyatholakala lapha.

Yimiphi imiyalo ye-Linux oyithola iwusizo kakhulu? Yiziphi ezinye izinto ezivamile ezingekho lapho usebenza ku-Windows? Bhala kumazwana noma ku-GitHub!

Source: www.habr.com

Engeza amazwana