Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

AutoClip v3.0 - AutoReplacer and ClipSaver


  • Please log in to reply
21 replies to this topic
skrommel
  • Members
  • 193 posts
  • Last active: Jun 07 2010 08:30 AM
  • Joined: 30 Jul 2004
:D This was originally posted as an AutoReplacer supporting Rich Text, images and other formats, but by adding the clips to the tray menu, it also works as a ClipSaver. The previous version is here: http://www.autohotke...opic.php?t=3486

Skrommel

:!: Updated to v3.0
- AutoClip now sends the clips and scripts to the last active control in the last active window.
- I've split the menu in two to separate clips and scripts.
- Added an ini-file to let the user edit the hotkeys.
- Added a help menu.

:!: Updated to v4.0
- Added support for user defined prefixes to run external programs. Make an ahk-script, compile it and place it together with AutoClip. Typing the name of the program followed by a colon and the parameters runs the program. Example: Typing calc:1+2 displays the result 3.

Calc.ahk uses ftp://ftp.sac.sk/pub/sac/utilmisc/calc387.zip
;calc.ahk compiled as calc.exe
SetWorkingDir,"%A_ScriptDir%"
RunWait,cmd /c calc387.com %1% > result.txt 
FileRead,result,result.txt 
MsgBox,%1% =%result%

AutoClip.ahk
SetWorkingDir,"%A_ScriptDir%"
SetKeyDelay,0 
SetWinDelay,0 

Gosub,BUILDTRAYMENU
Gosub,READINI
SetTimer,GETWINDOW,999

START:
hotkey=
Input,input,V L99,{RCtrl}
If hotkey In %cancel%
  Goto,START
StringGetPos,pos,input,:
StringLeft,command,input,%pos%
pos+=1
StringTrimLeft,parameter,input,%pos%
filename:=hexify(input)
IfNotExist,%filename%.clip
IfNotExist,%filename%.script
IfNotExist,%command%.exe
{
  Send,%hotkey%
  Goto,START
}
IfExist,%command%.exe
{
  Gosub,RUN
  Goto,START
}
StringLen,length,input
Send,{Backspace %length%}
post=clip
Gosub,EXECUTE
post=script
Gosub,EXECUTE
If hotkey Not In %ignore%
If hotkey Not In %cancel%
  Send,%hotkey%
Goto,START

EXECUTE:
SetTimer,GETWINDOW,Off
FileRead,Clipboard,*c %filename%.%post%
WinActivate,ahk_id %window%
WinWaitActive,ahk_id %window%
ControlFocus,%control%,ahk_id %window%
If post=script
  Send,%Clipboard%
Else 
  Send,^v
SetTimer,GETWINDOW,On
Return

RUN:
Run,%command%.exe "%parameter%"
Return

HOTKEYS:
StringTrimLeft,hotkey,A_ThisHotkey,1
StringLen,hotkeyl,hotkey
If hotkeyl>1
  hotkey=`{%hotkey%`}
Send,{RCtrl}
Return

