Splitting a string into multiple lines with a maximum lenght Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
Meow
Posts: 24
Joined: 21 Feb 2016, 22:48

Splitting a string into multiple lines with a maximum lenght

18 Jun 2018, 21:15

Hi,

So I'm looking to split a long string into array elements, and each element in the array can only be a maximum of x characters long.
Sounds simple enough, right?
But here's the tricky part:
I also don't want it to break up words. So it wouldn't start a new line just in the middle of a word awkwardly li
ke this.
And it also should respect newlines that were in the string already.

For an example, this thing that I am writing right now needs to be split into multiple lines, and lets say each line can be a maximum of 80 characters. So I'm going to do this manually, look below this block of text to see what I mean. Also, just to spice things up I'mWritingLikeThisJustToMakeSureThatItWouldHandleSpecialStuffAswell. ║ ┘ some special characters here as well §§§ § § § ╬ ²„² „„ ²„„ ®®® ®¾ ¾¾ ¾ test ∟¡æ◙ hel&&lo((( and here
are some

new lines, it should
respect these
aswell.

Code: Select all

For an example, this thing that I am writing right now needs to be split into 	; 77 chars
multiple lines, and lets say each line can be a maximum of 80 characters. So	; 76 chars 
I'm going to do this manually, look below this block of text to see what I		; 74 chars
mean. Also, just to spice things up												; 35 chars
I'mWritingLikeThisJustToMakeSureThatItWouldHandleSpecialStuffAswell. ║ ┘ some	; 77 chars
special characters here as well §§§ § § § ╬ ²„² „„ ²„„             ®®® ®¾ ¾¾ ¾ 	; 78 chars (yes, empty spaces, they didn't show up outside of the codeblock :L)
test ∟¡æ◙ hel&&lo((( and here													; 29 chars
are some																		; 8  chars
																				; 0  chars
new lines, it should															; 20 chars
respect these																	; 13 chars
aswell.																			; 7  chars
And yes, the character amount isn't technically correct in the last 6 lines, since I'm not accounting for the newline or linefeed or w/e characters.
But in my case I actually wouldn't be using these line breaking characters. The empty line that I marked to have 0 characters would just literally be empty.
An empty element in my array, and not consist of \n or \n\r, or whatever.

Also note that a useless empty space at the end of a line doesn't need to be preserved. It'll be of no use for me.

So yeah, I'm just having trouble implementing this logic with the AHK language.
Any help is highly appreciated,
Thanks.
User avatar
DyaTactic
Posts: 221
Joined: 04 Apr 2017, 05:52

Re: Splitting a string into multiple lines with a maximum lenght

19 Jun 2018, 14:59

This should do it:

Code: Select all

TooLong := "For an example, this thing that I am writing right now needs to be split into 	`; 77 chars"	; Note that the semi-colon need to be excaped.
ShortString := ""
MaxLen := 80
OrgiLen := StrLen(TooLong)
LastChar := 1

Loop
{
	If (LastChar >= OrgiLen)	; There are no more linefeeds to add.
		Break
	
	ShortString := ShortString . SubStr(TooLong, LastChar, MaxLen) . "`n"
	
	LastChar += MaxLen
}

MsgBox, % ShortString
Let me know how it works for you.
User avatar
Meow
Posts: 24
Joined: 21 Feb 2016, 22:48

Re: Splitting a string into multiple lines with a maximum lenght

19 Jun 2018, 15:27

DyaTactic wrote:This should do it:

Code: Select all

TooLong := "For an example, this thing that I am writing right now needs to be split into 	`; 77 chars"	; Note that the semi-colon need to be excaped.
ShortString := ""
MaxLen := 80
OrgiLen := StrLen(TooLong)
LastChar := 1

Loop
{
	If (LastChar >= OrgiLen)	; There are no more linefeeds to add.
		Break
	
	ShortString := ShortString . SubStr(TooLong, LastChar, MaxLen) . "`n"
	
	LastChar += MaxLen
}

MsgBox, % ShortString
Let me know how it works for you.
Yes, this splits at exactly 80 chars, but that wasn't what I was looking for.
This is the problem I was asking to get help for:
Meow wrote:But here's the tricky part:
I also don't want it to break up words. So it wouldn't start a new line just in the middle of a word awkwardly li
ke this.
And it also should respect newlines that were in the string already.
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Splitting a string into multiple lines with a maximum lenght

19 Jun 2018, 15:59

revised version available further below: https://autohotkey.com/boards/viewtopic ... 79#p224974

for posterity's sake, the original one:

Code: Select all

#NoEnv
#SingleInstance Force
#Persistent
SetBatchLines -1

haystack =
(LTrim Join`n
	For an example, this thing that I am writing right now needs to be split into multiple lines, and heres a new line in here,
	and lets say each line can be a maximum of 80 characters. So I'm going to do this manually, look below this block of text to see what I mean. Also, just to spice things up I'mWritingLikeThisJustToMakeSureThatItWouldHandleSpecialStuffAswell. ║ ┘ some special characters here as well §§§ § § § ╬ ²„² „„ ²„„ ®®® ®¾ ¾¾ ¾ test ∟¡æ◙ hel&&lo((( and here
	are some

	new lines, it should
	respect these
	aswell. also spaces at the end here   
)

Result := lineWrap(haystack)

Gui Display: New, +AlwaysOnTop, Results
Gui Display: Margin, 4, 4
for index, entry in Result
	res .= Format("[{}] : [{}] ({})`n", (index < 10 ? "0" index : index), entry, StrLen(entry))
Gui Display: Add, Edit, , % res
Gui Display: Show, xCenter yCenter
Return

DisplayGuiClose:
DisplayGuiEscape:
	ExitApp
Return

lineWrap(haystack) {
	static MAX_CHARS_PER_LINE := 80

	Result := []
	Lines := StrSplit(haystack, "`n")

	for each, Line in Lines
	{
		if (Line == "")
		{
			Result.Push(Line)
			continue
		}

		Words := StrSplit(Line, A_Space)

		for each, word in Words
		{
			if (StrLen(res) + StrLen(word) <= MAX_CHARS_PER_LINE)
			{
				res .= word A_Space
			}
			else
			{
				Result.Push(res)
				res := ""
			}
		}

		Result.Push(res)
		res := ""
	}

	lastElement := Result.Pop()
	Result.Push(RTrim(lastElement))

	return Result
}
Last edited by swagfag on 20 Jun 2018, 08:12, edited 1 time in total.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Splitting a string into multiple lines with a maximum lenght

19 Jun 2018, 17:48

I did something like this here, it uses InStr to find the first occurrence of a string before the nth character. To search backwards you have to convert the character index to a negative (or zero) index that InStr can handle.
Edit some text files, string length - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 69#p156069
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
Meow
Posts: 24
Joined: 21 Feb 2016, 22:48

Re: Splitting a string into multiple lines with a maximum lenght

19 Jun 2018, 19:49

swagfag wrote:

Code: Select all

#NoEnv
#SingleInstance Force
#Persistent
SetBatchLines -1

haystack =
(LTrim Join`n
	For an example, this thing that I am writing right now needs to be split into multiple lines, and heres a new line in here,
	and lets say each line can be a maximum of 80 characters. So I'm going to do this manually, look below this block of text to see what I mean. Also, just to spice things up I'mWritingLikeThisJustToMakeSureThatItWouldHandleSpecialStuffAswell. ║ ┘ some special characters here as well §§§ § § § ╬ ²„² „„ ²„„ ®®® ®¾ ¾¾ ¾ test ∟¡æ◙ hel&&lo((( and here
	are some

	new lines, it should
	respect these
	aswell. also spaces at the end here   
)

Result := lineWrap(haystack)

Gui Display: New, +AlwaysOnTop, Results
Gui Display: Margin, 4, 4
for index, entry in Result
	res .= Format("[{}] : [{}] ({})`n", (index < 10 ? "0" index : index), entry, StrLen(entry))
Gui Display: Add, Edit, , % res
Gui Display: Show, xCenter yCenter
Return

DisplayGuiClose:
DisplayGuiEscape:
	ExitApp
Return

lineWrap(haystack) {
	static MAX_CHARS_PER_LINE := 80

	Result := []
	Lines := StrSplit(haystack, "`n")

	for each, Line in Lines
	{
		if (Line == "")
		{
			Result.Push(Line)
			continue
		}

		Words := StrSplit(Line, A_Space)

		for each, word in Words
		{
			if (StrLen(res) + StrLen(word) <= MAX_CHARS_PER_LINE)
			{
				res .= word A_Space
			}
			else
			{
				Result.Push(res)
				res := ""
			}
		}

		Result.Push(res)
		res := ""
	}

	lastElement := Result.Pop()
	Result.Push(RTrim(lastElement))

	return Result
}
Oo, thanks a lot. This one is almost perfect, but it has problems with lines that is over the limit. The script loses 1 word in that case:

Code: Select all

hello hello hello hello hello hello hello hello hello hello hello1 hello2 hello3
123 123
Image

Code: Select all

hello hello hello hello hello hello hello hello hello hello hello1 hello2 hello3 hello4 hello5 hello6
123 123
Image
Last edited by Meow on 19 Jun 2018, 23:25, edited 1 time in total.
User avatar
Meow
Posts: 24
Joined: 21 Feb 2016, 22:48

Re: Splitting a string into multiple lines with a maximum lenght

19 Jun 2018, 19:51

jeeswg wrote:I did something like this here, it uses InStr to find the first occurrence of a string before the nth character. To search backwards you have to convert the character index to a negative (or zero) index that InStr can handle.
Edit some text files, string length - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 69#p156069
Thanks, I'll take a look at that.
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Splitting a string into multiple lines with a maximum lenght

20 Jun 2018, 03:08

Hi, Meow

I'm late to the party and I have knitted together this first attempt:
  • First example from OP has many tabs, not sure how to handle
  • Second example, also from OP, ignores stuff behind the semicolon
  • third example from your later post

Code: Select all

example1 =
(
For an example, this thing that I am writing right now needs to be split into 	; 77 chars
multiple lines, and lets say each line can be a maximum of 80 characters. So	; 76 chars
I'm going to do this manually, look below this block of text to see what I		; 74 chars
mean. Also, just to spice things up												; 35 chars
I'mWritingLikeThisJustToMakeSureThatItWouldHandleSpecialStuffAswell. ║ ┘ some	; 77 chars
special characters here as well §§§ § § § ╬ ²„² „„ ²„„             ®®® ®¾ ¾¾ ¾ 	; 78 chars (yes, empty spaces, they didn't show up outside of the codeblock :L)
test ∟¡æ◙ hel&&lo((( and here													; 29 chars
are some																		; 8  chars
																				; 0  chars
new lines, it should															; 20 chars
respect these																	; 13 chars
aswell.																			; 7  chars

)

example2 =
( comment
For an example, this thing that I am writing right now needs to be split into 	; 77 chars
multiple lines, and lets say each line can be a maximum of 80 characters. So	; 76 chars
I'm going to do this manually, look below this block of text to see what I		; 74 chars
mean. Also, just to spice things up												; 35 chars
I'mWritingLikeThisJustToMakeSureThatItWouldHandleSpecialStuffAswell. ║ ┘ some	; 77 chars
special characters here as well §§§ § § § ╬ ²„² „„ ²„„             ®®® ®¾ ¾¾ ¾ 	; 78 chars (yes, empty spaces, they didn't show up outside of the codeblock :L)
test ∟¡æ◙ hel&&lo((( and here													; 29 chars
are some																		; 8  chars
																				; 0  chars
new lines, it should															; 20 chars
respect these																	; 13 chars
aswell.																			; 7  chars

)

example3 =
(
hello hello hello hello hello hello hello hello hello hello hello1 hello2 hello3 hello4 hello5 hello6
123 123

)


Index := 0

ButtonNextExample:
Index ++
Gui, Destroy
Gui, Add, Text,, % Test(example%Index%)
Gui, Add, GroupBox, h3 wp
Gui, Add, Button,, Next example
Gui, Show
Return

GuiClose:
ExitApp



;-------------------------------------------------------------------------------
Test(Text) { ; top-level logic
;-------------------------------------------------------------------------------
    Loop, Parse, Text, `n, `r
        If StrLen(A_LoopField) > 80
            Result .= Splitter(A_LoopField, 80)
        Else
            Result .= A_LoopField "`n"

    Return, Result
}



;-------------------------------------------------------------------------------
Splitter(Line, Max) { ; line-by-line
;-------------------------------------------------------------------------------
    For each, Word in StrSplit(Line, A_Space)
        If Not Spitted And StrLen(Front) + StrLen(Word) < Max
            Front .= Word A_Space
        Else
            Back .= Word A_Space
            , Splitted := True

    Return, Front "`n" (Splitted ? Back "`n" : "")
}
Any good? Examples with edge cases with 79/80/81 chars would be good to decide between >80 and >=80

Edit: minor improvements and typos corrected
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Splitting a string into multiple lines with a maximum lenght  Topic is solved

20 Jun 2018, 04:31

Fixed now
User avatar
Meow
Posts: 24
Joined: 21 Feb 2016, 22:48

Re: Splitting a string into multiple lines with a maximum lenght

20 Jun 2018, 04:38

wolf_II wrote:Hi, Meow

I'm late to the party and I have knitted together this first attempt:
  • First example from OP has many tabs, not sure how to handle
  • Second example, also from OP, ignores stuff behind the semicolon
  • third example from your later post

Code: Select all

example1 =
(
For an example, this thing that I am writing right now needs to be split into 	; 77 chars
multiple lines, and lets say each line can be a maximum of 80 characters. So	; 76 chars
I'm going to do this manually, look below this block of text to see what I		; 74 chars
mean. Also, just to spice things up												; 35 chars
I'mWritingLikeThisJustToMakeSureThatItWouldHandleSpecialStuffAswell. ║ ┘ some	; 77 chars
special characters here as well §§§ § § § ╬ ²„² „„ ²„„             ®®® ®¾ ¾¾ ¾ 	; 78 chars (yes, empty spaces, they didn't show up outside of the codeblock :L)
test ∟¡æ◙ hel&&lo((( and here													; 29 chars
are some																		; 8  chars
																				; 0  chars
new lines, it should															; 20 chars
respect these																	; 13 chars
aswell.																			; 7  chars

)

example2 =
( comment
For an example, this thing that I am writing right now needs to be split into 	; 77 chars
multiple lines, and lets say each line can be a maximum of 80 characters. So	; 76 chars
I'm going to do this manually, look below this block of text to see what I		; 74 chars
mean. Also, just to spice things up												; 35 chars
I'mWritingLikeThisJustToMakeSureThatItWouldHandleSpecialStuffAswell. ║ ┘ some	; 77 chars
special characters here as well §§§ § § § ╬ ²„² „„ ²„„             ®®® ®¾ ¾¾ ¾ 	; 78 chars (yes, empty spaces, they didn't show up outside of the codeblock :L)
test ∟¡æ◙ hel&&lo((( and here													; 29 chars
are some																		; 8  chars
																				; 0  chars
new lines, it should															; 20 chars
respect these																	; 13 chars
aswell.																			; 7  chars

)

example3 =
(
hello hello hello hello hello hello hello hello hello hello hello1 hello2 hello3 hello4 hello5 hello6
123 123

)


Index := 0

ButtonNextExample:
Index ++
Gui, Destroy
Gui, Add, Text,, % Test(example%Index%)
Gui, Add, GroupBox, h3 wp
Gui, Add, Button,, Next example
Gui, Show
Return

GuiClose:
ExitApp



;-------------------------------------------------------------------------------
Test(Text) { ; top-level logic
;-------------------------------------------------------------------------------
    Loop, Parse, Text, `n, `r
        If StrLen(A_LoopField) > 80
            Result .= Splitter(A_LoopField, 80)
        Else
            Result .= A_LoopField "`n"

    Return, Result
}



;-------------------------------------------------------------------------------
Splitter(Line, Max) { ; line-by-line
;-------------------------------------------------------------------------------
    For each, Word in StrSplit(Line, A_Space)
        If Not Spitted And StrLen(Front) + StrLen(Word) < Max
            Front .= Word A_Space
        Else
            Back .= Word A_Space
            , Splitted := True

    Return, Front "`n" (Splitted ? Back "`n" : "")
}
Any good? Examples with edge cases with 79/80/81 chars would be good to decide between >80 and >=80

Edit: minor improvements and typos corrected
The comments were just for ease of understanding, and this script has a problem with lines that are more than once over the limit.
For example, this line is 230 chars long, so it's twice over the limit:

Input:

Code: Select all

hello1 hello2 hello3 hello4 hello5 hello6 hello7 hello8 hello9 hello10 hello11 hello12 hello13 hello14 hello15 hello16 hello17 hello18 hello19 hello20 hello21 hello22 hello23 hello24 hello25 hello26 hello27 hello28 hello29 hello30
Output:

Code: Select all

hello1 hello2 hello3 hello4 hello5 hello6 hello7 hello8 hello9 hello10 hello11 
hello12 hello13 hello14 hello15 hello16 hello17 hello18 hello19 hello20 hello21 hello22 hello23 hello24 hello25 hello26 hello27 hello28 hello29 hello30 

Also, in your script, in line 77, I'd assume it should be "splitted" instead of "spitted".
That didn't make a difference though.
User avatar
Meow
Posts: 24
Joined: 21 Feb 2016, 22:48

Re: Splitting a string into multiple lines with a maximum lenght

20 Jun 2018, 04:52

swagfag wrote:
Fixed now
Awesome, seems perfect.
I also fully understand the code here, so that's a big bonus as well.

In case someone is browsing the thread sometime, and needs this exact same thing, or something similar to this, I also added some RTrim to where is pushes an element into the array. That got rid of the trailing space(s).

Thanks to everyone who replied, I really learned a lot from this :)
And even though I now have the working solution, if anyone has anything else in mind, their input is still highly appreciated since I'm likely going to (try to) make my own implementation of this as well.
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Splitting a string into multiple lines with a maximum lenght

20 Jun 2018, 05:08

attempt 2:
  • used recursion

Code: Select all

example1 =
( comment
For an example, this thing that I am writing right now needs to be split into 	; 77 chars
multiple lines, and lets say each line can be a maximum of 80 characters. So	; 76 chars
I'm going to do this manually, look below this block of text to see what I		; 74 chars
mean. Also, just to spice things up												; 35 chars
I'mWritingLikeThisJustToMakeSureThatItWouldHandleSpecialStuffAswell. ║ ┘ some	; 77 chars
special characters here as well §§§ § § § ╬ ²„² „„ ²„„             ®®® ®¾ ¾¾ ¾ 	; 78 chars (yes, empty spaces, they didn't show up outside of the codeblock :L)
test ∟¡æ◙ hel&&lo((( and here													; 29 chars
are some																		; 8  chars
																				; 0  chars
new lines, it should															; 20 chars
respect these																	; 13 chars
aswell.																			; 7  chars

)
example2 =
(
hello hello hello hello hello hello hello hello hello hello hello1 hello2 hello3 hello4 hello5 hello6
123 123
)
example3 =
(
hello1 hello2 hello3 hello4 hello5 hello6 hello7 hello8 hello9 hello10 hello11 hello12 hello13 hello14 hello15 hello16 hello17 hello18 hello19 hello20 hello21 hello22 hello23 hello24 hello25 hello26 hello27 hello28 hello29 hello30
)



Index := 0

;-------------------------------------------------------------------------------
ButtonNextExample:
;-------------------------------------------------------------------------------
    Index ++
    Gui, Destroy

    ; use GUI here, can't use message box (auto-wraps)
    Gui, Add, Text,, % Test(example%Index%)
    Gui, Add, GroupBox, h3 wp
    Gui, Add, Button, Default, Next example
    Gui, Show,, MsgBox

Return

GuiClose:
ExitApp



;-------------------------------------------------------------------------------
Test(Text) { ; top-level logic
;-------------------------------------------------------------------------------
    Loop, Parse, Text, `n, `r
        If StrLen(A_LoopField) > 80
            Result .= Splitter(A_LoopField, 80)
        Else
            Result .= A_LoopField "`n"

    Return, Result
}



;-------------------------------------------------------------------------------
Splitter(Line, Max) { ; line-by-line
;-------------------------------------------------------------------------------
    For each, Word in StrSplit(Line, A_Space)
        If Not Splitted And StrLen(Front) + StrLen(Word) < Max
            Front .= Word A_Space
        Else
            Back .= Word A_Space
            , Splitted := True

    Return, Front "`n" (Splitted ? Splitter(Back, Max) : "")
}
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Splitting a string into multiple lines with a maximum lenght

20 Jun 2018, 14:28

I know this has already been "solved" but it was also solved long ago in the library below.

String Things
https://autohotkey.com/boards/viewtopic.php?t=53

It contains this function:

Code: Select all

/*
WordWrap
   Wrap the specified text so each line is never more than a specified length.
  
   Unlike st_lineWrap(), this function tries to take into account for words (separated by a space).
   
   string     = What text you want to wrap.
   column     = The column where you want to split. Each line will never be longer than this.
   indentChar = You may optionally indent any lines that get broken up. Specify
                What character or string you would like to define as the indent.
                
example: st_wordWrap("Apples are a round fruit, usually red.", 20, "---")
output:
Apples are a round
---fruit, usually
---red.
*/
st_wordWrap(string, column=56, indentChar="")
{
    indentLength := StrLen(indentChar)
     
    Loop, Parse, string, `n, `r
    {
        If (StrLen(A_LoopField) > column)
        {
            pos := 1
            Loop, Parse, A_LoopField, %A_Space%
                If (pos + (loopLength := StrLen(A_LoopField)) <= column)
                    out .= (A_Index = 1 ? "" : " ") A_LoopField
                    , pos += loopLength + 1
                Else
                    pos := loopLength + 1 + indentLength
                    , out .= "`n" indentChar A_LoopField
             
            out .= "`n"
        } Else
            out .= A_LoopField "`n"
    }
     
    Return SubStr(out, 1, -1)
}
Which seems to give the same results as the solution here with additional features in less code that probably executes faster.

This library is the first place I look for functions having to do with manipulating strings.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
User avatar
Meow
Posts: 24
Joined: 21 Feb 2016, 22:48

Re: Splitting a string into multiple lines with a maximum lenght

20 Jun 2018, 14:42

wolf_II wrote:attempt 2:
  • used recursion

Code: Select all

example1 =
( comment
For an example, this thing that I am writing right now needs to be split into 	; 77 chars
multiple lines, and lets say each line can be a maximum of 80 characters. So	; 76 chars
I'm going to do this manually, look below this block of text to see what I		; 74 chars
mean. Also, just to spice things up												; 35 chars
I'mWritingLikeThisJustToMakeSureThatItWouldHandleSpecialStuffAswell. ║ ┘ some	; 77 chars
special characters here as well §§§ § § § ╬ ²„² „„ ²„„             ®®® ®¾ ¾¾ ¾ 	; 78 chars (yes, empty spaces, they didn't show up outside of the codeblock :L)
test ∟¡æ◙ hel&&lo((( and here													; 29 chars
are some																		; 8  chars
																				; 0  chars
new lines, it should															; 20 chars
respect these																	; 13 chars
aswell.																			; 7  chars

)
example2 =
(
hello hello hello hello hello hello hello hello hello hello hello1 hello2 hello3 hello4 hello5 hello6
123 123
)
example3 =
(
hello1 hello2 hello3 hello4 hello5 hello6 hello7 hello8 hello9 hello10 hello11 hello12 hello13 hello14 hello15 hello16 hello17 hello18 hello19 hello20 hello21 hello22 hello23 hello24 hello25 hello26 hello27 hello28 hello29 hello30
)



Index := 0

;-------------------------------------------------------------------------------
ButtonNextExample:
;-------------------------------------------------------------------------------
    Index ++
    Gui, Destroy

    ; use GUI here, can't use message box (auto-wraps)
    Gui, Add, Text,, % Test(example%Index%)
    Gui, Add, GroupBox, h3 wp
    Gui, Add, Button, Default, Next example
    Gui, Show,, MsgBox

Return

GuiClose:
ExitApp



;-------------------------------------------------------------------------------
Test(Text) { ; top-level logic
;-------------------------------------------------------------------------------
    Loop, Parse, Text, `n, `r
        If StrLen(A_LoopField) > 80
            Result .= Splitter(A_LoopField, 80)
        Else
            Result .= A_LoopField "`n"

    Return, Result
}



;-------------------------------------------------------------------------------
Splitter(Line, Max) { ; line-by-line
;-------------------------------------------------------------------------------
    For each, Word in StrSplit(Line, A_Space)
        If Not Splitted And StrLen(Front) + StrLen(Word) < Max
            Front .= Word A_Space
        Else
            Back .= Word A_Space
            , Splitted := True

    Return, Front "`n" (Splitted ? Splitter(Back, Max) : "")
}
Seems to work now, thanks for you input!
User avatar
Meow
Posts: 24
Joined: 21 Feb 2016, 22:48

Re: Splitting a string into multiple lines with a maximum lenght

20 Jun 2018, 14:42

FanaticGuru wrote:I know this has already been "solved" but it was also solved long ago in the library below.

String Things
https://autohotkey.com/boards/viewtopic.php?t=53

It contains this function:

Code: Select all

/*
WordWrap
   Wrap the specified text so each line is never more than a specified length.
  
   Unlike st_lineWrap(), this function tries to take into account for words (separated by a space).
   
   string     = What text you want to wrap.
   column     = The column where you want to split. Each line will never be longer than this.
   indentChar = You may optionally indent any lines that get broken up. Specify
                What character or string you would like to define as the indent.
                
example: st_wordWrap("Apples are a round fruit, usually red.", 20, "---")
output:
Apples are a round
---fruit, usually
---red.
*/
st_wordWrap(string, column=56, indentChar="")
{
    indentLength := StrLen(indentChar)
     
    Loop, Parse, string, `n, `r
    {
        If (StrLen(A_LoopField) > column)
        {
            pos := 1
            Loop, Parse, A_LoopField, %A_Space%
                If (pos + (loopLength := StrLen(A_LoopField)) <= column)
                    out .= (A_Index = 1 ? "" : " ") A_LoopField
                    , pos += loopLength + 1
                Else
                    pos := loopLength + 1 + indentLength
                    , out .= "`n" indentChar A_LoopField
             
            out .= "`n"
        } Else
            out .= A_LoopField "`n"
    }
     
    Return SubStr(out, 1, -1)
}
Which seems to give the same results as the solution here with additional features in less code that probably executes faster.

This library is the first place I look for functions having to do with manipulating strings.

FG
I do still appreciate your input, as said in a above post.
Thanks! And thanks for that String Things library, will likely be using it in the future!

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: garry, Google [Bot], marypoppins_1, mikeyww, Rohwedder, RussF and 163 guests