 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Gehn
Joined: 02 Mar 2005 Posts: 13 Location: Terminus of Tears
|
Posted: Wed Mar 02, 2005 11:47 pm Post subject: Custom text wrapping script |
|
|
While working on creating a GUI for a bigger project, I found that neither text nor edit elements really wrapped like how I wanted them to for the situation. Then, I got the idea to design a wrapping system of my own, that manually put in newline statements. The prototype was successful, so I made this - a better designed and more feature complete version. Its header explains its usage.
Text Wrapper.ahk
| Code: |
; AutoHotkey Version: 1.0.29
; Language: English
; Platform: Windows XP
; Author: Gehn WillowGlade <gehnofsol@bigfoot.com>
;
; Script Function:
; Wraps text manually by adding in newline statements to a string using
; a configurable methodology. Configuration is done by setting specific
; variables, detailed below. Settings are remembered between calls. Most
; variables have a default and hence do not absolutely require setting.
; Text is wrapped by breaking the lines as long as possible, at certain
; 'break characters' defined in sets. These sets have priority, starting
; at 1. Wrap Text will attempt to break the line using set 1, and if it
; fails, it will continue on to set 2, and so forth, until it runs out of
; sets. The result is that it will prefer wrapping very short lines to
; wrapping at lower priority break characters.
;
; Variables:
; textToWrap - The text to be wrapped. No default.
; maxCharactersPerLine - The number of characters that are allowed
; on a line before a wrap is attempted. This
; setting defaults to 80.
; breakType - This can be set to either 'after', 'before'
; or 'eat'. 'after' will have lines break after
; the break character. 'before' will have the
; lines break before the break character. 'eat'
; will destroy the break character entirely.
; This setting defaults to 'after'.
; breakCharacterSet[*] - A set of individual characters which all
; have the same priority, starting at 1. Do
; not include spaces unless you want space to
; be a break character. Use a blank set to end
; the set list.
; breakCharacterSet[*]_type - This allows the break type to be set on a per
; break character set basis. This setting
; defaults to the breakType setting.
; forceWrap - This will force wrapping of the text, even if
; no break characters are found. In such a case
; the line will break right at the limit. Set
; this option using true or false. The default
; is false.
; wrappedText - This variable is not set. Instead, this is the
; text, wrapped, returned by Wrap Text.
;
; Example:
; textToWrap := "C:\Games\Guild Wars\GW.exe"
; maxCharactersPerLine := 10
; breakCharacterSet[1] := "\"
; breakCharacterSet[2] := " "
; breakCharacterSet[3] := ""
; Gosub , WrapText
;
; wrappedText would be: "C:\Games\`nGuild`nWars\`nGW.exe"
; Invoked externally to perform core function
WrapText:
{
Gosub , WrapText_Initialize
If ErrorLevel <> 0
Return
Gosub , WrapText_BreakIntoLines
Gosub , WrapText_CombineLines
Return
}
; Makes sure all variables are user set or filled with defaults (where applicable)
WrapText_Initialize:
{
If ( textToWrap = "" )
{
MsgBox , 48 , WrapText Error , The variable 'textToWrap' must be set when WrapText is called.
ErrorLevel := 1
Return
}
If ( maxCharactersPerLine = "" )
{
maxCharactersPerLine := 80
}
Else If maxCharactersPerLine is not integer
{
MsgBox , 48 , WrapText Error , The variable 'maxCharactersPerLine' must be a positive, nonzero integer.
ErrorLevel := 1
Return
}
Else If ( maxCharactersPerLine <= 0 )
{
MsgBox , 48 , WrapText Error , The variable 'maxCharactersPerLine' must be a positive, nonzero integer.
ErrorLevel := 1
Return
}
If ( breakType = "" )
{
breakType := "after"
}
Else If ( !( breakType = "after" OR breakType = "before" OR breakType = "eat" ) )
{
MsgBox , 48 , WrapText Error , The variable 'breakType' may only be set to 'after', 'before' or 'eat'.
ErrorLevel := 1
Return
}
If ( breakCharacterSet[1] = "" )
{
breakCharacterSet[1] := " "
}
Loop
{
If ( breakCharacterSet[%a_index%] == "" )
Break
If ( !( breakCharacterSet[%a_index%]_breakType = "" OR breakCharacterSet[%a_index%]_breakType = "after" OR breakCharacterSet[%a_index%]_breakType = "before" OR breakCharacterSet[%a_index%]_breakType = "eat" ) )
{
MsgBox , 48 , WrapText Error , The variable 'breakCharacterSet[%a_index%]_breakType' may only be set to 'after', 'before' or 'eat'.
ErrorLevel := 1
Return
}
}
If ( forceWrap = "" )
{
forceWrap := false
}
Else If ( !( forceWrap = true OR forceWrap = false ) )
{
MsgBox , 48 , WrapText Error , The variable 'forceWrap' must be either true or false.
ErrorLevel := 1
Return
}
Return
}
; Breaks the text into lines, as needed
WrapText_BreakIntoLines:
{
; Chop off the ends of lines, to create new lines, until all lines are under the character limit
WrapText_line[1] := textToWrap
WrapText_lineCount := 1
Loop
{
WrapText_currentLineNumber := a_index
StringLen , WrapText_currentLineLength , WrapText_line[%WrapText_currentLineNumber%]
If ( WrapText_currentLineLength <= maxCharactersPerLine )
Break
Else
{
; Loop through break character sets until a break character is found, or we run out of sets
WrapText_breakCharacterPosition := -1
Loop
{
; Search backwards from farthest possible character to find a break character
WrapText_currentBreakCharacterSet := a_index
If ( ( WrapText_breakCharacterPosition >= 0 ) OR ( ( breakCharacterSet[%WrapText_currentBreakCharacterSet%] = "" ) AND !forceWrap ) )
Break
If ( ( breakCharacterSet[%WrapText_currentBreakCharacterSet%] = "" ) AND forceWrap )
WrapText_forceWrapThisLine := true
Else
WrapText_forceWrapThisLine := false
If ( breakCharacterSet[%WrapText_currentBreakCharacterSet%]_breakType != "" )
WrapText_currentBreakType := breakCharacterSet[%WrapText_currentBreakCharacterSet%]_breakType
Else
WrapText_currentBreakType := breakType
If ( WrapText_currentBreakType = "after" )
WrapText_currentPosition := maxCharactersPerLine
Else
WrapText_currentPosition := maxCharactersPerLine + 1
Loop , %maxCharactersPerLine%
{
If ( WrapText_forceWrapThisLine )
WrapText_breakCharacterPosition := 1
Else
{
StringMid , WrapText_characterAtCurrentPosition , WrapText_line[%WrapText_currentLineNumber%] , WrapText_currentPosition , 1
StringGetPos , WrapText_breakCharacterPosition , breakCharacterSet[%WrapText_currentBreakCharacterSet%] , %WrapText_characterAtCurrentPosition%
}
If ( WrapText_breakCharacterPosition >= 0 )
{
WrapText_lineCount += 1
If ( WrapText_currentBreakType = "after" )
{
StringTrimLeft , WrapText_line[%WrapText_lineCount%] , WrapText_line[%WrapText_currentLineNumber%] , WrapText_currentPosition
StringLeft , WrapText_line[%WrapText_currentLineNumber%] , WrapText_line[%WrapText_currentLineNumber%] , WrapText_currentPosition
}
Else If ( WrapText_currentBreakType = "before" )
{
StringTrimLeft , WrapText_line[%WrapText_lineCount%] , WrapText_line[%WrapText_currentLineNumber%] , WrapText_currentPosition - 1
StringLeft , WrapText_line[%WrapText_currentLineNumber%] , WrapText_line[%WrapText_currentLineNumber%] , WrapText_currentPosition - 1
}
Else ; WrapText_currentBreakType = "eat"
{
StringTrimLeft , WrapText_line[%WrapText_lineCount%] , WrapText_line[%WrapText_currentLineNumber%] , WrapText_currentPosition
StringLeft , WrapText_line[%WrapText_currentLineNumber%] , WrapText_line[%WrapText_currentLineNumber%] , WrapText_currentPosition - 1
}
Break
}
WrapText_currentPosition -= 1
}
}
}
}
Return
}
; Recombines the text into a single variable
WrapText_CombineLines:
{
wrappedText := ""
Loop , %WrapText_lineCount%
{
WrapText_currentLine := WrapText_line[%a_index%]
wrappedText := wrappedText "`n" WrapText_currentLine
}
StringTrimLeft , wrappedText , wrappedText , 1
Return
}
|
I'm mostly happy with the result. It seems fully functional - if anybody spots a bug please let me know. Any other comments would be nice too - this is the first time I've actually put out any code for public display and I imagine I could use some feedback.
However, there's three layers of looping in the WrapText_BreakIntoLines function however, and combined with the ifs in said section, there's a bit more nesting than I'd like. It makes the code less clear than it could be. I considered, and am still considering, moving some of the code from WrapText_BreakIntoLines into other functions. That could make the function much clearer in some ways, but then you'd have even more variables crossing functions and more function call overhead. Thoughts on this issue would be appreciated.
Edit: I apologize that some of the lines are really long, it makes the formatting here (and in any text editor you may paste it into) rather ugly. _________________ The dumber people think you are, the more surprised they're going to be when you kill them. |
|
| Back to top |
|
 |
