Kev sib xyaw Linux cov lus txib rau hauv Windows siv PowerShell thiab WSL

Cov lus nug ib txwm los ntawm Windows developers: “Vim li cas tseem tsis muaj <ВСТАВЬТЕ ТУТ ЛЮБИМУЮ КОМАНДУ LINUX>?. Seb nws yog lub zog los so less los yog cov cuab yeej paub grep los yog sed, Windows developers xav tau yooj yim nkag mus rau cov lus txib hauv lawv cov haujlwm niaj hnub.

Windows Subsystem rau Linux (WSL) tau ua ib kauj ruam loj rau pem hauv ntej ntawm qhov no. Nws tso cai rau koj hu rau Linux cov lus txib los ntawm Windows los ntawm kev tso npe rau lawv wsl.exe (Xws li. wsl ls). Txawm hais tias qhov no yog qhov kev txhim kho tseem ceeb, qhov kev xaiv no raug kev txom nyem los ntawm ntau qhov tsis zoo.

  • Ubiquitous ntxiv wsl tedious thiab unnatural.
  • Txoj hauv kev Windows hauv kev sib cav tsis yog ib txwm ua haujlwm vim tias cov backslashes raug txhais ua cov cim khiav tawm es tsis yog cov npe cais.
  • Txoj hauv kev Windows hauv kev sib cav tsis tau txhais mus rau qhov sib thooj mount point hauv WSL.
  • Default settings tsis raug hwm hauv WSL cov ntaub ntawv nrog cov npe thiab ib puag ncig hloov pauv.
  • Linux txoj kev ua tiav tsis txaus siab.
  • Kev ua tiav tsis txaus siab.
  • Kev sib cav ua tiav tsis txaus siab.

Raws li qhov tshwm sim, Linux cov lus txib raug kho zoo li cov pej xeem thib ob hauv qab Windows - thiab nyuaj rau siv dua li cov lus txib ib txwm muaj. Txhawm rau kom sib npaug lawv cov cai, nws yog ib qho tsim nyog los daws cov teeb meem teev tseg.

PowerShell muaj nuj nqi wrappers

Nrog PowerShell muaj nuj nqi wrappers, peb tuaj yeem ntxiv cov lus txib ua tiav thiab tshem tawm qhov xav tau ua ntej wsl, txhais Windows paths rau hauv WSL paths. Cov ntsiab lus tseem ceeb rau cov plhaub:

  • Rau txhua qhov Linux hais kom ua yuav tsum muaj ib txoj haujlwm wrapper nrog tib lub npe.
  • Lub plhaub yuav tsum paub txog lub Windows paths dhau los ua kev sib cav thiab hloov mus rau WSL txoj hauv kev.
  • Lub plhaub yuav tsum hu wsl nrog rau qhov tsim nyog Linux hais kom ua rau cov raj xa dej tawm thiab dhau ib qho kev sib cav hais kom dhau mus rau txoj haujlwm.

Txij li cov qauv no tuaj yeem siv rau txhua qhov kev hais kom ua, peb tuaj yeem paub qhov tseeb ntawm cov ntaub qhwv no thiab ua kom muaj zog los ntawm cov npe ntawm cov lus txib kom import.

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

Sau npe $command txhais cov lus txib ntshuam. Peb ces dynamically tsim ib tug muaj nuj nqi wrapper rau txhua tus ntawm lawv siv cov lus txib Invoke-Expression (los ntawm thawj zaug tshem tawm cov npe uas yuav cuam tshuam nrog lub luag haujlwm).

Lub luag haujlwm iterates dhau cov kab lus sib cav, txiav txim siab txoj hauv kev Windows siv cov lus txib Split-Path и Test-Paththiab tom qab ntawd hloov cov kab no mus rau WSL txoj hauv kev. Peb khiav txoj hauv kev los ntawm kev ua haujlwm pab Format-WslArgument, uas peb yuav txhais tom qab. Nws dim cov cim tshwj xeeb xws li qhov chaw thiab cov kab lus uas yuav tsum tau txhais tsis raug.

