sql server - Autohotkey will prematurely end loop during execution -
i've written autohotkey script allows me run sql query @ cursor's current position in microsoft sql server management studio 2012. , works--most of time anyway.
the implementation uses sort of delta movement determine when it's reached top of sql query block or top of window. selects downward until reaches bottom of window or bottom of block in same fashion. afterwards, presses f5 run script highlighted.
here's script:
$f5:: ; first check current line isn't blank (the cursor has on text) send, {home} hltext := selectnextchar() if hltext = `r`n { ; return current position send, {left} return } ; move cursor until gets top of text block ; first length future comparisons send, {end} send, {shift down}{home}{shift up} send, ^c stringlen, slctsize, clipboard ; begin checking lengths see if there still 'movement' loop { send, {shift down}{left}{home}{shift up} send, ^c ; if new length same we've hit top , can break out stringlen, temp, clipboard ifequal, slctsize, %temp% { send, {left} break } ; if have hit blank space can stop here firstchar := substr(clipboard, 1, 1) if firstchar space { send, {left}{down} break } ; if neither 1 of these conditions met, continue on slctsize = %temp% sleep, 50 } ; select down until blank space or end of file send, {shift down}{end}{shift up} send, ^c stringlen, slctsize, clipboard loop { send, {shift down}{right}{end}{shift up} send, ^c stringlen, temp, clipboard ifequal, slctsize, %temp% { break } ; if have hit blank space can stop here lastchar := substr(clipboard, 0) if lastchar space { break } ; if neither 1 of these conditions met, continue on slctsize = %temp% sleep, 50 } ; execute! send, {f5} ; place cursor @ end of last line send, {right} return selectnextchar() { send, {lshift down}{right}{lshift up} send, ^c return %clipboard% }
these movements--up , down--will end prematurely, causing query not selected when f5 pressed. small queries isn't problem; large queries spanning more ~10 lines, becomes apparent going on.
i've tested placing sleep, 500
in loops, , seems trick, whole point of script make testing queries on fly lot faster. if i'm waiting more 2 or 3 seconds (hopefully) highlight, makes quicker old strategy, i.e. manually highlighting mouse?
to clear, larger queries are run part, process not fast enough warrant usage , there's no guarantee highlight before execution. understand implementation inherently o(x^2). if run script on full blast (setkeydelay, -1
), wouldn't problem.
any thoughts on matter or limitation of os/program/ahk?
also, me or so's ahk syntax highlighting severely broken?
update: here's updated script suggested edits:
sendmode, input ; fast gives unpredictable results @ low sleep speeds setbatchlines, -1 $f5:: ; first check current line isn't blank (the cursor has on text) send, {home} hltext := selectnextchar() if hltext = `r`n { ; return current position send, {left} return } ; move cursor until gets top of text block ; first length future comparisons send, {end} send, {shift down}{home}{shift up} send, ^c sleepaftercopy() stringlen, slctsize, clipboard ; begin checking lengths see if there still 'movement' loop { send, {shift down}{left}{home}{shift up} send, ^c sleepaftercopy() ; if new length same we've hit top , can break out stringlen, temp, clipboard ifequal, slctsize, %temp% { send, {left} break } ; if have hit blank space can stop here firstchar := substr(clipboard, 1, 1) if firstchar space { send, {left}{down} break } ; if neither 1 of these conditions met, continue on slctsize = %temp% } ; select down until blank space or end of file send, {shift down}{end}{shift up} send, ^c sleepaftercopy() stringlen, slctsize, clipboard loop { send, {shift down}{right}{end}{shift up} send, ^c sleepaftercopy() stringlen, temp, clipboard ifequal, slctsize, %temp% { break } ; if have hit blank space can stop here lastchar := substr(clipboard, 0) if lastchar space { break } ; if neither 1 of these conditions met, continue on slctsize = %temp% } ; execute! send, {f5} ; place cursor @ end of last line send, {right} return selectnextchar() { send, {lshift down}{right}{lshift up} send, ^c return %clipboard% } sleepaftercopy() { sleep, 50 }
update 2: here's version includes clipwait
per @sidola. runs fast possible. update includes logic make sure if had copied before hand, isn't obliterated because of our overuse of clipboard. , finally, takes account indents or spaces @ beginning/ end of lines:
sendmode, input ; fast gives unpredictable results @ low sleep speeds setbatchlines, -1 #ifwinactive ahk_exe ssms.exe $f5:: ; save current clipboard material , restore @ end before = %clipboard% ; first check current line isn't blank (the cursor has on text) send, {home} clipboard = hltext := selectnextchar() if hltext = `r`n { ; return current position send, {left} return } ; move cursor until gets top of text block ; first length future comparisons send, {end} send, {shift down}{home}{home}{shift up} clipboard = send, ^c sleepaftercopy() stringlen, slctsize, clipboard ; begin checking lengths see if there still 'movement' loop { send, {shift down}{left}{home}{home}{shift up} clipboard = send, ^c sleepaftercopy() ; if new length same we've hit top , can break out stringlen, temp, clipboard ifequal, slctsize, %temp% { send, {left} break } ; if have hit blank space can stop here firstchar := substr(clipboard, 1, 1) if firstchar = `r { send, {left}{down} break } ; if neither 1 of these conditions met, continue on slctsize = %temp% } ; select down until blank space or end of file send, {shift down}{end}{shift up} clipboard = send, ^c sleepaftercopy() stringlen, slctsize, clipboard loop { send, {shift down}{right}{end}{shift up} clipboard = send, ^c sleepaftercopy() stringlen, temp, clipboard ifequal, slctsize, %temp% { break } ; if have hit blank space can stop here lastchar := substr(clipboard, 0) if lastchar = `n { break } ; if neither 1 of these conditions met, continue on slctsize = %temp% } ; execute! send, {f5} ; place cursor @ end of last line send, {right} ; restore clipboard clipboard = %before% return +f5:: send, {f5} return selectnextchar() { send, {lshift down}{right}{lshift up} send, ^c sleepaftercopy() return %clipboard% } sleepaftercopy() { clipwait ; sleep, 30 }
the reason ends prematurely due copy-command not having enough time update clipboard before go work on it.
the best way handle clear clipboard before copying anything, , relying on clipwait
tell when has been copied. alternatively let time-out tell nothing has been copied.
clipwait
allows detect top , bottom of document without checking duplicates, we'll waiting time-out.
below working example fast make it.
note however: script works programs copy-command behaves normally. meaning if copy without selection, nothing gets copied. while trying discovered programs don't have behavior, , such script won't work programs. in cases have resort checking duplicates way or another.
sendmode, input setbatchlines, -1 esc::exitapp $f5:: ; check if line we're @ line break if (islinebreak( getfirstchar() )) return ; top of document traversetext("up") ; bottom linecount := traversetext("down") ; select selectalllines(linecount) return ; --- functions below --- selectalllines(linecount) { send, {lshift down} loop, % linecount { send, {up} } send, {home} send, {lshift up} } traversetext(direction) { loop { selectline(direction) thisline := copytext() ; if it's line break, we're out if (islinebreak(thisline)) { ; if going want move down once first if (direction = "up") send, {down} break } ; if nothing copied, we're out if (!thisline) break := a_index ; keep track of how many lines we've moved passed } ; if had line break beneath ; need add 1 counter if (thisline) i++ return ; return amount of lines traversed } islinebreak(value) { return value = "`r`n" } getfirstchar() { send, {home}+{down} ; home, shift + down char := copytext() send, {left} return char } selectline(direction) { send, % direction = "up" ? "{home}" : "{end}" ; ternary operator send, {lshift down} send, % direction = "up" ? "{up}" : "{down}" ; ternary operator send, {lshift up} } copytext() { clipboard := "" send, ^c clipwait, 0.2 ; time-out after 200ms return clipboard }
Comments
Post a Comment