jonny
Joined: 13 Nov 2004 Posts: 3004 Location: Minnesota
|
Posted: Thu Mar 03, 2005 12:06 am Post subject: |
|
|
Your sig is awesome.
A witty sig and a few good scripts will get you anything in this forum.  |
|
| Back to top |
|
 |
Gehn
Joined: 02 Mar 2005 Posts: 13 Location: Terminus of Tears
|
Posted: Thu Mar 03, 2005 2:55 am Post subject: |
|
|
Unfortunately, I can't take credit for my signature. It's a quote from William Clayton. _________________ The dumber people think you are, the more surprised they're going to be when you kill them. |
|
| Back to top |
|
 |
observer_420 Guest
|
Posted: Sun Mar 06, 2005 5:05 pm Post subject: filtering text through arbitrary unix (cygwin) filters |
|
|
Heh... if you have Cygwin installed (and what a wonderful way to get Unix commands in your Windows box!), you can use the fmt(1) command to wrap your text in default and optional ways.
| Code: |
;
; AutoHotkey Version: 1.x
; Language: English
; Platform: Win9x/NT
; Author: Doug Snead
;
; Script Function:
; filter text through arbitrary unix (cygwin)
; stdin/stdout filters (in perl)
;
menu tray, tip, HotKey: windows t`r`nfilter selected text
TMPDIR = C:\cygwin\tmp ; = /tmp in cygwin installation
TMPFILEIN = %TMPDIR%\filtr_in.tmp ; = /tmp/filtr_in.tmp, _out.tmp
TMPFILEOUT = %TMPDIR%\filtr_out.tmp
BINDIR = C:\cygwin\bin ; of sh(1) executable
Command = fmt ; default filter command
;;
;; run selected text through a Unix filter (stdin/stdout) command
;;
#t:: ;; = the Windows key and the t key together
saveClipBoard = %clipboard%
Send, ^c ;; copy selected text into clipboard
FileAppend, %clipboard%, %TMPFILEIN%
InputBox, Command, select stdio filter, unix filter command:,,350,150,,,,,%Command%
if ErrorLevel = 0
{
TrayTip, running:, %Command%, 120, 16
RunWait, %BINDIR%\sh.exe -c "dos2unix </tmp/filtr_in.tmp | %Command% | unix2dos >/tmp/filtr_out.tmp",,Hide
TrayTip
FileRead, clipboard, %TMPFILEOUT%
Send, ^v ;; paste processed text back in
FileDelete, %TMPFILEOUT%
}
clipboard = %saveClipBoard%
saveClipBoard =
FileDelete, %TMPFILEIN%
return
|
That script should work from any windows application that allows Ctl v copy and Ctl v paste operations.
Use the unix tidy command to reformat html, etc. |
|
| Back to top |
|
 |
