Page 1 of 3

NotStr() : Switch between multiple states

Posted: 21 Apr 2020, 09:40
by SKAN
NotStr(Value, Delimited list of unique values, Delimiter)
NotStr() is a wrapper for SubStr()

  • neogna2 wrote:
    The NotStr function cycles to the next value in a set of values, wrapping around the end.
    First parameter is a value in the set.
    Second parameter is the set, a string of delimited values.
    Third parameter (optional) is for changing the default delimiter "|".
    Examples:
    NotStr("B", "A|B|C") returns "C".
    NotStr("C", "A|B|C") returns "A" (wrap around)

    Edit: Worth pointing out also that the values in the set must be unique, otherwise the function does not cycle in the way one might expect.

The function:

Code: Select all

NotStr(S:="", Z:="", D:="|") {               ; NotStr v0.6b By SKAN on D34M/D34R @ tiny.cc/notstr
Local Q, LS:=StrLen(S), LZ:=StrLen(Z), LD:=StrLen(D), P1, P2, Q
Return SubStr(LZ?Z:1,(P1:=LS+LZ=0||S=Z?1:InStr(Z,(S)(D),0,0-LZ+LS+LD)?LS+LD+1:InStr(Z,(D)(S),0,LZ
   -LS)?1:(Q:=InStr(Z,(D)(S)(D)))?Q+LD+LS+LD:1),(LS+LZ=0?2:S=Z?1:(Q:=InStr(Z,D,0,P1))?Q:LZ+1)-P1)
}

The function - Readable version
Spoiler



Functionality explained with examples:

In computing, toggle means switching between two states 0/1 True/False or On/Off
Here follows an infinite loop

Code: Select all

N := 0
 Loop
   MsgBox % N := not N
NotStr() helps to switch between multiple values
Here follows an infinite loop:

Code: Select all

N := 0
Loop
   MsgbOX % N := NotStr(N, "1|2|3|0")
Spoiler


Here follows a GUI based demo: Use Alt+Arrows keys to adjust size of edit control.

  • Image

Code: Select all

#NoEnv
#Warn
#SingleInstance, Force

Gui, -DPIScale
s := 11,  DPI := A_ScreenDPI 
Gui, Font, % "s" . s-( DPI<=96 ? 0 : DPI<=120 ? 1 : DPI<=144 ? 2 : 3), Calibri
Gui, Margin, 25, 15

Gui, Add, Text,   xm ym  w175 h30 0x200, SetBatchLines
Gui, Add, Text,   xm     wp   h30 0x200, DetectHiddenWindows
Gui, Add, Text,   xm     wp   h30 0x200, Process priority

Gui, Add, Button, x+10  ym w75  h30   gSubRoutine, % T1 := ""
Gui, Add, Button, wp hp               gSubRoutine, % T2 := "Off"
Gui, Add, Button, wp hp    w140       gSubRoutine, % T3 := "Normal"

Gui, Add, Text,   xm                , Use Alt+Arrow key to adjust the size of edit control    
Gui, Add, Edit,   xm       w325 h120, Hello world!                               
Gui, Show,, NotStr() Demo 
T4 := "", T5 := ""
Return

SubRoutine:
GuiControlGet, Button, Focus

  Switch (Button) 
  {
    case "Button1" : 
      {
        GuiControl,,Button1, % T1 := NotStr(T1, "-1")
        SetBatchLines, %T1%
      }  
    case "Button2" : 
      {
        GuiControl,,Button2, % T2 := NotStr(T2, "On|Off")
        DetectHiddenWindows, %T2%
      }
    case "Button3" : 
      {
        GuiControl,,Button3, % T3 := NotStr(T3, "Low BelowNormal Normal AboveNormal High", " ")
        Process,Priority,, %T3%
      }   
  }
Return

EditWidth:
  Switch (A_ThisHotkey) 
  {
    Case "!Right" : GuiControl,Move,Edit1, % T4 := NotStr(T4, "w425 w525 w625 w700 w900 w325", " ")
    Case "!Left"  : GuiControl,Move,Edit1, % T4 := NotStr(T4, "w900 w700 w625 w525 w425 w325", " ")      
    Case "!Up"    : GuiControl,Move,Edit1, % T5 := NotStr(T5, "h180 h240 h320 h480 h120", " ")
    case "!Down"  : GuiControl,Move,Edit1, % T5 := NotStr(T5, "h480 h320 h240 h180 h120", " ")
  }
  Gui, Show, Center AutoSize
Return

