Integrating Linux mandata in Fenestra utens PowerShell et WSL

Typical quaestio e Windows developers: "Cur adhuc non est" <ВСТАВЬТЕ ТУТ ЛЮБИМУЮ КОМАНДУ LINUX>?. An validus ungunt less aut nota instrumenta grep aut sed, Fenestrae tincidunt facilem accessum volunt ad haec mandata in opere suo cotidiano.

Fenestra Subsystem pro Linux (WSL) ingentem gradum hac de re fecit. Liceat tibi a Windows Linux vocare mandata procurando per eos wsl.exe (Exampla: wsl ls). Etsi haec emendatio notabilis est, haec optio multis incommodis laborat.

  • Ubiquitous addition wsl longum atque impium.
  • Fenestrae semitae in argumentis non semper laborant quia backslashes interpretantur ingenia effugia potius quam directoria separatorum.
  • Fenestrae rationes in argumentis ad respondentem punctum montis WSL transferuntur.
  • Default occasus in WSL profiles cum aliases et variabiles ambitus non observantur.
  • Linux iter complementum non praebetur.
  • Mandatum complementum non praebetur.
  • Argumentum perfectio non praebetur.

Quam ob rem mandata Linux tractata sunt sicut cives sub Fenestra secunda classis - et difficiliora sunt utendi quam nativi imperia. Ad eorum iura aequanda, problemata enumerata solvere necesse est.

PowerShell munus derecta

Cum involucris functionis PowerShell, addere possumus complementum iubere et necessitatem praefixis tollere wsl, Fenestras vias in vias WSL vertens. Basic requisita testarum:

  • Nam omne mandatum Linux unum cum eodem nomine munus esse debet.
  • Testa fenestrarum semitas tamquam argumenta latas agnoscere debet et eas ad WSL semitas convertere.
  • Testa debet vocare wsl cum congruo Linux mandato cuilibet pipeline input et transeundo quodlibet mandatum linea argumenta ad functionem lata.

Cum hoc exemplar ad quodvis praeceptum applicari possit, definitionem horum involucrorum abstrahere et dynamice generare ex indice mandatorum importare possumus.

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

album $command definit imperium importare. Nos ergo dynamice munus serratus generamus pro unoquoque eorum utentes mandato Invoke-Expression (primo quodlibet aliases qui cum officio pugnantes removerent).

Munus per rationes rectas mandatum iterat, Fenestra viis imperat utens Split-Path и Test-Pathac deinde has semitas ad WSL semitas convertit. Viae currimus per munus adiutorium Format-WslArgumentquem postea definiemus. Speciales notas fugit ut spatia et parentheses quae alioqui male intellecta sunt.

Demum importamus wsl pipeline input and any command line arguments.

Cum his involucris nominare potes praecepta tua dilectissima Linux magis naturali modo sine praepositione adiecta wsl et sine cura quomodo viae convertuntur;

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

Praecipua mandatorum copia hic ostenditur, sed testam cuivis imperio Linux creare potes, ad indicem addito simpliciter. Si hoc codice adde tuum profile PowerShell, haec mandata vobis praesto erunt in omni sessione PowerShell, sicut praecepta nativa!

default occasus

In Linux, commune est aliases et/vel variabiles ambitus in login profiles definire, ambitum defectivum ponere pro mandatis saepe adhibitis (exempli gratia, alias ls=ls -AFh aut export LESS=-i). Una incommoda procurandi per testam non-interactive wsl.exe - ut profile non onerentur, ideo hae optiones per defaltam non in promptu sunt (i.e. ls in WSL and * wsl ls aliter agemus cum alias supra definitis).

PowerShell praebet $ PSDefaultParameterValues, vexillum mechanismum ad ambitum default definiendum, sed solum pro cmdlets et functionibus provectis. Utique ex conchis nostris functiones provectas facere possumus, sed haec complicationes superfluas infert (exempli gratia, PowerShell nominat nomina parametri partiales (exempli gratia; -a habeat cum -ArgumentList), qui cum Linux mandatis repugnet quae nomina partialia pro argumentis accipient), et syntaxis ad valores defectus definiendos aptissima non erit (defalta argumenta require nomen parametri in clave, non solum nomen praecepti) .

