Page 2 of 2

Posted: Tue Jan 25, 2005 2:52 pm
by lionelb
Having though a bit about the issues raised in this thread, I'd like to propose the following specific enhancements:

*) Implement $Stdin and $Stdout "pseudo parameter macros" for user tools ("pseudo" because, like $Clip, they do not supply command-line arguments). $Stdin would cause cause the currently selected text (which may be multi-line) to be directed to the standard input of the specified tool (rather than delivered as a command-line parameter like $Sel). $Stdout would replace the current selection with the standard output of the tool (with no selection specified, $Stdout could simply insert the output at the cursor). $Stdin and $Stdout could be used in conjunction for simple "stdin/stdout" Unix-style filters.

*) Allow tools to be chained via pipes; thus a tool Command could be specified as eg. tool1.exe | tool2.exe | ..., with the obvious effect.

Any thoughts?

Posted: Wed Feb 02, 2005 6:50 pm
by Jslay
Any thoughts?
Brilliant! I would make great use of this feature! How do we get it implemented?

J.

Posted: Wed Mar 02, 2005 7:18 pm
by Jslay
Bump.

Is this enhancement actually being considered by TextPad development? It could be a very, very powerful feature.

J.

Posted: Fri Mar 18, 2005 2:40 am
by jumpfroggy
lionelb: Please post the C code you have. Along with $clip, this could be a simple framework to do this "text filter" stuff without waiting for helios.

How about a wrapper program? Called from the tools menu, "wrapper.exe" with parameters "filter.exe $Clip" which would call filter.exe, pipe $clip into the stdin, grab the stdout, put that back into the clipboard, and paste into textpad. This would clobber the clipboard again with the changed text, but for a lot of filters I think this would be ok. How about it?

This would give us flexibility to make all our filters in any language, just use stdin and stdout. Anyone see any problems or caveats? Would anyone else use it?

Either case, please post the C code.

Posted: Fri Mar 18, 2005 12:20 pm
by lionelb
lionelb: Please post the C code you have. Along with $clip, this could be a simple framework to do this "text filter" stuff without waiting for helios.
Ok. It's far from perfect, though: http://lionelb.allmail.net/tpfilter.zip (let me know if that link doesn't work).
How about a wrapper program? Called from the tools menu, "wrapper.exe" with parameters "filter.exe $Clip" which would call filter.exe, pipe $clip into the stdin, grab the stdout, put that back into the clipboard, and paste into textpad. This would clobber the clipboard again with the changed text, but for a lot of filters I think this would be ok. How about it?
The posted code does something pretty much like that in a rather clunky way; main difference is it's actually several separate programs and the piping happens in a DOS batch file (I would do it all in one program if I could figure out how to do pipes in Windows :? ).

Let us know what you think.

Posted: Sat Mar 19, 2005 1:36 am
by Jslay
Thanks, lionelb. I've DL'd and I'll play with the files.

The code I write is usually perl (or awk), not C. Micro$oft seems to think that stdin and stdout are BATCH files (can't deal with 'em outside of .bat's...means I have to write .bat wrappers for my scripts, anyway). I suppose, if you consider the commandline obsolete, it makes sense?

J.

Posted: Sat Mar 19, 2005 11:15 pm
by ben_josephs
What do you mean? You don't use the names stdin and stdout on the command line or in a .bat file. You manipulate them using redirection and piping. For example, the following, entered on a cmd.exe command line, do exactly what I would expect them to do:

Code: Select all

dir | sort > dir.out
sort < \boot.ini
The command line is certainly not obsolete. It's what serious developers use to get much of their work done efficiently. It's just that Microsoft's various apologies for command line processors are so primitive as to be barely usable. If you want a useful one, try 4NT, a replacement for cmd.exe from JP Software (http://jpsoft.com), or one of the many unix-style ones, such as bash from Cygwin (http://www.cygwin.com/).

Posted: Sun Aug 28, 2005 8:19 pm
by noah
lionelb wrote:Having though a bit about the issues raised in this thread, I'd like to propose the following specific enhancements:

*) Implement $Stdin and $Stdout "pseudo parameter macros" for user tools ("pseudo" because, like $Clip, they do not supply command-line arguments).
Simple. I only suggest that this feature should be a checkbox option instead of a pseudo parameter -- just like "Capture Output" and "Run Minimized", etc. I never liked the $Clip pseudo parameter. It would make more sense as checkbox option.

