Author |
Topic |
|
gopikrish2000
34 Posts |
Posted - 11/07/2013 : 13:58:52
|
Below script will give a popup of recent 15 copies (configurable) which you have done through copy gestures (not ctrl +c , create new gesture for copy as below ) And upon clicking on item will send the text to the last focused window like notepad , browser input box etc. This is very useful for people who does multiple copies and want to paste one of the recent copy which is not the last one.
Following are the things you need to do to make it work . 1. First create a file "temp.txt" (without quotes) in the same folder as StrokesPlus.exe is there will all possible permissions ( read , write ... ) 2. Create a copy gesture with code
acSendKeys("^c")
local recentCopyText = acGetClipboardText()
addClipItem(recentCopyText)
3. Create a Recent copies popup gestures with code
local res = renderCopyPopup()
local swnd = acFindWindow("STROKESPLUS",nil)
acActivateWindow(swnd)
acDelay(100)
acPostMessage(swnd, 0x0000, 0, 0)
acDelay(100)
acCreatePopupMenu(gex,gey, res, ",","popupMenuForCopy")
4. Add following code to your Global lua tab of file
pattern = "||"
fileToBeStored = "temp.txt"
lines = {}
function file_exists(file)
local f = io.open(file, "r")
if f then f:close() end
return f ~= nil
end
function lines_from(file)
if not file_exists(file) then return {} end
local matchCountAry = {}
local fi = io.open("temp.txt","r")
local completeStr = fi:read("*all")
fi:close()
for i in string.gmatch(completeStr, "([^"..pattern.."]+)") do
matchCountAry[#matchCountAry + 1] = i
end
--acMessageBox(matchCountAry[2])
return matchCountAry
end
function addClipItem(item)
if string.len(item) <= 0 then
return
end
for k,v in pairs(lines) do
if v == item then
return
end
end
if #lines >= 15 then
for index = 2,15 do
lines[index] = lines[index-1]
end
lines[15] = item
else
lines[#lines+1] = item
end
local writingStr = ""
for k,v in pairs(lines) do
if string.len(v) > 0 then
writingStr = writingStr..v..pattern
end
end
local fi = io.open("temp.txt","w")
if string.len(writingStr) > 0 then
fi:write(writingStr)
end
fi:close()
end -- end of clipItem method
function popupMenuForCopy(id)
acActivateWindow(acGetOwnerWindowByPoint(gsx, gsy))
local itemVal = lines[id]
if itemVal then
local prevCopyVal = acGetClipboardText()
acSetClipboardText(itemVal)
acSendKeys("{DELAY 100}^v")
acSetClipboardText(prevCopyVal)
end
end
function renderCopyPopup()
local result = ""
for k,v in pairs(lines) do
v = string.sub(v,0,20)
result = result..v..","
end
return result
end
function sp_init()
lines = lines_from(fileToBeStored)
end
5. Note if sp_init() function is already be present in your global lua then add lines = lines_from(fileToBeStored) line to that , ie ( you shouldn't have two methods of sp_init())
6. If you copy big text , in popup i'm trimming to first 20 characters and showing otherwise popup willn't look good ( but on clicking will paste complete result)
7. If above thing is done correctly , then use copy gesture (of point 2 ) and do some copies then do recent copy gesture to show popup and upon clicking on item will send that text to last focused window like notepad,firefox search input etc. (acSendKeys(<item clicked text>) [ Also check the file text.txt , every time you copy using copy gesture the copied text should be appended there ]
Actually I didn't found a clipboard change event or listener kind of thing in lua other wise you can track the copies of ctrl+c as well |
Edited by - gopikrish2000 on 11/09/2013 02:11:08 |
|
Rob
USA
2615 Posts |
Posted - 11/07/2013 : 14:19:56
|
Nice work!
You are correct, the proper way of monitoring the Windows clipboard is via SetClipboardViewer which requires a window handle and that window to receive and process the WM_DRAWCLIPBOARD and WM_CHANGECBCHAIN messages (sent each time the clipboard contents or chain has changed).
I'd like to note that sp_init() is only executed in Lua state 1 as it was intended only to be executed once on load, but not for anything which affects data within Lua states; see here for details.
Although, 95% of the time, you'll be executing in Lua state 1 anyway, but I wanted to make sure I mentioned this fact.
You should be able to simply put the following line in Global Lua (not within sp_init() or any other function):lines = lines_from(fileToBeStored) This will execute within both Lua states; and since you're saving the file each time a clip is added, there's no harm in the code being executed again when you click OK on the S+ window or otherwise reload the Lua states. Though, I haven't tested it out.
Very handy script, though! |
|
|
gopikrish2000
34 Posts |
Posted - 11/07/2013 : 14:34:04
|
I want to keep it in sp_init() because you should not unnecessarily do I/O operations unless very much required , also user's should not change the text in temp.txt directly ( if they do they have to reload/apply it , that's fine because they r tweaking) . So it shouldn't effect performance of all users who r using.
Only copy i'm putting it in file because i didn't find any sp_close() function which will be called once S+ closes , so OK i guess.
I still have problems in displaying the exact copied text because in acSendKeys() special characters we need to replace before insertion ( see convertItemAccordingToRules() ) , still some of the special characters after replacing also not working ( not sure why ) but general text copies shouldn't have problem. |
|
|
Rob
USA
2615 Posts |
Posted - 11/08/2013 : 15:15:10
|
You could always call acSetClipboardText(value) then acSendKeys("^v") to avoid converting characters. |
|
|
gopikrish2000
34 Posts |
Posted - 11/09/2013 : 01:58:31
|
Yes working like a charm , I didn't got this idea , Thanks . I'm modifying above script |
Edited by - gopikrish2000 on 11/09/2013 02:04:28 |
|
|
chandisciple
75 Posts |
Posted - 03/22/2016 : 01:22:44
|
Another amazing code ! thanks GopiKrish.
I followed everything from the first post and did not make the changes suggested by ROB. Because i am not sure where to make the change. So i skipped , acSetClipboardText(value) then acSendKeys("^v") to avoid converting characters lines = lines_from(fileToBeStored)
The script works fine until i select one from the pop up window, it does not take the focus to where i executed the paste gesture and so does not pate the selected line anywhere !
Can anyone help on this please ? Also , where would i add the lines suggested by ROB ? |
Edited by - chandisciple on 03/22/2016 20:10:47 |
|
|
chandisciple
75 Posts |
Posted - 03/22/2016 : 20:11:13
|
Rob :May i please request your help here. :) |
|
|
Rob
USA
2615 Posts |
Posted - 03/22/2016 : 22:27:37
|
Changed the line in red in this function:function popupMenuForCopy(id)
acActivateWindow(acGetOwnerWindowByPoint(acGetMouseLocationX(), acGetMouseLocationY()))
local itemVal = lines[id]
if itemVal then
local prevCopyVal = acGetClipboardText()
acSetClipboardText(itemVal)
acSendKeys("{DELAY 100}^v")
acSetClipboardText(prevCopyVal)
end
end I haven't tested it out thoroughly, but it fixed it for me. The problem is that the original was referencing gsx and gsy, but those variables are not in scope within that function at that time. So this updates it to activate the window at the current mouse location. |
|
|
chandisciple
75 Posts |
Posted - 03/23/2016 : 01:47:51
|
Cooooooool , i am modifying the script. it works but i see some extra clip board line. i will figure it out and update you .
But can you give a script to erase all in the pop up menu ? That I can trigger with another gesture to add new clip items ? |
|
|
Rob
USA
2615 Posts |
Posted - 03/23/2016 : 10:10:34
|
Made these changes to address timing and getting rid of the blank menu item:function popupMenuForCopy(id)
acActivateWindow(acGetOwnerWindowByPoint(acGetMouseLocationX(), acGetMouseLocationY()))
acDelay(50)
local itemVal = lines[id]
if itemVal then
local prevCopyVal = acGetClipboardText()
acSetClipboardText(itemVal)
acSendKeys("{DELAY 100}^v")
acSetClipboardText(prevCopyVal)
end
end
function renderCopyPopup()
local result = ""
local delim = ""
for k,v in pairs(lines) do
v = string.sub(v,0,20)
result = result..delim..v
delim = ","
end
return result
end You should be able to use something like this to erase the file:local fi = io.open("temp.txt","w")
fi:write("")
fi:close()
lines = {}--clear the lines in the variable since S+ is running That's about as much as I'm going to spend on this! :) Google is your friend, and definitely practice scripting using many of the websites out there. Remember that S+ uses Lua, so always include that in your search, like last night I searched for "Lua trim string" to find the script to trim the whitespace.
Best of luck! |
|
|
chandisciple
75 Posts |
Posted - 03/24/2016 : 00:05:25
|
All the above script worked perfectly ROB.
Thanks and yes will start practicing more on lua !!! Thanks appreciate your effort :):):) |
|
|
|
Topic |
|
|
|