Attamen, ut nostris conchis aliqualiter modificatione, exemplar simile efficere possumus $PSDefaultParameterValueset fac default optiones pro Linux imperata!

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

Transiens $WslDefaultParameterValues imperio lineae parametri mittimus wsl.exe. Sequentia ostendit quomodo informationes tuas profile PowerShell addendi ad occasus default configurare. Nunc id facere possumus!

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

Cum ambitum imitantur $PSDefaultParameterValues, Potes facile disable illis tempus per installing clavem "Disabled" in significatione $true. Nullam mensam separatum beneficium additional est facultas disable $WslDefaultParameterValues seorsim a * $PSDefaultParameterValues.

Argumentum complementum

PowerShell sino vos ut subcriptio argumentum massa utens imperio Register-ArgumentCompleter. Pagina potens est programmable auto- complementum instrumenta. WSL permittit te bash vocare ex PowerShell. Si argumenta completionum subcriptio pro functionibus PowerShell nostris involucris et vercundus vocamus ad complementum generandum, plenam argumenti complementum eadem praecisione ac ipsum vercundus obtinemus!

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

Codex densissimus est sine aliqua functionum internarum bajularum intellegentia, sed plerumque hoc est quod agimus;

  • Perscriptum argumentum perfectoris pro omnibus functionibus nostris involucris transeundo elenchum $commands in parametri -CommandName ad Register-ArgumentCompleter.
  • Singulum mandatum ad munus testae describendum, quae vercundus usus ad autocompletionem pertinet (definire autocompletionem specificationis, vercundus usus $F, abbreviation for complete -F <FUNCTION>).
  • Convertere PowerShell Argumenta $wordToComplete, $commandAst и $cursorPosition in forma expectata a vercundus scriptor autocompletion munera secundum determinationes programmable auto- completionem vercundus.
  • Nos lineam mandatum transferre componimus wsl.exequae efficit ut ambitus recte constituatur, munus opportunum vocat auto- completionem, et eventus in linea ratione disponit.
  • Tunc vocamus wsl cum linea recta separamus output per separatores et generant pro singulis CompletionResults, genus earum et ingenia effugia, ut spatia et parentheses, quae alioqui male intellecta sunt.

Quam ob rem mandatum Linux nostra testa eadem autocompletione prorsus utetur ut vercundus! Exempli gratia:

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

Quaelibet autocompletio valores determinatos ad argumentum priorem praebet, notitias configurationis legendi ut nota exercitus ab WSL!

<TAB> per ambitum revolvetur. <Ctrl + пробел> ostendet omnia bene available.

Plus, quia nunc bash autocompletionem habemus, Linux autocompletam vias rectas in PowerShell potes!

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

In casibus ubi bash autocompletio nullum eventum gignit, PowerShell revertitur ad systema viae Windows default. Ita in usu simul utraque via ad arbitrium tuum uti potes.

conclusio,

Utentes PowerShell et WSL, possumus Linux mandata Linux in Fenestra applicationes ut nativas integrare. Non opus est ut Win32 aedificat vel Linux utilitates quaeras vel tuum workfluum interrumpat eundo ad Testam Linux. Just install WSL, configurare PowerShell profile и commemorare mandata vis importare! Dives autocompletio pro Linux et Windows parametri mandatum ac viae limae est functionality quae etiam in Fenestra patria imperat hodie praesto non est.

Codex fons plenus supra descriptus est, necnon lineamenta additamenta ad incorporandum in tuo labore profluvio, praesto est hic.

Linux quod maxime utile imperium habes? Quae alia communia desunt cum in Fenestra laborant? Scribere in commentaria vel in GitHub!

Source: www.habr.com

Add a comment