#IfWinActive NotStr() Demo ahk_class AutoHotkeyGUI
  !Right:: GoSub, EditWidth
  !Left::  GoSub, EditWidth
  !Up::    GoSub, EditWidth
  !Down::  GoSub, EditWidth
#IfWinActive

Re: NotStr() : Swtich betwen multiple states

Posted: 21 Apr 2020, 12:22
by burque505
Thanks, @SKAN. I encourage everybody to try the examples, especially the GUI demo. This function should really come in handy.
Regards,
burque505

Re: NotStr() : Swtich betwen multiple states

Posted: 21 Apr 2020, 18:16
by Delta Pythagorean
I didn't think this was possible, but this error occured:

Code: Select all

==> Too many parameters passed to function.
     Specifically: Max(InStr(Z,(S)(D),0,0-LZ+LS+LD)?LS+LD+LD:0,InStr(Z,(D)(S),,LZ-LS) ?1:0,(Q:=InStr(Z,(D)(S)(D)))?Q+LD+LS+LD:0),1),((Q:=InStr(Z,D,,P1))?Q:LZ+1)-P1)
I don't know if you're running a different version of AHK but this function doesn't seem to work.

Re: NotStr() : Swtich betwen multiple states

Posted: 21 Apr 2020, 18:58
by SKAN
Delta Pythagorean wrote:
21 Apr 2020, 18:16
I don't know if you're running a different version of AHK but this function doesn't seem to work.
Yes. I was running Version 1.1.31.01. Just installed latest version for your sake and tested.
I'm unable to reproduce your error.

Re: NotStr() : Swtich betwen multiple states

Posted: 21 Apr 2020, 19:07
by boiler
He selectively pulled out a part of that line of code that doesn’t make sense as a stand-alone line because part of it belongs to the other Max() call and and the SubStr() call, which he left out of it.

Re: NotStr() : Swtich betwen multiple states

Posted: 21 Apr 2020, 20:54
by Delta Pythagorean
I used the full function and tested it in full and I could not get it to work. I did not edit the function itself.
Also, the error that I provided was copied from the debugger I'm using that displays the errors to a console.

Re: NotStr() : Swtich betwen multiple states

Posted: 21 Apr 2020, 21:23
by SKAN
@Delta Pythagorean Strange!

Before posting, I always test my functions in Ansi, Unicode 32/64 in Windows 7/10.
It would be helpful if somebody else can test and confirm if there is an error.

Re: NotStr() : Swtich betwen multiple states

Posted: 21 Apr 2020, 21:33
by boiler
No error here. Win10, 64-bit machine with Unicode 32-bit AHK, v1.1.32.00.

Re: NotStr() : Swtich betwen multiple states

Posted: 21 Apr 2020, 22:02
by SKAN
boiler wrote:
21 Apr 2020, 21:33
No error here. Win10, 64-bit machine with Unicode 32-bit AHK, v1.1.32.00.
Thank you.. much appreciated! :)

Re: NotStr() : Switch between multiple states

Posted: 22 Apr 2020, 00:57
by Delta Pythagorean
My apologies, I had a library that was included that replaced the Max function.
I'll have to look deeper into where that specific function is placed but the function does work for me.

TL;DR:
My fault, had a function somewhere that replaced a function.

Re: NotStr() : Switch between multiple states

Posted: 22 Apr 2020, 15:58
by SKAN
Delta Pythagorean wrote: My apologies, I had a library that was included that replaced the Max function.
I'll have to look deeper into where that specific function is placed but the function does work for me.
Thanks for the clarification. Okay, I've removed Max() from NotStr()
You may try it now.

:)

Re: NotStr() : Swtich betwen multiple states

Posted: 22 Apr 2020, 16:00
by SKAN
burque505 wrote: Thanks, @SKAN.
:thumbup: :)

Re: NotStr() : Switch between multiple states

Posted: 23 Apr 2020, 03:17
by neogna2
Nice function SKAN! :thumbup:

I didn't understand what it did on first read through, until I got to the examples. Perhaps this sentence could be updated?
SKAN wrote:
21 Apr 2020, 09:40
NotStr() will return next key if first parameter (key) is matches a value. If match fails, the first value is returned.
"is matches" looks like a typo and the mix of the phrases key/value tripped me up at first.

On second thought, maybe CycleStr() or just Cycle() would be a more self-explanatory name for the function?

In case some other people also think of the terms "cycle" and "wrap around" when they're looking for the kind of thing your function does here is more text that will make search engines guide them to this thread. :)