fsnow55
Joined: 08 Jun 2006 Posts: 19
|
Posted: Tue Jun 20, 2006 4:15 pm Post subject: |
|
|
Hopefully, the last person to post the cygwin filter script will reply, or somebody that knows will reply:
This script looks like it matches my need but
I did not get any useful output from this script. Perhaps the problem is with the quotes here?
RunWait, %BINDIR%\sh.exe -c "dos2unix </tmp/filtr_in.tmp | %Command% | unix2dos > /tmp/filtr_out.tmp",,Hide
I tried different combinations of quoting but can not get output to /tmp/filtr_out.tmp (it never got created).
I think the problem is with the %Command% variable in the string.
BTW, this works:
RunWait, %BINDIR%\sh.exe -c "echo haha > /tmp/haha.txt"
Appreciate your help. |
|
| Back to top |
|
 |
evl
Joined: 24 Aug 2005 Posts: 1239
|
Posted: Tue Jun 20, 2006 5:06 pm Post subject: |
|
|
Maybe using 2 quoteded sections would work (so the variable isn't enclosed):
| Code: | | "dos2unix </tmp/filtr_in.tmp | " %Command% " | unix2dos > /tmp/filtr_out.tmp",, |
|
|
| Back to top |
|
 |
fsnow55
Joined: 08 Jun 2006 Posts: 19
|
Posted: Tue Jun 20, 2006 7:07 pm Post subject: |
|
|
Thanks. I found out the problem isn't with the quotes but that I have to fully qualify all the cygwin commands e.g. this works:
RunWait, %BINDIR%\sh.exe -c "/usr/bin/dos2unix </tmp/filtr_in.tmp | %Command% | /usr/bin/unix2dos > /tmp/filtr_out.tmp",,Hide
and in the popup, I type the full path for the command e.g. /usr/bin/fmt -w 20
I'm new to cygwin, so need to find out how to "auto-source" the path so XP/AHK can understand it. |
|
| Back to top |
|
 |
fsnow55
Joined: 08 Jun 2006 Posts: 19
|
|
| Back to top |
|
 |
Kudos
Joined: 21 Aug 2006 Posts: 20
|
Posted: Sat Oct 07, 2006 3:45 pm Post subject: thanks |
|
|
Gehn, thanks for this - it was very helpful to me!  |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|