Thaum kawg, peb qhia wsl pipeline input thiab tej kab lus sib cav.

Nrog cov wrappers no koj tuaj yeem hu koj nyiam Linux cov lus txib hauv txoj hauv kev zoo dua yam tsis tau ntxiv cov npe ua ntej wsl thiab tsis muaj kev txhawj xeeb txog yuav ua li cas cov kev hloov dua siab tshiab:

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

Cov txheej txheem ntawm cov lus txib tau qhia ntawm no, tab sis koj tuaj yeem tsim lub plhaub rau ib qho Linux hais kom ua los ntawm kev ntxiv rau hauv daim ntawv. Yog tias koj ntxiv cov cai no rau koj profile PowerShell, cov lus txib no yuav muaj rau koj hauv txhua qhov kev sib tham PowerShell, ib yam li cov lus txib ib txwm!

Default Settings

Hauv Linux, nws yog ib qho tsim nyog los txheeb xyuas cov npe npe thiab / lossis ib puag ncig hloov pauv hauv cov ntawv nkag mus, teeb tsa qhov tsis raug rau cov lus txib nquag siv (piv txwv li, alias ls=ls -AFh los yog export LESS=-i). Ib qho tsis zoo ntawm kev tso npe los ntawm lub plhaub tsis sib tham wsl.exe - tias cov profiles tsis thauj khoom, yog li cov kev xaiv no tsis muaj los ntawm lub neej ntawd (piv txwv li. ls hauv WSL thiab wsl ls yuav coj txawv txawv nrog cov alias teev saum toj no).

PowerShell muab $PSDefaultParameterValues, tus txheej txheem txheej txheem rau kev txheeb xyuas qhov tsis zoo, tab sis tsuas yog rau cmdlets thiab cov haujlwm siab heev. Tau kawg, peb tuaj yeem ua cov haujlwm siab tshaj tawm ntawm peb lub plhaub, tab sis qhov no qhia txog cov teeb meem tsis tsim nyog (piv txwv li, PowerShell cuam tshuam cov npe ntawm ib feem (piv txwv li, -a cuam ​​tshuam nrog -ArgumentList), uas yuav cuam tshuam nrog Linux cov lus txib uas coj cov npe ib feem raws li cov lus sib cav), thiab cov lus qhia rau kev txheeb xyuas qhov tseem ceeb yuav tsis yog qhov tsim nyog tshaj plaws (kev sib cav tsis zoo yuav tsum muaj lub npe ntawm qhov ntsuas hauv qhov tseem ceeb, tsis yog lub npe hais kom ua). .

Txawm li cas los xij, nrog kev hloov kho me ntsis rau peb lub plhaub, peb tuaj yeem siv cov qauv zoo ib yam li $PSDefaultParameterValues, thiab pab kom muaj kev xaiv rau Linux cov lus txib!

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 ' ')
    }
}

Hla $WslDefaultParameterValues mus rau kab hais kom ua, peb xa cov parameters ntawm wsl.exe. Cov hauv qab no qhia yuav ua li cas ntxiv cov lus qhia rau koj qhov profile PowerShell kom teeb tsa qhov chaw pib. Tam sim no peb tuaj yeem ua tau!

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

Txij li cov parameters yog qauv tom qab $PSDefaultParameterValues, Koj ua tau nws yooj yim rau lov tes taw lawv ib ntus los ntawm kev txhim kho tus yuam sij "Disabled" rau hauv lub ntsiab lus $true. Ib qho txiaj ntsig ntxiv ntawm lub rooj sib cais hash yog qhov muaj peev xwm ua haujlwm tsis tau $WslDefaultParameterValues cais los ntawm $PSDefaultParameterValues.

Kev sib cav tiav

PowerShell tso cai rau koj los sau npe sib cav sib cav siv cov lus txib Register-ArgumentCompleter. Bash muaj zog programmable auto-completion cov cuab yeej. WSL tso cai rau koj hu bash los ntawm PowerShell. Yog tias peb tuaj yeem sau npe sib cav ua tiav rau peb lub PowerShell muaj nuj nqi wrappers thiab hu bash los tsim cov kev ua tiav, peb tau txais kev sib cav tag nrho nrog tib qhov tseeb li bash nws tus kheej!

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

