I'm trying to make a useful system to automatically increase numbers in selected text. For example, when I working in Zbrush on the project named "Example_character012" I have a folder with 23 files from "Example_character012_prj_01.zpr" to "Example_character012_prj_23.zpr". When I need to save next iteration I'm pressing "ctrl+s" and then regular saving screen opens in the last working directory with preselected filename text, in this scenario it would be "Example_character012_prj_23.zpr". I need to copy this text, select the last number(23) increase it by one, and past it all the text back to the text-field. In this case it would be "Example_character012_prj_24.zpr".
This kind of script would be really useful in all kinds of scenario, mainly with saving in different programs.
I tried to made it myself and come up with this:
^!Numpad1::
Sleep 100
Send ^c
Sleep 10
RegExMatch(clipboard,"(\d+)(?!.*\d)",Number)
NewNumber:=Number1+1
OldNumber:=NewNumber-1
Clipboard:=RegExReplace(clipboard, OldNumber, NewNumber)
Sleep 10
Send ^v
Sleep 10
Send +{Home}
Return
^!Numpad0::
Sleep 100
Send ^c
Sleep 10
RegExMatch(clipboard,"(\d+)(?!.*\d)",Number)
NewNumber:=Number1-1
OldNumber:=NewNumber+1
Clipboard:=RegExReplace(clipboard, OldNumber, NewNumber)
Sleep 10
Send ^v
Sleep 10
Send +{Home}
Return
Ctrl+alt+Num1 for increase and Ctrl+alt+Num0 for decrease.
It's work fine with in the simplest scenario, but have significant problems I can't solve myself:
It only works in english keyboard-layout. When I use it in russian layout - it puts "cv" instead of pasting(If I paste manually afterwards it put the correct text)
Sometimes it increases not only the last number "Example_character012_prj_01.zpr" changing to "Example_character022_prj_02.zpr" instead of "Example_character012_prj_02.zpr"
Zeros working incorrectly "Example_prj_09.zpr" changing to "Example_prj_010.zpr" instead of "Example_prj_10.zpr"
After pasting it selects the whole line instead of only what just have been pasted
If it's possible, it would be great to make it work without affecting clipboard at all.
Sometimes some keys like "ctrl" just get stuck until being clicked manually for some reason.
Edit:
Got some help at Autohotkey forums, current version of script below. Only questions 4 and 5 left.
^!Numpad1::
^!Numpad0::
Sleep 50
Send {Ctrl up}^{Ins}
Sleep 10
RegExMatch(Clipboard, "^(.*)(?=_)_(\d+)(\....)$", Match)
Len := StrLen(Match2)
if InStr(A_ThisHotkey, 1)
Match2++
else
Match2--
if (StrLen(Match2) < Len)
Match2 := Format("{:0" Len "}", Match2)
Clipboard := Match1 "_" Match2 Match3
Sleep 10
Send +{Ins}
Sleep 10
Send +{Home}
Return
The reason your CTRL key is misbehaving is maybe because:
If you have a hotkey like
^F12::
Send {a}
What actually happens when you hit CTRL+F12 is that AHK releases CTRL, sends a, then re-hits CTRL.
This can get more complicated, eg in your scenario.
Try prefixing your Send commands with {Blind} eg Send {Blind}^v to suppress this behavior.
This may or may not work (ie if the hotkey is shift+ctrl+something but the hotkey sends ctrl+v, then what would actually get sent is ctrl+shift+v) but if it does still work, it may make CTRL start behaving itself more.
Related
In my output there are certain lines that are refreshed every few seconds. If I resize the terminal by clicking F11, then output is just as I wanted. If terminal isn't big enough some long lines that are refreshed are splitted in two, and because of that, only one part of line is refreshed, and every time line is refreshed I also get new line.
This could be easily avoided if I could specify default size of terminal (resize terminal from my program). Also it would be great if I could forbid user to change terminal size while program is running.
while(1)
{
cout<<"Long line that is refreshed every 5s... \r";
//if line is splited in two lines, \r will return to beginning of that new line
//and the first part of original line would stay as it is(won't be rewrited)
sleep(5);
}
How do I specify a terminal size or stop terminal resizing?
Some terminal emulators (including the default macOS Terminal.app) support being resized/moved/etc in response to printed control sequences. The sequences are fairly standard but not all terminal emulators implement all of them.
For example:
# set terminal width to 50, height to 100
cout << "\e[8;50;100t";
This answer includes an overview of some other available control sequences.
I don't think you can forbid the user to change the terminal size. A better way would be to catch the SIGWINCH signal that is sent to the process everytime the window size is changed, and use the TIOCGWINSZ / TIOCGSIZE ioctl() to get the dimensions.
The code below works, with two things I cant figure out how to fix:
1. Default Win + Tab behavior is broken.
2. The Thumbnails are cycled in the wrong order. How could I keep the script as it is now, but also add another shortcut combination (say Alt + `) to cycle in the correct order.
BTW: I have added an {Enter} after Alt is realeased, so the script automatically activates the desired window.
$*Tab::
WinActivate, ahk_class Shell_TrayWnd ;this is used to bring focus out of the current window
Getkeystate, Laltstate, Lalt, P
if Laltstate = D
{
Send {Blind}{LAlt up}{LWin down}{T}
ifequal FixB, 0, Send {T}
FixB = 1
}
else
Send {Blind}{T}
return
~$*LAlt up::
Send {Blind}{Lwin up}{Enter}
FixB = 0
return
You say that this works, but I would expect your Tab key to always produce a T unless the Alt key is down. If you try to insert a tab within a Notepad document, I would expect you to instead type T.
$*Tab:: indicates that hitting Tab will trigger this hotkey, no matter what else is held down. Thus, when you hold down the Win key and hit Tab, you're sending Win+T instead with your else Send {Blind}{T} code.
You are cycling in reverse order because you're using an upper-case T in your Send statement. Send T or Send {T} are sending t along with shift, which reverses the order. Just send t instead, and you'll go in the correct order.
I'm struggling with the following thing. I have a simple script, that points to a word with mouse, clicks on it, does copy (ctrl+c), then does paste (ctrl+v).
Now, when a copy is done, I need to trim the text in the buffer/clipboard, meaning delete either beginning space (if any) or ending space (if any) - or both. Here's the code I have so far (I list only relevant part):
MouseMove, 439, 219
Click 2
Send ^c
ClipWait
clipboard := RegexReplace(clipboard, "^\s+|\s+$")
clipboard := Trim(clipboard," \`t\`r\`n")
clipboard := LTrim(clipboard, OmitChars = " \`t\`r\`n")
clipboard := RTrim(clipboard, OmitChars = " \`t\`r\`n")
StringReplace, clipboard, clipboard, \`t\`r\`n, , All
StringReplace, clipboard, clipboard, %A_Space%, , All
Send ^v
As you can see I used all the possible options I could find, and STILL the space does not get removed. But also, the strange thing is sometimes the space is removed, but in around 40% of cases it's not. But in any case, I simply need to a solution that would trim/remove spaces in all cases (every single time).
Any ideas, suggestions?
Your code seems to work for me. This leads be to believe it has something to do with the timing of your clipboard contents. The likely culprit of your problem is your usage of ClipWait. The most reliable way to use it is to clear out your clipboard first, then copy, then use ClipWait with a timeout value. Here is some example usage.
clipboard := "" ; Clear clipboard
Send ^c
ClipWait, 10 ; Waits 10 seconds for clipboard to contain something
Msgbox % clipboard
I'm developing a Windows Console Application, using Visual Studio 2010, which prints progress percentage on screen such that the last number gets overwritten with the current number. I'm using carriage return to achieve this like so:
std::wcout
<< "[Running: "
<< std::setw(3)
<< std::setprecision(3)
<< percent
<< "%]"
<< '\r'
;
When I execute this program through PowerShell on a remote host using PSSesion:
Enter-PSSession WWW.XXX.YYY.ZZZ -credential <UserName>
[WWW.XXX.YYY.ZZZ]: PS C:\> .\test.exe
it behaves differently compared to when its executed locally either in PowerShell or in cmd.exe. I face following three problems:
1) The console output of the program is different, in that, instead of overwriting [Running xx%] its printing in the next line like so:
[Running 1%]
[Running 2%]
[Running 3%]
[Running 4%]
...
This is similar to what happens when output of a program is redirected to a file (lone carriage returns or newlines are replaced with carriage returns+newlines combinations).
2) The output doesn't shows up as and when the program writes something to cout. It comes at once at the end of execution. Does powershell caches the output of remote program and sends to the caller only once? If there is significant time difference between two lines (line meaning all the output between two newlines) then the first line gets printed as if it waits for some time for another newline and if received, it again goes to waiting state, if not received within certain time period (~500ms), it sends the output till last newline (and not all the accumulated output) to the caller. As can be seen from my code, there is no newline resulting in all the [Running xx%] being printed at once at the end.
3) At certain point in the program I need user's confirmation, but cin.fail() returns true in remote execution. So, is there any way to take user input in such an execution environment? Or is there any way to detect that the program is being executed remotely through Powershell (eg. some env variable)?
Any help related to any point will be greatly appreciated. :)
With respect to 1), the WinRM protocol for PowerShell Remoting is really just an input/output stream for commands and their serialized output. It has no terminal emulation capabilities, so when you run things remotely, their output is fed back sequentially one line at a time. If you used SSH or Telnet to a remote shell of powershell.exe, you would likely see what you expect.
As for 2), the default output buffermode appears to be "Block" so this would explain the behaviour you're seeing. You can change this with the New-PSSessionOption cmdlet to create a configuration for a session created by New-PSSession that can be passed to the -Session parameter on remoting aware cmdlets. The option is OutputBufferingMode. If you set it to None, you should get the desired behaviour.
# default output buffering mode is "none" for default options
$s = new-pssession localhost -sessionoption (new-pssessionoption)
enter-pssession $s
For 3), you should be able to accept input interactively IIRC. Looks like interactive stuff doesn't work right - I may have completely misremembered this.
I use the following lines to output my simulation's progress info in my c++ program,
double N=0;
double percent=0;
double total = 1000000;
for (int i; i<total; ++i)
{
percent = 100*i/total;
printf("\r[%6.4f%%]",percent);
}
It works fine!
But the problem is I see the terminal cursor keeps blinking cyclically through the numbers, this is very annoying, anyone knows how to get rid of this?
I've seen some programs like wget or ubuntu apt, they use progress bar or percentages too, but they seems no blinking cursor issue, I am wondering how did they do that?
Thanks!
You can hide and show the cursor using the DECTCEM (DEC text cursor enable mode) mode in DECSM and DECRM:
fputs("\e[?25l", stdout); /* hide the cursor */
fputs("\e[?25h", stdout); /* show the cursor */
Just a guess: try to use a proper number of '\b' (backspace) characters instead of '\r'.
== EDIT ==
I'm not a Linux shell wizard, but this may work:
system("setterm -cursor off");
// ...display percentages...
system("setterm -cursor on");
Don't forget to #include <cstdlib> or <iostream>.
One way to avoid a blinking cursor is (as suggested) to hide the cursor temporarily.
However, that is only part of the solution. Your program should also take this into account:
after hiding the cursor and modifying the screen, before showing the cursor again move it back to the original location.
hiding/showing the cursor only keeps the cursor from noticeably blinking when your updates take only a small amount of time. If you happened to mix this with some time-consuming process, your cursor will blink.
The suggested solution using setterm is not portable; it is specific to the Linux console. And running an executable using system is not really necessary. But even running
system("tput civis");
...
system("tput cnorm");
is an improvement over using setterm.
Checking the source-code for wget doesn't find any cursor-hiding escape sequences. What you're seeing with its progress bar is that it leaves the cursor in roughly the same place whenever it does something time-consuming. The output to the terminal takes so little time that you do not notice the momentary rewrite of the line (by printing a carriage return, then writing most of the line over again). If it were slower, then hiding the cursor would help — up to a point.
By the way — this cursor-hiding technique is used in the terminal drivers for some editors (vim and vile).
Those apps are probably using ncurses. See mvaddstr
The reason the cursor jumps around is because stdout is buffered, so you don't know actually how many characters are being printed at some point in time. The reason wget does not have a jumping cursor is that they are actually printing to stderr instead, which is unbuffered. Try the following:
fprintf(stderr, "\r[%6.4f%%]", percent);
This also has the advantage of not cluttering the file if you are saving the rest of the output somewhere using a pipe like:
$ ./executable > log.data
Press insert key...if that doesn't work then press the fn key in your keyboard.
This will definitely work
Hope this helps