AutoHotkey - Zip called as a part of a path - path

1. I am in a certain folder called "2" where are different kind of files and the path looks like this:
"C:\Users\Me\Desktop\Named_Folder\1\2"
I want to put all those files in there in a Zip and how should the script look like so at the end the Zip would be called "Named_Folder", the same as the folder in the path ? Need to mention that the "Named_Folder" will have different name each time. So how to name the zip as two directories above.
2. Till now I have just found the script to put all those files in a zip:
#IfWinActive ahk_class CabinetWClass
Send ^a ; Select All
Send, {AppsKey} ; Press the "context menu" key
Sleep 100
Send n ; Select "Send to" with the "n" key
Sleep 100
Send {Right} ; Open "Sent to" with the "right arrow" key
Sleep 100
Send {Down} ; Select "Compressed (zipped) folder" with the "arrow down" key
Sleep 100
Send {Enter} ; Execute "Compressed (zipped) folder" with the "Enter" key
return
And how the script should look like to combine the 1. and the 2. step ? With one letter shortcut.
So at the end the result should look like this:
Example
3. And then I would like to combine below two scripts (F2 F3 or even F1 if it changes anything) with one letter shortcut (4 first lines are from default AHK file):
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#If WinActive("ahk_class CabinetWClass") ; explorer
F1::
for window in ComObjCreate("Shell.Application").Windows
try Fullpath := % window.Document.Folder.Self.Path
; IfExist, %Fullpath%\1\
Run, %Fullpath%\2
return
F2::
for window in ComObjCreate("Shell.Application").Windows
try Fullpath := % window.Document.Folder.Self.Path
; IfExist, %Fullpath%\1\2\
Run, %Fullpath%\1\2
return
#If
#IfWinActive ahk_class CabinetWClass
F3::
for window in ComObjCreate("Shell.Application").Windows
try Fullpath := % window.Document.Folder.Self.Path
if (SubStr(Fullpath, -3) = "\1\2")
{
StringReplace, Fullpath, Fullpath, :,
StringTrimRight, Fullpath, Fullpath, 4
StringSplit, folder_array, Fullpath, \,
MsgBox, % folder_array%folder_array0%
Send ^a ; Select All
Send, {AppsKey} ; Press the "context menu" key
Sleep 100
Send n ; Select "Send to" with the "n" key
Sleep 100
Send {Right} ; Open "Sent to" with the "right arrow" key
Sleep 100
Send {Down} ; Select "Compressed (zipped) folder" with the "arrow down" key
Sleep 100
Send {Enter} ; Execute "Compressed (zipped) folder" with the "Enter" key
Sleep 2000 ; wait 2 seconds
SendInput, % folder_array%folder_array0%
}
return
#IfWinActive
4. And then extract the zip (right click-->context menu-->Extract to "folder with the same name as zip"
Context menu entry example
So it creates a folder named "NAMED_FOLDER" with all the extracted content.
I know that when I select the zip and press mouse right-button (to open context menu) and press letter "e" it works.
5. Then move this Zip and This new Extracted Folder to Desktop in a Folder "FINAL"
And at the end to do all those 5 steps with one letter shortcut. That would do some voodoo magic for me which I really need for the workflow.

#IfWinActive ahk_class CabinetWClass
F4::
for window in ComObjCreate("Shell.Application").Windows
try Fullpath := window.Document.Folder.Self.Path
IfNotExist, %Fullpath%\1\2
{
MsgBox, The folder "%Fullpath%\1\2" doesn't exist
return
}
Run, %Fullpath%\1\2
WinWait, %Fullpath%\1\2
WinActivate, %Fullpath%\1\2
WinWaitActive,%Fullpath%\1\2
StringReplace, Fullpath2, Fullpath, :,
StringSplit, folder_array, Fullpath2, \,
FolderName = % folder_array%folder_array0%
; MsgBox, % folder_array%folder_array0%
FileCopyDir %Fullpath%\1\2, %A_Desktop%\FINAL\%FolderName%
; Sleep 2000 ; wait 2 seconds
Send ^a ; Select All
Send, {AppsKey} ; Press the "context menu" key
Sleep 100
Send n ; Select "Send to" with the "n" key
Sleep 100
Send {Right} ; Open "Sent to" with the "right arrow" key
Sleep 100
Send {Down} ; Select "Compressed (zipped) folder" with the "arrow down" key
Sleep 100
Send {Enter} ; Execute "Compressed (zipped) folder" with the "Enter" key
Sleep 2000 ; wait 2 seconds
SendInput, % folder_array%folder_array0%
Send {Enter}
SetTimer, Move_ZIP, 500
return
#IfWinActive
Move_ZIP:
IfExist, %Fullpath%\1\2\%FolderName%.zip
{
SetTimer, Move_ZIP, off
FileMove, %Fullpath%\1\2\%FolderName%.zip, %A_Desktop%\FINAL
}
return
or this:
#IfWinActive ahk_class CabinetWClass
F4::
for window in ComObjCreate("Shell.Application").Windows
try Fullpath := window.Document.Folder.Self.Path
IfNotExist, %Fullpath%\1\2
{
MsgBox, The folder "%Fullpath%\1\2" doesn't exist
return
}
Run, %Fullpath%\1\2
WinWait, %Fullpath%\1\2
WinActivate, %Fullpath%\1\2
WinWaitActive,%Fullpath%\1\2
StringReplace, Fullpath2, Fullpath, :,
StringSplit, folder_array, Fullpath2, \,
FolderName = % folder_array%folder_array0%
; MsgBox, % folder_array%folder_array0%
; Sleep 2000 ; wait 2 seconds
Send ^a ; Select All
Send, {AppsKey} ; Press the "context menu" key
Sleep 100
Send n ; Select "Send to" with the "n" key
Sleep 100
Send {Right} ; Open "Sent to" with the "right arrow" key
Sleep 100
Send {Down} ; Select "Compressed (zipped) folder" with the "arrow down" key
Sleep 100
Send {Enter} ; Execute "Compressed (zipped) folder" with the "Enter" key
Sleep 2000 ; wait 2 seconds
SendInput, % folder_array%folder_array0%
Send {Enter}
SetTimer, Move_ZIP, 500
return
#IfWinActive
Move_ZIP:
FileCreateDir %A_Desktop%\FINAL
IfExist, %Fullpath%\1\2\%FolderName%.zip
{
SetTimer, Move_ZIP, off
FileMove, %Fullpath%\1\2\%FolderName%.zip, %A_Desktop%\FINAL
Sleep 2000 ; wait 2 seconds
SetTimer, CopyDir, 500
}
return
CopyDir:
IfExist, %Fullpath%\1\2\%FolderName%.zip
return
SetTimer, CopyDir, off
FileCopyDir %Fullpath%\1\2, %A_Desktop%\FINAL\%FolderName%
return

Related

Measure execution time forth

How to measure execution time of my program? I`ve found this but it doesnot work for me because my program needs some numbers in stack to work so my program and this solution kind of interfiering with each other(as I understand because when i try time: myfunc or time: num1 num2 myfunc nothing works....)
: time: ( "word" -- )
utime 2>R ' EXECUTE
utime 2R> D-
<# # # # # # # [CHAR] . HOLD #S #> TYPE ." seconds" ;
thanks for any help
The tick ' will parse the text immediately following the call to time:. So for a call with arguments it should be num1 num2 time: myfunc
Also, the tick will parse the input stream in run time. If you have the call to time: embedded in the word definition, it will try to get the execution toke for the word from the input stream, not for the word immediately following the time:. Use ['] to get an xt of the next word in compile time, and pass that xt as argument to time:
: time ( xt -- )
utime 2>R EXECUTE
utime 2R> D-
<# # # # # # # [CHAR] . HOLD #S #> TYPE ." seconds" ;
: foo 0 1000000 0 do i + loop drop ;
: bar num1 num2 ['] foo time ; \ pass the foo's xt as argument to time
Note there's no ' call in time, the EXECUTE will grab the token from the stack.

Loop using GO TO

I need to write a "for loop" in COBOL without using the 'PERFORM ... THRU ...' structure. My idea is to add a paragraph that I can jump back to once certain conditions are met. Here is what I came up with:
PROGRAM-BEGIN.
PAR-A.
IF I <= 10 THEN
SET J TO 1
PAR-B.
IF J <= 10 THEN
DISPLAY ARRAY(I,J)
SET J UP BY 1
GO TO PAR-B
END-IF.
SET I UP BY 1
GO TO PAR-A
END-IF.
PROGRAM-DONE.
Clearly this doesn't work because writing in this way will incur a syntax error. Can anyone help me on this? I can only use IF and GO TO.
This is what you'd need with your existing structure. You've not shown the initialisation of I, but you'll need one. You've attempted to avoid an explicit termination condition/GO TO,
PROGRAM-BEGIN.
SET I TO 1
PAR-A.
IF I <= 10 THEN
SET J TO 1
ELSE
GO TO PROGRAM-DONE
END-IF
.
PAR-B.
IF J <= 10 THEN
DISPLAY ARRAY(I,J)
SET J UP BY 1
GO TO PAR-B
END-IF
SET I UP BY 1
GO TO PAR-A
.
PROGRAM-DONE.
Note the use of the full-stops/periods. You should adopt that for your code, you'll have fewer troubles.
That comma is also trying to disguise itself as a full-stop/period/mark on the screen, and why even include it if you are jamming everything up against each other:
DISPLAY ARRAY ( I J )
There, isn't that nicer?
From the start, work on your names. Use descriptive names. I and J are just plain dumb, and in some wonderful situations you will even confuse them with the number 1.
SET first-level-index
second-level-index TO 1
.
output-results.
IF second-level-index
NOT GREATER THAN 10
DISPLAY
">"
the-data
( first-level-index
second-level-index )
"<"
SET second-level-index UP BY 1
GO TO output-results
END-IF
IF first-level-index
NOT GREATER THAN 10
SET second-level-index TO 1
SET first-level-index UP BY 1
GO TO output-results
END-IF
.
Or
set-up-for-loop.
SET first-level-index TO 1
.
outer-loop.
SET second-level-index TO 1
.
inner-loop.
IF second-level-index
NOT GREATER THAN 10
DISPLAY
">"
the-data
( first-level-index
second-level-index )
"<"
SET second-level-index UP BY 1
GO TO inner-loop
END-IF
IF first-level-index
NOT GREATER THAN 10
SET first-level-index UP BY 1
GO TO outer-loop
END-IF
.
You'd give those paragrpah-names descibing the actual task.
Be aware that comparing indexes (your I and J) to literals requires some twists and turns for the compiler.
To fix the syntax error caused by putting a paragraph name inside
the if, you can use the GOTO to move the PARB paragraph out of the first IF statement:
PROGRAM-BEGIN.
PAR-A.
IF I <= 10 THEN
SET J TO 1
GOTO PAR-B
END-IF
PAR-B.
IF J <= 10 THEN
DISPLAY ARRAY(I,J)
SET J UP BY 1
GO TO PAR-B
END-IF.
SET I UP BY 1
GO TO PAR-A
PROGRAM-DONE.

How do you parse 4-bit chunks from binary?

I'm trying to understand how I might parse binary per 4 bits if it is possible.
For example:
I have 2-byte codes that need to be parsed to determine which instruction to use
#{1NNN} where the first 4 bits tell where which instruction, and NNN represents a memory location (i.e. #{1033} says jump to memory address #{0033}
It seems to be easy to do this with full bytes, but not with half bytes:
parse #{1022} [#{10} {#22}]
because #{1} isn't valid binary!
So far, I've used giant switch statements with: #{1033} AND #{F000} = #{1000} in order to process these, but wondering how a more mature reboler might do this.
This is a rather big entry, but it addresses your needs and shows off PARSE a bit.
This is basically a working, albeit simple VM which uses the memory layout you describe above.
I set up a simple block of RAM which is an actual program that it executes when I use PARSE with the emulator grammar rule... basically, it increments an address and then jumps to that address, skipping over an NOP.
it then hits some illegal op and dies.
REBOL [
title: "simple VM using Parse, from scratch, using no external libraries"
author: "Maxim Olivier-Adlhoch"
date: 2013-11-15
]
;----
; builds a bitset with all low-order bits of a byte set,
; so only the high bits have any weight
;----
quaternary: func [value][
bs: make bitset!
reduce [
to-char (value * 16)
'-
to-char ((value * 16) + 15)
]
]
;------
; get the 12 least significant bits of a 16 bit value
LSB-12: func [address [string! binary!] ][
as-binary (address AND #{0FFF})
]
;------
i32-to-binary: func [
n [integer!]
/rev
][
n: load join "#{" [form to-hex to-integer n "}"]
either rev [head reverse n][n]
]
;------
; load value at given address. (doesn't clear the opcode).
LVAL: func [addr [binary!]][
to-integer copy/part at RAM ( (to-integer addr) + 1) 2
]
;------
; implement the opcodes which are executed by the CPU
JMP: func [addr][
print ["jumping to " addr]
continue: at RAM ((to-integer addr) + 1) ; 0 based address but 1 based indexing ;-)
]
INC: func [addr][
print ["increment value at address: " addr]
new-val: 1 + LVAL addr
addr: 1 + to-integer addr
bin-val: at (i32-to-binary new-val) 3
change at RAM addr bin-val
]
DEC: func [addr][
print ["decrement value at address: " addr]
]
NOP: func [addr][
print "skipping Nop opcode"
]
;------
; build the bitsets to match op codes
op1: quaternary 1
op2: quaternary 2
op3: quaternary 3
op4: quaternary 4
;------
; build up our CPU emulator grammar
emulator: [
some [
[
here:
[ op1 (op: 'JMP) | op2 (op: 'INC) | op3 (op: 'DEC) | op4 (op: 'NOP)] ; choose op code
:here
copy addr 2 skip (addr: LSB-12 addr) ; get unary op data
continue:
(do reduce [op addr])
:continue
]
| 2 skip (
print ["^/^/^/ERROR: illegal opcode AT: " to-binary here " offset[" -1 + index? here "]"] ; graceful crash!
)
]
]
;------
; generate a bit of binary RAM for our emulator/VM to run...
0 2 4 6 8 ; note ... don't need comments, Rebol just skips them.
RAM: #{2002100540FF30015FFF}
RAM-blowup: { 2 002 1 005 4 0FF 3 001 5 FFF } ; just to make it easier to trace op & data
parse/all RAM emulator
print "^/^/Yes that error is on purpose, I added the 5FFF bytes^/in the 'RAM' just to trigger it :-)^/"
print "notice that it doesn't run the NOP (at address #0006), ^/since we used the JMP opcode to jump over it.^/"
print "also notice that the first instruction is an increment ^/for the address which is jumped (which is misaligned on 'boot')^/"
ask "press enter to continue"
the output is as follows:
increment value at address: #{0002}
jumping to #{0006}
decrement value at address: #{0001}
ERROR: illegal opcode AT: #{5FFF} offset[ 8 ]
Yes that error is on purpose, I added the 5FFF bytes
in the 'RAM' just to trigger it :-)
notice that it doesn't run the NOP (at address #0006),
since we used the JMP opcode to jump over it.
also notice that the first instruction is an increment
for the address which is jumped (which is misaligned on 'boot')
press enter to continue

Custom interpreter

I'm trying to write an interpreter in Gforth, but it doesn't work. All I get is an infinite list of num num num num ...
: ?refill
source nip >in # =
if
refill drop
then
;
: inter
begin
?refill
bl word find dup
if
state # =
if
." comp "
,
else
." exec "
execute
then
else
dup rot count >number
if
abort
then
drop drop state #
if
." lit "
['] lit , ,
else
." num "
then
then
again
;
inter
: test 10 20 ;
Your interpreter does work, it just does not block, see the first couple of words from the output:
num exec lit lit exec num num num ...
However, you leave a 0 on the stack somewhere, thats why you create a stack overflow, you can use ~~ in the code to check the stack and track the unconsumed 0.
Bernd Paysan has introduced Recognizers to GForth, I suggest you take a look at them, as they would ease your task of writing an interpreter.

AutoHotKey iOS double space script

In iOS there's an option in Settings > General > Keyboard called '"." Shortcut'. When enabled, "Double tapping the space bar will insert a period followed by a space" and automatically capitalizes the next letter.
Does anyone know how to go abouts creating an AutoHotKey script to do this, as I find it extremely useful in iOS?
Ben,
You could try this:
~$Space:: ; trigger on {Space}
if (A_PriorHotkey <> "~$Space" or A_TimeSincePriorHotkey > 250)
Return
SendInput, {BS 2}.{Space}
Input, NextKey, I L1 T10 V B, {LControl}{RControl}{LAlt}{RAlt}{LShift}{RShift}{LWin}{RWin}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{BS}{Capslock}{Numlock}{PrintScreen}{Pause}
If NextKey and NextKey is lower
SendInput, {BS}+%NextKey%
Return

Resources