Cov cai yog me ntsis ntom yam tsis nkag siab qee qhov ntawm bash lub luag haujlwm sab hauv, tab sis qhov peb ua yog qhov no:

  • Sau npe qhov kev sib cav ua tiav rau tag nrho peb cov ntaub ntawv muaj nuj nqi los ntawm kev dhau ib daim ntawv teev npe $commands nyob rau hauv parameter -CommandName rau Register-ArgumentCompleter.
  • Peb daim ntawv qhia txhua qhov hais kom ua rau lub plhaub ua haujlwm uas bash siv rau kev ua tiav autocompletion (kom txhais cov ntsiab lus autocompletion, bash siv $F, abbreviation rau complete -F <FUNCTION>).
  • Hloov PowerShell Arguments $wordToComplete, $commandAst и $cursorPosition rau hauv hom xav tau los ntawm bash's autocompletion functions raws li cov specifications programmable pib ua kom tiav bash.
  • Peb sau cov kab hais kom hloov mus rau wsl.exe, uas ua kom ntseeg tau tias ib puag ncig raug teeb tsa kom raug, hu rau qhov tsim nyog nws pib ua tiav, thiab tso tawm cov txiaj ntsig hauv kab-los-kab zam.
  • Ces peb hu wsl nrog cov kab hais kom ua, peb cais cov zis los ntawm kab cais thiab tsim rau txhua tus CompletionResults, txheeb lawv thiab khiav cov cim xws li qhov chaw thiab cov kab lus uas yuav txhais tau yuam kev.

Yog li ntawd, peb cov lus txib Linux yuav siv raws nraim tib yam autocompletion li bash! Piv txwv li:

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

Txhua qhov autocompletion muab cov txiaj ntsig tshwj xeeb rau qhov kev sib cav dhau los, nyeem cov ntaub ntawv teeb tsa xws li paub cov tswv los ntawm WSL!

<TAB> yuav voj voog los ntawm cov tsis. <Ctrl + пробел> yuav qhia tag nrho cov kev xaiv muaj.

Ntxiv rau, txij li tam sim no peb muaj bash autocompletion, koj tuaj yeem ua tiav Linux txoj hauv kev ncaj qha hauv PowerShell!

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

Nyob rau hauv rooj plaub uas bash autocompletion tsis tsim ib qho txiaj ntsig, PowerShell rov qab mus rau qhov system default Windows paths. Yog li, hauv kev xyaum, koj tuaj yeem siv ib txhij siv ob txoj hauv kev ntawm koj qhov kev txiav txim siab.

xaus

Siv PowerShell thiab WSL, peb tuaj yeem ua ke cov lus txib Linux rau hauv Windows raws li cov ntawv thov ib txwm muaj. Tsis tas yuav tshawb nrhiav Win32 tsim lossis Linux siv lossis cuam tshuam koj cov haujlwm los ntawm kev mus rau lub plhaub Linux. Tsuas yog nruab WSL, configure PowerShell profile и sau cov lus txib uas koj xav import! Kev nplua nuj autocompletion rau Linux thiab Windows cov lus txib tsis thiab cov ntaub ntawv txoj hauv kev yog kev ua haujlwm uas tsis muaj nyob hauv cov lus txib Windows niaj hnub no.

Daim ntawv qhia tag nrho uas tau piav qhia saum toj no, nrog rau cov lus qhia ntxiv rau kev sib koom ua ke rau hauv koj qhov kev ua haujlwm, muaj no.

Yam twg Linux commands koj pom muaj txiaj ntsig tshaj? Lwm yam dab tsi uas ploj lawm thaum ua haujlwm hauv Windows? Sau rau hauv cov lus los yog ntawm GitHub!

Tau qhov twg los: www.hab.com

Ntxiv ib saib