The pseudo parameter is a conceptual mistake. The tool process never sees then, so they are not really parameters. Instead the pseudo parameter changes an option, which is what the checkboxes already do.

Yours,
Noah

Posted: Tue Apr 18, 2006 3:10 pm
by jofficer
I read through the end of this thread, and it seems that about a year ago, work was progressing, but then all of a sudden nothing.

Is this feature still something that is desired, or has it been implemented and I cannot find the function?

Posted: Wed Apr 19, 2006 9:36 pm
by jumpfroggy
It just kinda died. I'm pretty sure there's nothing in the latest version, 4.7.3, released almost 2 years ago. This says a few things: 1) textpad is incredibly stable and mature to keep people using it for 2 years without need for patches, 2) we cannot count on any changes of features in a reasonable timeframe and 3) the entire program may be a maintenance-only kinda thing for Helios.

This feature (a way to do better macros & filters via piping) is still very much needed, but the reason I haven't done much about it is that I've just learned to cope. I use macros, I use snippets. For most of the things I want piping for, I use regex's (so powerful, just tedious to type in every time).

The bottom line is that I really want more helpful tools in Textpad. The plain editing, indenting, keyboard shortcuts, regex's, and macros are unequaled in any other program. Unfortunately, it also stops there. The syntax/highlighting is rudimentary at best, really fails on any complex language. There is no auto-help (intellisense), no auto-complete, functional but not too powerful macros, basically nothing an IDE would give you. I want filtering and piping to try to replace some of that, but at some point you're just rebuilding a huge manually-operated IDE onto a text editor. Use netbeans and you can see how helpful a real IDE can be, vs a text editor like Textpad.

Don't get me wrong, textpad is still good. I have netbeans and textpad both open, I do most of my things in netbeans and do the hard regex/macro stuff in textpad. But for me, textpad is a dead end. I cannot count on them fixing the little nagging bugs (that have been evident for almost 2 years now), let alone adding really helpful new features into textpad. I'm looking into HTMLkit, Netbeans, and other IDE's to really sink into, and when I can find something that works I'll dump textpad. It's great, but it's no longer growing and I need something more.

That being said, I may try to jump back into this just for curiousity's sake. It'd be great to have a filter that could do just about anything you want. Imagine, build a perl script to auto format anything into anything else (list of properties into getters/setters, or pull all the comments out, properly format, etc) and bind it to a hotkey. Powerful. We'll see.

Anyone else still need/want this?

Posted: Wed Apr 19, 2006 10:23 pm
by ben_josephs
I do this via the clipboard. See my post in http://forums.textpad.com/viewtopic.php?t=7021.

Below is a script I use to align the selected text vertically at symbols that are specified literally or as regular expressions. The script uses the clipboard, but it saves the clipboard contents before it begins and restores them afterwards. This isn't an ideal method of communication between an application and a script, but it does the job.

I have two tools that use this script:

