Samstag, 20. November 2010

Eval-Selection in ISE editor, result in editor pane

Here is a little demo showing, who to use ISEs editor pane to display untruncated, unwrapped results.

Run the script in ISE.
Open a new editor.
Tpye dir and press F7:



            
            
function Eval-Selection            
{            
    # Bernd Kriszio 2010-11-21            
    # http://pauerschell.blogspot.com/            
    # twitter @bernd_k            
                
                    
    $editor = $psise.CurrentFile.Editor            
            
    if ($editor.SelectedText)            
    {            
        $inputScript = $editor.SelectedText            
        $editor.InsertText('')            
        $editor.InsertText($inputScript)            
        $result = Invoke-expression $inputScript | out-String            
        $editor.insertText("`r`n")            
        $editor.InsertText($result)            
            
    }            
    else            
    {            
        $inputScript = $editor.Text            
        $EndLine =  $editor.LineCount             
        $EndColumn = $editor.GetLineLength($EndLine) + 1            
        $editor.SetCaretPosition($EndLine, $EndColumn)            
        $result = Invoke-expression $inputScript | out-String            
        $editor.insertText("`r`n")            
        $editor.InsertText($result)            
    }            
}                    
                    
             
$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Eval-Selection", {Eval-Selection} ,  'f7')

Edited
After playing a while, I modified the rules for the case, when nothing is selected. Now I use just the single line, the caret is in. Further I added the -width 1000 parameter to make it realy an improvement about usual output-pane results.

And I have a lot of crazy ideas, what to do if the caret is in an empty line. I don't implement them. Next month I wouldn't remember them myself.

Keep things simple

Bernd

This is the version, I added to my profile:

function Eval-Selection            
{            
    # Bernd Kriszio 2010-11-21            
    # http://pauerschell.blogspot.com/            
    # twitter @bernd_k            
                
                    
    $editor = $psise.CurrentFile.Editor            
                
    # if nothing is selected just use the line the caret is in            
    if (!$editor.SelectedText)            
    {            
        $caretLine = $editor.CaretLine            
        $caretLineEnd = $editor.GetLineLength($caretLine) + 1                
                    
        $editor.Select($caretLine, 1, $caretLine, $caretLineEnd)            
    }            
            
    # if something is selected use it.            
    if ($editor.SelectedText)            
    {            
        $inputScript = $editor.SelectedText            
        $editor.InsertText('')            
        $editor.InsertText($inputScript)            
        $result = Invoke-expression $inputScript | out-String -width 1000            
        if ($editor.CaretColumn -ne 1)            
        {            
            $editor.insertText("`r`n")            
        }            
        $editor.InsertText($result)            
            
    }            
}            

Dienstag, 16. November 2010

Determine Start and End of a Selection in PowerShell Ise

Hello, I' m just working on a new inline outpout mode for SQLPSX a very ambious project to access SQL databases based on PowerShell.

There ISEs Output pane doesn't always satisfy my needs, because it truncates and wraps output but you can put your Output into the current or new Editor panes and that works fine. Today I focus on using the current editor pane. 

My goal is to insert the output exactly at the starting of the line below the selection if there is one or at the end of the editor.

First I found it difficult to get the start and end of a selection, but than I found a clever work around. I can even determine, if a selection was done from left to right or from right to left.

But don't use this possibility. It would be really confusing.

Here is my test code, with which I designed (honestly redesigned) the logic to evaluate the output location in SQLPSX (next release).

Have fun studying it. Just put the code below it into an ISE editor, select some text (or nothing) and press F5.

Bernd