READINI:
IfNotExist,AutoClip.ini
  FileAppend,;Keys that start completion - must include Ignore and Cancel keys`n[Autocomplete]`nKeys={Escape}`,{Tab}`,{Enter}`,{Space}`,{`,}`,{;}`,{.}`,{:}`n;Keys not to send after completion`n[Ignore]`nKeys={Tab}`,{Enter}`n;Keys that cancel completion`n[Cancel]`nKeys={Escape},AutoClip.ini
IniRead,cancel,AutoClip.ini,Cancel,Keys ;keys to stop completion, remember {}
IniRead,ignore,AutoClip.ini,Ignore,Keys ;keys not to send after completion
IniRead,keys,AutoClip.ini,Autocomplete,Keys
Loop,Parse,keys,`,
{
  StringTrimLeft,key,A_LoopField,1
  StringTrimRight,key,key,1
  StringLen,length,key
  If length=0
    Hotkey,$`,,HOTKEYS
  Else
    Hotkey,$%key%,HOTKEYS
}
Return

F12::
ADDCLIP:
post=clip
Gosub,ADD
Return

F11:
ADDSCRIPT:
post=script
Gosub,ADD
Return

ADD:
Input
Hotkey,$Enter,Off
InputBox,shorthand,Add %post%,Type the shorthand to be replaced,,300,150 
If ErrorLevel=1 
  Return 
If shorthand= 
  Goto,ADD
filename:=hexify(shorthand)
IfNotExist,%filename%.%post%
  FileAppend,%ClipboardAll%,%filename%.%post%
Else 
{ 
  MsgBox,4,AutoClip,Shorthand %shorthand% already exists.`n`nReplace?
  IfMsgBox,Yes 
    FileAppend,%ClipboardAll%,%filename%.%post%
  IfMsgBox,No 
    Goto,ADD
} 
Gosub,BUILDTRAYMENU
Hotkey,$Enter,On
Return 

BUILDTRAYMENU:
Menu,Tray,NoStandard
Menu,Tray,DeleteAll
post=clip
Gosub,ADDTRAYFILES
Menu,Tray,Add,&Add Clip,ADDCLIP
Menu,Tray,Add,&Remove Clip,REMOVECLIP 
Menu,Tray,Add
post=script
Gosub,ADDTRAYFILES
Menu,Tray,Add,&Add Script,ADDSCRIPT
Menu,Tray,Add,&Remove Script,REMOVESCRIPT
Menu,Tray,Add
Menu,Tray,Add,&List All,LIST 
Menu,Tray,Add,&Help,HELP
Menu,Tray,Add,E&xit,EXIT 
Return

ADDTRAYFILES:
filelist=
Loop,*.%post% 
  filelist=%FileList%%A_LoopFileName%`n 
Sort,filelist 
counter=0 
Loop,Parse,filelist,`n 
{ 
  If A_LoopField= 
    Continue 
  counter+=1 
  FileRead,Clipboard,*c %A_LoopField% 
  shorthand:=Dehexify(A_LoopField) 
  Menu,Tray,Add,%shorthand%,PASTE%post%
} 
Return

REMOVECLIP:
post=clip
Gosub,REMOVE
Return

REMOVESCRIPT:
post=script
Gosub,REMOVE
Return

REMOVE:
Input
filelist=
Loop,*.%post%
  filelist=%FileList%%A_LoopFileName%`n 
Sort,filelist 
Menu,clipmenu,Add
Menu,clipmenu,DeleteAll
counter=0 
Loop,Parse,filelist,`n 
{ 
  If A_LoopField= 
    Continue 
  counter+=1 
  FileRead,Clipboard,*c %A_LoopField% 
  shorthand:=Dehexify(A_LoopField) 
  Menu,clipmenu,Add,%shorthand%,REMOVESELECT
} 
Menu,clipmenu,Show
Return 

REMOVESELECT:
Input
filename:=hexify(A_ThisMenuItem)
IfNotExist,%filename%.%post%
  MsgBox,0,Remove %post%,Filename %shorthand% doesn't exists.
Else 
  FileDelete,%filename%.%post% 
Gosub,BUILDTRAYMENU
;Menu,clipmenu,Delete,%shorthand%
Return 

PASTECLIP:
post=clip
Gosub,PASTESELECT
Return

PASTESCRIPT:
post=script
Gosub,PASTESELECT
Return

PASTESELECT:
Input
filename:=hexify(A_ThisMenuItem)
IfNotExist,%filename%.%post%
{
  MsgBox,0,AutoClip,Shorthand %A_ThisMenuItem% doesn't exists.
  Gosub,BUILDTRAYMENU
  Return 
}
FileRead,Clipboard,*c %filename%.%post%
Gosub,EXECUTE
Return

LIST:
Input
FileDelete,AutoClip.rtf 
FileAppend,,AutoClip.rtf 
Run,WordPad.exe "AutoClip.rtf" 
WinWait,AutoClip.rtf - WordPad,,5 
If ErrorLevel=1 
{ 
  MsgBox,Can't find WordPad 
  Return 
} 
post=clip
Gosub,LISTLOOP
post=script
Gosub,LISTLOOP
Return

LISTLOOP:
filelist= 
Loop,*.%post%
  filelist=%FileList%%A_LoopFileName%`n 
Sort,filelist 
counter=0 
Loop,Parse,filelist,`n 
{ 
  If A_LoopField= 
    Continue 
  counter+=1 
  FileRead,Clipboard,*c %A_LoopField% 
  shorthand:=Dehexify(A_LoopField) 
  WinActivate,AutoClip.rtf - WordPad 
  WinWaitActive,AutoClip.rtf - WordPad 
  Send,%post%%counter%: %shorthand%`n`n{Up}^v{Down}`n 
} 
Send,^s 
Return 

GETWINDOW:
WinGet,window0,ID,A
WinGetClass,class,ahk_id %window0%
If class<>
If class<>Shell_TrayWnd
If class<>AutoHotkey
{
  ControlGetFocus,control,ahk_id %window0%
  window=%window0%
}
Return

EXIT: 
ExitApp 

Hexify(x) ;Stolen from Laszlo 
{ 
  StringLen,len,x 
  format=%A_FormatInteger% 
  SetFormat,Integer,Hex 
  hex=
  Loop,%len% 
  { 
    Transform,y,Asc,%x% 
    StringTrimLeft,y,y,2 
    hex=%hex%%y% 
    StringTrimLeft,x,x,1 
  } 
  SetFormat,Integer,%format% 
  Return,hex 
} 

DeHexify(x) 
{ 
   StringLen,len,x 
   len:=(len-5)/2 
   string= 
   Loop,%len% 
   { 
      StringLeft,hex,x,2 
      hex=0x%hex% 
      Transform,y,Chr,%hex% 
      string=%string%%y% 
      StringTrimLeft,x,x,2 
   } 
   Return,string 
}

HELP:
help=         AutoClip v4.0
help=%help%`n
help=%help%`n Replaces text you type with any formatted text, image or other clip. 
help=%help%`n
help=%help%`n Example: Place the clip you want to use on the clipboard by selecting
help=%help%`n text or an image, and press Ctrl-C.  
help=%help%`n Rightclick the tray icon, select Add Clip, and input the shorthand.
help=%help%`n Rightclick the tray icon to Remove or List clips. F12=Add Clip. 
help=%help%`n The clips are showed at the top of the tray menu, and clicking
help=%help%`n pastes the clip into the active control of the active window.
help=%help%`n 
help=%help%`n You can also make Scripts that send key presses for automation, using
help=%help%`n {Tab}{Enter}{Left}{PgUp} etc... !=alt, ^=ctrl, +=shift, #=windows. 
help=%help%`n Example: Start Notepad, write user{Tab}password, select the text,
help=%help%`n press Ctrl-C. 
help=%help%`n Rightclick the tray icon, select Add Script, and input the shorthand.
help=%help%`n Rightclick the tray icon to Remove or List scripts. F11=Add Script.
help=%help%`n The scripts are showed in the middle of the tray menu, and clicking
help=%help%`n sends the script into the active control of the active window.
help=%help%`n
help=%help%`n AutoClip can also run external programs. Any exe-file placed together
help=%help%`n with AutoClip is run by typing the name of the exe-file,
help=%help%`n a colon, and the parameters to send. Example: calc:1+2*3
help=%help%`n
help=%help%`n The clips and scripts are listed using WordPad.
help=%help%`n
help=%help%`n It also works in programs without an input box, like PaintBrush. 
MsgBox,0,AutoClip,%help%
help=
Return


Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
The idea of terminating the input command collecting keystrokes with a sent LControl looks very clever. I still see a few points, though, which could be improved.

(a) In a program, where you don’t often press terminator keys, like Enter or Tab or ";", the input string grows indefinitely. E.g. in games, where you control movements with the keys W, A, S, Z. Eventually, the script slows down, having this huge and growing input buffer. Furthermore, when you finally press a terminator key, a humongous hexified filename is generated, to see if such a file exists. It could crash Windows, provoke an error message or just takes a lot of time. This was the reason my example script had limited the length of the collected keystroke string.

(B) I am surprised, that Send %ClipBoard% actually works. It is an undocumented feature, and future AHK versions might not allow it. Even short clip files contain many forbidden characters, like 0x00. The length of the clipboard is encoded, too. Sending those could cause unpredictable results.

© Some strings behave funny. A replacement text `123' is OK, but {123} won’t show up, like Hi! . Even with the ` character, Hi`! just disappears.

(d) Sending LControl to terminate the input could cause problems in programs using it to trigger some actions (like launch a rocket or bring up a command window). This could be avoided by sending some scan code without a key on the keyboard, instead.

(e) Overwriting the existing last clip does not work reliably in my machine.

(f) After typing in the shorthand, an Enter should terminate it, but instead it is given to the active program when the input box is closed. [Edit]

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004

(B) I am surprised, that Send %ClipBoard% actually works. It is an undocumented feature, and future AHK versions might not allow it.

This is fully supported because anywhere you write %Clipboard%, the plain text equivalent of whatever is on the clipboard is substituted. For example, if some italic text is on the clipboard, %Clipboard% would see it as unformatted plain text. Later, when you press Ctrl-V, the receiving app would see it as italic if it supports that type of formatted text.

This plain text nature of %Clipboard% is implied on the clipboard page, but maybe it needs to be clarified somehow.

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
Chris: if Send %ClipBoard% is supported and actually has to send the text equivalent of the Clipboard content, it does not work as expected. Either a fix or an extensive documentation change is necessary.

  • Guests
  • Last active:
  • Joined: --
:D Just when you think the job is done...

a) Input,input,V I99,{LControl} should solve this.
c) That's got to do with the pure text functionality. Maybe I should drop it? Or need a prefix, like Run: to run programs, and Script: to send keystrokes?
d) I can't get Input to terminate on something lik {Asc 0001}. Chris?
e) I have had no such problems. What happens?
f) I can't reproduce this either. What programs and input boxes?

Skrommel

skrommel
  • Members
  • 193 posts
  • Last active: Jun 07 2010 08:30 AM
  • Joined: 30 Jul 2004
Here's the command prefix suggestion:

To execute a script, start the clip with scr: as in scr:username{Tab}password.
To run a program, start the clip with run: as in run:notepad.exe c:\boot.ini.

The code should look like this:

START:
hotkey=
Input,input,V L99,{RCtrl}
If hotkey In %cancel%
  Goto,START
filename:=hexify(input)
IfNotExist,%filename%.clip
{
  Send,%hotkey%
  Goto,START
}
StringLen,length,input
Send,{Backspace %length%}
FileRead,Clipboard,*c %filename%.clip
FileGetSize,size,%filename%.clip 
StringMid,command,Clipboard,1,4
If command=run:
{
  StringTrimLeft,program,Clipboard,4
  Run,%program%
}
Else
If command=scr:
{
  StringTrimLeft,Clipboard,Clipboard,4
  Send,%Clipboard% 
}
Else 
  Send,^v
If hotkey Not In %ignore%
If hotkey Not In %cancel%
  Send,%hotkey%
Goto,START

Skrommel

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
Skrommel: (a) did you mean the option L99 for the Input command, to terminate after 99 characters? It introduces another problem. After 99 characters the input is terminated without an end key, so in theory there could be an unwanted replacement triggered. Also, a shorthand could be cut, having its first key as the 99th in one input run, and the next keys in the restarted input. It won’t be recognized. Yes, these are unlikely scenarios, but if I give the script to others, they would eventually bump into it, and don’t understand the reasons. I still think my example script is the best, with its own ring buffer.

© I think a user selectable scheme is the best: there could be 3 choices for saving the clipboard (or the selection), and they also determine how the replacement is pasted: (1) Add clip, Save in file, Paste with Ctrl-C after setting up the ClipBoard, (2) Add pure text, Saved in the ini file, SendRaw pastes it in the application and (3) Add control text, Saved in the ini file, Send pastes it with all the AHK control character functionality. The current scheme is confusing. If you copy control text from MS Word (^c{Tab}), it always produces a large ClipBoard. If you copy the same text from a text editor, it will be small, and handled differently.

(d) I meant {SC123} type of things, not {ASC 001}. But I have not tested it.

(e) I figured, it was my problem: I left a file viewer open with the clip file. In any case, if a file operation fails, for any reason (like disk is full), an error message should be issued, and the user should be able to choose another clip name.

(f) Type: "F12 shd{Enter}" in the InputBox. The InputBox remains open. Click on OK. The editor receives the {Enter}. During the InputBox operation the Enter HotKey should have been disabled.

skrommel
  • Members
  • 193 posts
  • Last active: Jun 07 2010 08:30 AM
  • Joined: 30 Jul 2004
Laszlo wrote:

(f) After typing in the shorthand, an Enter should terminate it, but instead it is given to the active program when the input box is closed.


That's because the Enter hotkey is enabled. The following code should solve this.

Any suggestions for other prefixes?

Skrommel


F12:: 
ADD:
Input
Hotkey,$Enter,Off
InputBox,shorthand,Add AutoClip,Type the shorthand to be replaced,,300,150 
If ErrorLevel=1 
  Return 
If shorthand= 
  Goto,ADD 
filename:=hexify(shorthand)
IfNotExist,%filename%.clip 
  FileAppend,%ClipboardAll%,%filename%.clip 
Else 
{ 
  MsgBox,4,AutoClip,Shorthand %shorthand% already exists.`n`nReplace?
  IfMsgBox,Yes 
    FileAppend,%ClipboardAll%,%filename%.clip 
  IfMsgBox,No 
    Goto,ADD
} 
Gosub,BUILDMENU
Hotkey,$Enter,On
Return


Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
I’d prefer the user selectable control text option. This way you don’t need to restrict the commands to prefixes, "#r notepad" could be used, too.

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004

if Send %ClipBoard% is supported and actually has to send the text equivalent of the Clipboard content, it does not work as expected. Either a fix or an extensive documentation change is necessary.

I meant that %Clipboard% is the same as any other variable as far as the Send command is concerned. If Clipboard contains the string "{Enter}", Send %Clipboard% will send an Enter keystroke. If you know of any example that doesn't work this way, please post or describe it.

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
When I first saw the problem it looked serious, but actually it is not. I used
#z::
MsgBox %ClipBoard%
Send %ClipBoard%
Return
In MultiEdit 9.0e, MsgBox properly shows the copied text, but here is what I got sent (the problem is the ` does not work as escape character):
! -> nothing (should be ALT, moving the focus to the tool bar, but that does not happen.)
`! -> `
{123} -> nothing
`{123`} -> `
``{123``} -> ``

skrommel
  • Members
  • 193 posts
  • Last active: Jun 07 2010 08:30 AM
  • Joined: 30 Jul 2004
:D It's getting uglier by the minute, but here's v3.0.

- AutoClip now sends the clips and scripts to the last active control in the last active window.
- I've split the menu in two to separate clips and scripts.
- Added an ini-file to let the user edit the hotkeys.
- Added a help menu.

Skrommel

:!: Script moved to the top.

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
It might be easier for people if the latest version is kept in the post at the top of the topic (unless you think the older version should be retained too). In case you don't know, you can edit your posts with the Edit button.

skrommel
  • Members
  • 193 posts
  • Last active: Jun 07 2010 08:30 AM
  • Joined: 30 Jul 2004
:D I just thought of another use for the prefix: Checking for it while it's being typed. 4Dos, wasn't it?

run:notepad.exe c:\boot.ini
math:1+2*3
volume:+
winamp:+

Actually, these could be user defined "plugins", just check if the word before the colon exists as an exe-file, and run it with the parameters.

math.ahk compiled as math.exe:
;math.ahk compiled as math.exe
input=%1%
answer:=input
MsgBox,%1%=%answer%
Return

Skrommel

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
Interesting idea, but math.ahk (or math.exe) needs to be more complicated. There is no run time parser in AHK, so what you would see is 1+2=1+2. It is not terribly difficult to parse a math expression, with parenthesis and function handling, but I’d like see it done in less than a full page of code.