PowerShell / PSReadLine

A bash inspired readline implementation for PowerShell
BSD 2-Clause "Simplified" License
3.75k stars 296 forks source link

Add "text object" support for Vi mode #584

Open gwojan opened 6 years ago

gwojan commented 6 years ago

It would be really nice if Vi mode supported text objects so things like:

ci{
da{
ci[
ci"
ci'
etc...

were possible.

lzybkr commented 6 years ago

Indeed - I might have mentioned this to @srdubya a long time ago. I might even switch to vi mode if this was implemented. (I use vim or vim bindings in my editors.)

gwojan commented 6 years ago

Yeah, my workaround when I really want to get nasty is set $env:VISUAL = 'vim.exe' and then edit the whole thing inside vim proper...

I'm even using the wasavi extension for chrome and editing this comment inside a vim-like editor. Yes, I'm sad... ๐Ÿ˜‰

springcomp commented 3 years ago

Iโ€™m working on this issue.

This will probably need to be broken up into several pull requests. This is how I see tackling this subject in order:

I donโ€™t see the immediate value for other more arcane text objects ๐Ÿ˜„.

belotn commented 2 years ago

Hello,

I worked on some custom key handler for ci, ca, di and da as it really make editing more fluent. At the moment I only address ' " ( [ {

https://gist.github.com/belotn/538be5504b858c95890893b189720592

`Set-PSReadLineKeyHandler -Chord "c,i" -ViMode Command -ScriptBlock { VIChangeInnerBlock } Set-PSReadLineKeyHandler -Chord "c,a" -ViMode Command -ScriptBlock { VIChangeOuterBlock } Set-PSReadLineKeyHandler -Chord "d,i" -ViMode Command -ScriptBlock { VIDeleteInnerBlock } Set-PSReadLineKeyHandler -Chord "d,a" -ViMode Command -ScriptBlock { VIDeleteOuterBlock }

######################################################################

Section Function

######################################################################

function VIChangeInnerBlock(){ $quotes = @{ "'" = @("'","'"); '"'= @('"','"'); "(" = @('(',')'); "{" = @('{','}'); "[" = @('[',']') } $quote = ([Console]::ReadKey($true)).KeyChar if( $quotes.ContainsKey($quote.toString())){ $Line = $Null $Cursor = $Null

            [ref]$Cursor)
    $OpeningQuotes = $quotes[$quote.ToString()][0]
    $ClosingQuotes = $quotes[$quote.ToString()][1]
    $EndChar=$Line.indexOf($ClosingQuotes, $Cursor)
    $StartChar=$Line.LastIndexOf($OpeningQuotes, $Cursor) + 1
    if($StartChar -eq 0 -or $EndChar -eq -1){
        Return
    }
    [Microsoft.PowerShell.PSConsoleReadLine]::Replace($StartChar,`
                $EndChar - $StartChar, '')
    [Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($StartChar)
    [Microsoft.PowerShell.PSConsoleReadLine]::ViInsertMode()
}

}

function VIDeleteInnerBlock(){ $quotes = @{ "'" = @("'","'"); '"'= @('"','"'); "(" = @('(',')'); "{" = @('{','}'); "[" = @('[',']') } $quote = ([Console]::ReadKey($true)).KeyChar if( $quotes.ContainsKey($quote.toString())){ $Line = $Null $Cursor = $Null

            [ref]$Cursor)
    $OpeningQuotes = $quotes[$quote.ToString()][0]
    $ClosingQuotes = $quotes[$quote.ToString()][1]
    $EndChar=$Line.indexOf($ClosingQuotes, $Cursor)
    $StartChar=$Line.LastIndexOf($OpeningQuotes, $Cursor) + 1
    if($StartChar -eq 0 -or $EndChar -eq -1){
        Return
    }
    [Microsoft.PowerShell.PSConsoleReadLine]::Replace($StartChar,`
                $EndChar - $StartChar, '')
    [Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($StartChar)
}

}

function VIChangeOuterBlock(){ $quotes = @{ "'" = @("'","'"); '"'= @('"','"'); "(" = @('(',')'); "{" = @('{','}'); "[" = @('[',']') } $quote = ([Console]::ReadKey($true)).KeyChar if( $quotes.ContainsKey($quote.toString())){ $Line = $Null $Cursor = $Null

            [ref]$Cursor)
    $OpeningQuotes = $quotes[$quote.ToString()][0]
    $ClosingQuotes = $quotes[$quote.ToString()][1]
    $EndChar=$Line.indexOf($ClosingQuotes, $Cursor) + 1
    $StartChar=$Line.LastIndexOf($OpeningQuotes, $Cursor)
    if($StartChar -eq -1 -or $EndChar -eq -1){
        Return
    }
    [Microsoft.PowerShell.PSConsoleReadLine]::Replace($StartChar, `
            $EndChar - $StartChar, '')
    [Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($StartChar)
    [Microsoft.PowerShell.PSConsoleReadLine]::ViInsertMode()
}

}

function VIDeleteOuterBlock(){ $quotes = @{ "'" = @("'","'"); '"'= @('"','"'); "(" = @('(',')'); "{" = @('{','}'); "[" = @('[',']') } $quote = ([Console]::ReadKey($true)).KeyChar if( $quotes.ContainsKey($quote.toString())){ $Line = $Null $Cursor = $Null

            [ref]$Cursor)
    $OpeningQuotes = $quotes[$quote.ToString()][0]
    $ClosingQuotes = $quotes[$quote.ToString()][1]
    $EndChar=$Line.indexOf($ClosingQuotes, $Cursor) + 1
    $StartChar=$Line.LastIndexOf($OpeningQuotes, $Cursor)
    if($StartChar -eq -1 -or $EndChar -eq -1){
        Return
    }
    [Microsoft.PowerShell.PSConsoleReadLine]::Replace($StartChar, `
            $EndChar - $StartChar, '')
    [Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($StartChar)
}

}`

Regards, Nicolas