function Get-InfoAboutCurentFilesEditor            
{            
    $editor          = $psIse.CurrentFile.Editor            
    $LineCount       = $editor.LineCount            
    $CaretLine       = $editor.CaretLine            
    $caretColumn     = $editor.CaretColumn            
    $CaretLineLength = $editor.GetLineLength($CaretLine)            
    $CaretAtLineEnd  = $caretColumn -eq $CaretLineLength + 1            
    $CaretInLastLine = $CaretLine -eq $LineCount            
    $SelectedText    = $editor.SelectedText            
    $hasSelection    = $SelectedText -ne ''            
                
    if ($hasSelection)            
    {            
        # delete selected text            
        $editor.InsertText('')            
        $StartLine =  $editor.CaretLine            
        $StartColumn = $editor.CaretColumn            
        # reinsert the text            
        $editor.InsertText($SelectedText)            
        $EndLine =  $editor.CaretLine            
        $EndColumn = $editor.CaretColumn            
        # restore the selection            
        $editor.select($StartLine, $StartColumn, $EndLine, $EndColumn)             
        $reverse =  $CaretLine -eq  $StartLine -and $caretColumn -eq $StartColumn            
    }            
    else            
    {            
        $StartLine =  $EndLine = $LineCount            
        $StartColumn = $EndColumn = $editor.GetLineLength($EndLine) + 1            
        $reverse = $False            
    }            
                
    if (  $EndLine -lt  $LineCount)            
    {            
        $outputLine = $EndLine + 1            
        $outputColumn = 1            
        $NeedsNewLine = $False            
    }            
    else            
    {            
        $outputLine = $EndLine            
        $outputColumn = $EndColumn            
        if ($EndColumn -ne 1)            
        {            
            $NeedsNewLine = $True            
            $outputColumn = $editor.GetLineLength($EndLine) + 1            
        }            
        else            
        {            
            $NeedsNewLine = $False            
        }            
    }            
@"
DisplayName:     $($psIse.CurrentFile.DisplayName) 
LineCount:       $LineCount

CaretLine:       $CaretLine
CaretColumn:     $caretColumn
CaretLineLength: $CaretLineLength
CaretAtLineEnd:  $CaretAtLineEnd
CaretInLastLine: $CaretInLastLine

hasSelection:    $hasSelection
reverse:         $reverse

outputLine:      $outputLine
outputColumn:    $outputColumn
NeedsNewLine:    $NeedsNewLine
"@            
}            
            
Get-InfoAboutCurentFilesEditor

Montag, 15. November 2010

New ISE work arounds -- determine start and end of textselection

I just guess that ISE is made by some Trappist monks. One never hears anything about future versions.
At most some closed Change Request at Microsoft Commit.
I get a little tired hoping, they will release anything soon.
If I need something, I'm going to write some dirty workaround.
Current problem: you can select text within the editor from left to right or from right to left ending with the caret at different positions.
Only the holy men didn't publish the API to get the start and the end of the selection. You can query only the caret position.
What I want acchieve, is to be able to insert in the line just below the current selection.
Well the following work around sets the caret to the beginning of the selection.
Put the code into an ise editor select testa and press f5, than repeat it by selecting the tesxt in the oposite direction and press again f5:


$editor = $psise.CurrentFile.Editor            
 $currentselection = $editor.SelectedText            
 if ($currentselection)            
 {            
    $initialCaretLine = $editor.CaretLine            
    $initialCaretColumn = $editor.CaretColumn            
    $editor.InsertText('')            
    $selstartline  = $editor.CaretLine            
    $selstartColumn = $editor.CaretColumn             
    $editor.InsertText($currentselection)            
    $selEndline  = $editor.CaretLine            
    $selEndColumn = $editor.CaretColumn             
    $editor.Select($selstartline, $selstartColumn, $selEndline, $selEndColumn)            
                
    "Selection is ($selstartline, $selstartColumn, $selEndline, $selEndColumn)"            
    "Initial Caret Position ($initialCaretLine, $initialCaretColumn)"            
 }            
            
            
# testa            
# testb            



Hope this really helps

Bernd


Sonntag, 14. November 2010

I can code Bad Influenced style too

I hope there is a better way to do this, but if PowerShell enforces the use of work arounds, I'll use them.
Please, if you find something more elegant, please drop a note.

Well to make SQLPSX one of the most powerfull tools to extract data from SQL-Server or Oracle databases I just want to transform a datarow into a tabular representation.