Align (plain)
Command: C:\Perl\bin\wperl.exe
Parameters: C:\path\to\align.clip.pl -s -p $prompt(Strings to be aligned [default: "= ;"])
Align (regex)
Command: C:\Perl\bin\wperl.exe
Parameters: C:\path\to\align.clip.pl -s -r $prompt(Strings to be aligned [default: "= ;"])
The program wperl.exe is from the ActiveState Perl distribution (http://www.activestate.com/Products/ActivePerl/). It's just like perl.exe, except for one bit of one byte. This causes it not to create a console (which is of use in this context only for debugging).

( Actually, the version I use is slightly different from this. I found that sometimes the response was a bit sluggish, especially in the presence of an overenthusiastic corporate anti-virus program. So I have another script that acts as a server. It loads all the required modules just once and sits in the background handling its clients' scripts as they are sent to it. The details of the communication with the server are entirely hidden from the client. The client simply passes the file name of the script to (yet) another script, which sends that file name to the server by named pipe. )

Here is align.clip.pl:

Code: Select all

#! /usr/local/bin/perl

##########################################################################################
#
# align.clip.pl
#
# TextPad macro.
# Aligns selected text at specified symbols.
# The symbols can be specified literally or as matches to regular expressions.
# The alignment can be squeezed to any given minimum.
# The clipboard is used, but is left as it was.
#
# Options
#   -r      Symbols are represented as regular expressions
#   -r-     Symbols are represented literally (default)
#   -sN     White space preceding a symbol should be squeezed to a minimum of N spaces
#   -s      = -s1 (default)
#   -s-     White space preceding a symbol should not be squeezed
#   -z      Reselect the selection (default)
#   -z-     Don't reselect the selection
#
# Parameters
#   sym...  the symbols to align
#
# Examples
#
#   Default; minimum number of spaces before an aligned symbol is squeezed to 1:
#     align.clip.pl
#       $a=42;
#       $abcd=567;
#       $abc=56789;
#     ->
#       $a    =42    ;
#       $abcd =567   ;
#       $abc  =56789 ;
#
#   Minimum number of spaces before an aligned symbol is squeezed to 0:
#     align.clip.pl -s0
#       $a =42 ;
#       $abcd =567 ;
#       $abc =56789 ;
#     ->
#       $a   =42   ;
#       $abcd=567  ;
#       $abc =56789;
#
#   Spaces before aligned symbols are not squeezed; each symbol is aligned to its
#   existing rightmost position (relative to the position of any preceding symbol):
#     align.clip.pl -s-
#       $a   =42;
#       $abcd  =567;
#       $abc =56789;
#     ->
#       $a     =42   ;
#       $abcd  =567  ;
#       $abc   =56789;
#
#   Regular expressions
#     align.clip.pl [!=] [ms]?/ ;
#       $a=~/42/;
#       $ab=~m/56/;
#       $abcd!~s/42/;
#     ->
#       $a    =~ /42/  ;
#       $ab   =~ m/56/ ;
#       $abcd !~ s/42/ ;
#
##########################################################################################


use warnings ;
use strict   ;

use Win32::Clipboard               ;
use Win32::GuiTest qw ( SendKeys ) ;
use Win32::GUI                     ;


##########################################################################################
#
# Forward declaration
#
sub diddle ( $$$$ ) ;


##########################################################################################
#
# main
#
{
  ######################################################################################
  #
  # Handle options
  #
  my $regOpt = 'r' ;
  my $sqzOpt = 's' ;
  my $resOpt = 'z' ;

  my %opts ;

  while ( @ARGV > 0 && ( substr $ARGV[ 0 ], 0, 1 ) eq '-' && length $ARGV[ 0 ] > 1 )
  { $opts{ substr $ARGV[ 0 ], 1, 1 } = substr $ARGV[ 0 ], 2 ;
    shift ;
  }

  my $isRegex = defined $opts{ $regOpt } && $opts{ $regOpt } ne '-' ;
  my $sqzWid  = $opts{ $sqzOpt } ;
  $sqzWid =   ! defined $sqzWid || $sqzWid eq '-' ? undef
            : $sqzWid !~ /^[0-9]+$/               ? 1
            :                                       $sqzWid ;
  my $resel   = ! defined $opts{ $resOpt } || $opts{ $resOpt } eq '' ;


  ######################################################################################
  #
  # Handle arguments
  #
  my $rSyms = @ARGV ? \@ARGV : [ '=', ';' ]  ; # get args (default: ('=', ';'))


  ######################################################################################
  #
  # Do it
  #
  my $clip   = Win32::Clipboard                ; # fetch the clipboard

  # Save current contents of clipboard
  #
  my $oldSel = $clip->GetText || ''            ; # fetch current clipboard text

  # Fetch the selected text, align it, copy it over selection (via clipboard both ways)
  #
  SendKeys "^c"                                ; # copy selection to clipboard
  my $text   = $clip->GetText || ''            ; # fetch clipboard text
  my $isBlck = $clip->GetAs ( 49908 )          ; # fetch block mode indicator

  if ( ! $isBlck )
  {
    my ( $nLines, $tixt ) =
      diddle $rSyms, \$text, $isRegex, $sqzWid ; # diddle the text
    $clip->Set ( $tixt )                       ; # set clipboard to diddled text
    SendKeys "^v"                              ; # paste it over the selection
    ( $resel ) and
      SendKeys "+{Up $nLines}", 0              ; # reselect the selection
  }
  else
  {
    Win32::GUI::MessageBox 0, "The editor is in block select mode.\n" .
                              "This action would bugger the text,\n"  .
                              "so I won't perform it"
                            , "align.clip.regex", MB_OK ;
  }

  # Restore contents of clipboard
  #
  $clip->Set ( $oldSel )                       ; # restore clipboard text
}


##########################################################################################
#
# diddle
#
# Params
#   $rSyms    ref to array of symbols to align
#   $rText    ref to text to be diddled
#   $isRegex  symbols are regexes; o.w. they're literal
#   $sqzWid   alignment is adjusted so min num spaces before a symbol is $sqzWid
# Result
#   @         ( num_lines, diddled_text )
#
# Takes the text referred to by $rText and adds spaces to align occurrences of the
# symbols in the list referred to by $rSyms.
# If $isRegex, the symbols are regex matches; o.w. they're literal.
# If $sqzWid is defined, min num spaces before an aligned symbol is squeezed to $sqzWid.
#
sub diddle ( $$$$ )
{
  my ( $rSyms, $rText, $isRegex, $sqzWid ) = @_ ;

  my @text   = split /\n/, $$rText ;                  # the text as an array of lines
  my $nLines = @text               ;                  # num lines of text
  my $rePre  = ''                  ;                  # anchor all searches to beginning

  for my $sym ( @$rSyms )                             # for each symbol in turn
  {
    if ( ! $isRegex )
    { $sym =  "\Q$sym\E"                              # quote regex special characters
    }
    else
    { $sym =~ s/(^|[^\\])[(]([^?]|$)/$1(?:$2/g ;      # make all parentheses non-capturing
      $sym =~ s/(^|[^\\])[\$]/$1\\r?\$/g       ;      # make all anchor '$'s accept
    }                                                 #   preceding "\r"s

    my $pos   = 0 ;                                   # aligned position of current symbol
    my @pairs ;                                       # a (lhs, rhs) pair for each line

    my $re = qr/^((?:$rePre)?.*?[^ ]?)( *)($sym.*)/ ; # regex for next split

    for my $line ( @text )                            # run over the entire text
    {
      # Split the current line at the current symbol.

      my ( $lhs, $pad, $rhs ) = $line =~ $re ;        # split the line before the symbol

      defined $lhs or $lhs ||= $line ;                # in case the symbol
      defined $pad or $pad ||= ''    ;                #   or while space
      defined $rhs or $rhs ||= ''    ;                #   wasn't found

      ( defined $sqzWid && $rhs ) and
        $pad = ' ' x $sqzWid ;

      $lhs .= $pad ;

      my $len = length $lhs ;

      ( $rhs ) and                                    # adjust position of symbol
        $pos = $len > $pos ? $len : $pos ;            #   as necessary

      push @pairs, [ $lhs, $rhs ] ;
    }

    # Now we know the required alignment position of the current symbol.
    # Overwrite the array of lines with lines in which the symbol is aligned.

    @text = () ;

    for my $rPair ( @pairs )
    {
      my ( $lhs, $rhs ) = @$rPair ;
                                                      # stick the line back together
      push @text, $rhs ? sprintf "%-${pos}s%s", $lhs, $rhs : $lhs ;
    }

    $rePre = "(?:$rePre)?.*?$sym" ;                   # parentheses must be non-capturing;
                                                      # previous symbols are optional
  }

  ( $nLines, join "\n", @text ) ;
}
Edit: Corrected link.