The NotStr function cycles to the next value in a set of values, wrapping around the end.
First parameter is a value in the set.
Second parameter is the set, a string of delimited values.
Third parameter (optional) is for changing the default delimiter "|".
Examples:
NotStr("B", "A|B|C") returns "C".
NotStr("C", "A|B|C") returns "A" (wrap around)

Edit: Worth pointing out also that the values in the set must be unique, otherwise the function does not cycle in the way one might expect. Examples

Code: Select all

Loop
    MsgBox % item := NotStr(item, "A|A|B")  ; stuck on A
or

Code: Select all

Loop
    MsgBox % item := NotStr(item, "A|B|CC|CC")  ; skips second CC

Re: NotStr() : Switch between multiple states

Posted: 23 Apr 2020, 06:20
by kczx3
Spoiler
Thank you for this. I too didn’t understand SKANs description.

Re: NotStr() : Switch between multiple states

Posted: 23 Apr 2020, 07:15
by boiler
I also think neogna2’s suggestions really make clear what the value of this function is, including the name of the function and especially the clear description and examples.

Re: NotStr() : Switch between multiple states

Posted: 23 Apr 2020, 07:17
by SKAN
@neogna2

Many thanks for the fantastic feedback. :)
I didn't understand what it did on first read through, until I got to the examples. Perhaps this sentence could be updated?
I thought the GUI demo will explain it all.
I will update it totally with your quote.

  • NotStr(Value, Delimited unique values, Delimiter)
    The NotStr function cycles to the next value in a set of values, wrapping around the end.
    First parameter is a value in the set.
    Second parameter is the set, a string of delimited values.
    Third parameter (optional) is for changing the default delimiter "|".
    Examples:
    NotStr("B", "A|B|C") returns "C".
    NotStr("C", "A|B|C") returns "A" (wrap around)
On second thought, maybe CycleStr() or just Cycle() would be a more self-explanatory name for the function?

In case some other people also think of the terms "cycle" and "wrap around" when they're looking for the kind of thing your function does here is more text that will make search engines guide them to this thread. :)
Actually I wanted to name the function Not() but since its a wrapper for SubStr() I had to Include the "Str" part.
Google will index this page in couple of days anyways and whatever you've suggested will be google-able. :)
Worth pointing out also that the values in the set must be unique.
Yes. I should have mentioned it. Values (Switch states) need to be unique.

Thanks again :)

Re: NotStr() : Switch between multiple states

Posted: 23 Apr 2020, 08:19
by arcticir
Here is a similar scheme.

Code: Select all

MsgBox str_skip("a","a/b/c")

str_skip(t,s,k:="/") => (RegExMatch(k s k, "(" k "([^" k "]+))?.*" k t k "(([^" k "]+)" k ")?", t),t.value(4) or t.value(2))

Re: NotStr() : Switch between multiple states

Posted: 23 Apr 2020, 09:05
by SKAN
boiler wrote:I also think neogna2’s suggestions really make clear what the value of this function is,
Yes .I have re-quoted him in OP.
boiler wrote:including the name of the function
The function is modeled after Not operator and is a Str manipulation function and hence the name NotStr()
My first two examples show this.
boiler wrote:and especially the clear description and examples.

Yes. My description was bad :(. The cover of the book is also important.
But my My GUI based demo is a good example.. if only people reach that far!

Re: NotStr() : Switch between multiple states

Posted: 23 Apr 2020, 09:08
by SKAN
arcticir wrote:
23 Apr 2020, 08:19
Here is a similar scheme.

Code: Select all

MsgBox str_skip("a","a/b/c")

str_skip(t,s,k:="/") => (RegExMatch(k s k, "(" k "([^" k "]+))?.*" k t k "(([^" k "]+)" k ")?", t),t.value(4) or t.value(2))
Very nice!. I don't have tools to benchmark V2 scripts, so unable to compare it with mine.
Would be nice if the function could return the first value when t is blank.

Re: NotStr() : Switch between multiple states

Posted: 24 Apr 2020, 08:13
by SpeedMaster
Thanks for this usefull function :D :thumbup:

Is it also possible to add an option for the direction ? :think:

NotStr(S:="", Z:="", D:="|", dir:="1")

dir = 1 ; cycle forward
dir = -1 ; cycle backward
dir = 0 ; reset/restore starting pos

SKAN wrote:
23 Apr 2020, 08:19
Yes. My description was bad . The cover of the book is also important.
I think a function without it's description is almost a dead function. :(
I recomand to put the help and usage right above the function.
good example : ST library https://www.autohotkey.com/boards/viewtopic.php?f=6&t=53
ST library is missing some of your functions so I added them into my personal ST library. ( :shh: I hope you don't mind. :shifty:)

Cheers