$datarow | Format-Table -auto

seems a good start, but as described in http://poshoholic.com/2010/11/11/powershell-quick-tip-creating-wide-tables-with-powershell/

you need to pass the result to Out-String -width 10000 or as many characters you want.
Sorry can't say -1 for unlimited. (Perhaps in V3, if we cry load enough?)

Oops not all columns included, lets add -property *

$datarow | Format-Table -auto -property * | Out-String -width 10000

Oops what happens now?  At the end you get some unwanted addition columns:

RowError, RowState, Table, ItemArray,  HasErrors

A problem well described in https://connect.microsoft.com. With no work around supplied.

Go there and vote for it.

And here is the code, that gives me the wanted result. I agree, it is ugly, but its result is fine:


$columns = ''            
            
                            foreach ($i in 0.. ($res[0].Table.columns.count -1))            
                            {            
                                if ($columns) { $columns +=  ', '+ $res[0].Table.Columns[$i].ColumnName }            
                                else { $columns = $res[0].Table.Columns[$i].ColumnName}            
                            }            
            
                            $c = '($res | ft -Property ' + $columns + ' -auto | Out-string -width 10000 -stream ) -replace " *$", ""-replace "\.\.\.$", "" -join "`r`n" '            
                            $text = Invoke-expression $c            

I hope this helps

Bernd

Samstag, 13. November 2010

SQLPSX Release 2.3 is real tool for SQL-Server

Well it took some time, until Chad Miller published the current version of SQLPSX.
Concerning SQL-Server I dare say, it is a real tool to work with, with some unique features.

You get a lot of options for output format, e.g. list, which showes you the contents of the columns above each other. That helps, if you have varchar fields containing multiple lines. While the usual grid format only displays the first line and the text format looses column alignment, here you get nearly the complete content.
Nearly? Yes using ISE Output window, some wise man desided that truncating the output to current width of the Output window is what users have to want.

OK. With the limitations of the output window you have two options. First you can tweet about this last millenium decision. Second you can pray to Microsoft Connect and send a change Request for an option to programmatically set the witdth of the output pane).
Or you just ignore the two options and write a workaround.

The workaround I invented is the output format isetab. (Yes you find it in SQLPSX 2.3)
The trick is not using the Output pane for displaying the result, but to create a new editor and display it there in its whole witdh.

Working with the new mode, I soon end with lots of ofen editors and nearly as a joke to a coworker I designed the idea of an inline output format. I put the result into the calling editor, just below the calling selection or at the end, if there is none.

First trial was just 4 lines and it just felt good.

You can adjust the princip, if you have a function, which you invoke by ISE menu, which produces some wide output. Instead of sending the output to the output pane, you can use something similar to:


$text = "your code goes here>"            
         $editor = $psise.CurrentFile.Editor            
         $caretLine = $editor.CaretLine            
         $lineCount = $editor.LineCount            
         if (-not $selectedEditor.SelectedText)            
         {            
            $lineend = $editor.GetLineLength($lineCount) + 1            
            # Write-Host "Nothing Selected  Linecount: $lineCount LineEnd: $lineend"            
            if ($lineend -eq 0) {$lineend = 1}            
            # set selection to the end of the editor            
            $editor.Select($lineCount, $lineend, $lineCount, $lineend)            
         }            
         elseif ($caretLine -lt $lineCount)            
         {            
            # Write-Host "Usual case"            
            # set selection to the start of the next line            
            $editor.Select($caretLine + 1, 1, $caretLine + 1, 1)            
         }            
         else            
         {            
            $lineend = $editor.GetLineLength($lineCount) + 1            
            # Write-Host "At end  Linecount: $lineCount LineEnd: $lineend"            
            if ($lineend -eq 0) {$lineend = 1}            
            # set selection to the end of the editor            
            $editor.Select($lineCount, $lineend, $lineCount, $lineend)            
         }            
         $editor.InsertText($text)            



You can load this into an ISE editor and run it using F5. You see the line your code goes here added at the end.

Bernd