I would like to start a julia script by using the keyboard shortcut Ctrl+Shift+H.
When the script starts, the keys Ctrl and Shift may still be pressed (depending on how quickly I remove my fingers).
I would like to be sure that these two keys are released before executing the rest of the script. To do that I need to test if the key are pressed.
Note that triggering an event when the key are released would not be enough as the keys may not be pressed when the script starts.
I found several references to detect when a key is pressed in Julia but I did not find one to test if a key is currently pressed.
Do you know how I could do that?
Here is a minimal example of why I would like to do that.
You can find here a file in the cnee format which enables to write "azerty" in the window which has the focus. If you type the following command in a terminal, "azerty" is typed in it as expected:
cnee --replay -sp 0 -f ./recorded_macro.xnl
In order to write "azerty" in any window (not just terminals), I create a keyboard shortcut Ctrl+Shift+H which executes this command. If I use the shortcut, the keys Ctrl and Shift are likely to be pressed when the command is executed (except if I use the shortcut very quickly) and instead of typing "azerty", the window with the focus will get Ctrl+Shift+a, Ctrl+Shift+z, Ctrl+Shift+e, Ctrl+Shift+r, Ctrl+Shift+t and Ctrl+Shift+y which will trigger actions in the window but will not write "azerty".
So, I would like instead to start a python script with this shortcut which waits for Ctrl and Shift to be non-pressed before executing the cnee command. Note again that waiting for the keys to be released with a listener is not a solution as the keys Ctrl and Shift may not be pressed at the start of the python script if I use the shortcut quickly (and so I will have to press again Ctrl and Shift before executing the cnee command which I do not want).
The following Gtk program will detect the release of shift, control, and alt that are already pressed before the program starts or gets the focus. Note that my keyboard at least seems to not always detect multiple keystrokes, so perhaps depending on your keyboard you may have to just detect one of those releases.
using Gtk
function keypresswindow()
txt = "Press and Release a Key"
state = ""
win = GtkWindow("Key Release Test", 500, 30) |> (GtkFrame() |> ((vbox = GtkBox(:v)) |> (lab = GtkLabel(txt))))
function keyreleasecall(w, event)
event.keyval == 65505 && (state *= "SHIFT ")
event.keyval == 65507 && (state *= "CONTROL ")
event.keyval == 65513 && (state *= "ALT ")
set_gtk_property!(lab, :label, "You have released: $state")
end
signal_connect(keyreleasecall, win, "key-release-event")
cond = Condition()
endit(w) = notify(cond)
signal_connect(endit, win, :destroy)
showall(win)
wait(cond)
end
keypresswindow()
Related
shortcut = QtWidgets.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Shift), MayaMainWindow)
shortcut.setContext(QtCore.Qt.ApplicationShortcut)
I have a system in place for overloading Maya shortcuts, as and when needed. I want to do this with the shift key, however simply writing it as above seems to do nothing. Not even an error message.
I have tried
QtGui.QKeySequence(QtCore.Qt.Key_Shift)
QtGui.QKeySequence(QtCore.Qt.Key_Shift + QtCore.Qt.SHIFT)
QtGui.QKeySequence(QtCore.Qt.Key_Shift + QtCore.Qt.NoModifier)
QtGui.QKeySequence(QtCore.Qt.Key_Shift + QtCore.Qt.NoButton)
I want to run a custom shortcut when only the shift key is pressed.
I have a script that I'd like to use to automate processes in Audacity. I have it set up so that all the functions I want to do in Audacity are keyboard shortcuts (since I don't think Audacity uses standard window menus like is required for WinMenuSelectItem()) In other words, my whole code consists of multiple instances of the Send() command. The problem is, AutoIT executes the code too fast. I've tried using WinWait(), but the processes take variable amounts of time. I've also tried ShellExecuteWait() and RunWait()Is there a way to get it to wait until the program isn't doing something, and then execute my send commands? Here's some of my code
Run("C:\Program Files (x86)\Audacity\audacity.exe")
; wait until it's active
WinWaitActive("Audacity")
; get the dialogue box to go away
Send("{ENTER}")
RunWait("Audacity")
; open files
Send("^o")
RunWait("Audacity")
; open the certain file & press enter
Send("test.wav")
RunWait("Audacity")
Send("{ENTER}")
RunWait("Audacity")
; select left boundary of silence period
Send("[")
RunWait("Audacity")
Send("000000100{ENTER}")
RunWait("Audacity")
; select right boundary of silence period
Send("]")
RunWait("Audacity")
Send("200000000{ENTER}")
RunWait("Audacity")
; Use for debugging issues. Systray icon show current line.
Opt('TrayIconDebug', 1)
; Delay default: 250s
Opt('WinWaitDelay', 400)
; Delay default: 5s
Opt('SendKeyDelay', 100)
; Path of the wav file.
$sInFile = #WorkingDir & '\test.wav'
; Optional permanent change of splash screen setting.
_SplashScreen(True)
; Run Audacity and argument of the wav file.
$iPid = Run('"C:\Program Files (x86)\Audacity\audacity.exe" "' & $sInFile & '"')
; Check if Run Audacity failed.
If #error Then
MsgBox(0x40030, #ScriptName, 'Failed to run Audacity')
Exit 1
EndIf
; Wait for main window to get handle. Title is the filename with no extension.
$hMainWindow = WinWait('[TITLE:test; CLASS:wxWindowNR]', '', 10)
; Check allowed timeout of window.
If Not $hMainWindow Then
MsgBox(0x40030, #ScriptName, 'Audacity window not detected.')
Exit 1
EndIf
; If splash screen setting not 0 then handle the window.
If _SplashScreen() Then
AdlibRegister('_WelcomeWindow')
WinWait('Welcome to Audacity', '', 3)
AdlibUnRegister('_WelcomeWindow')
EndIf
; Send '[' to main window to trigger Left Boundary window.
ControlSend($hMainWindow, '', '', '[')
; Get handle of Left Boundary window.
$hMsgWindow = WinWait('Set Left Selection Boundary', '', 5)
; Check allowed timeout of window.
If Not $hMsgWindow Then
MsgBox(0x40030, #ScriptName, 'Selection Boundary window not detected.')
Exit 1
EndIf
; Activate window, set time and click OK.
If WinActivate($hMsgWindow) Then
ControlSend($hMsgWindow, '', 'wxWindowNR1', '{LEFT 3}1'); 1000
ControlClick($hMsgWindow, '', 'Button2'); OK
EndIf
; Send ']' to main window to trigger Right Boundary window.
ControlSend($hMainWindow, '', '', ']')
; Get handle of Right Boundary window.
$hMsgWindow = WinWait('Set Right Selection Boundary', '', 5)
; Check allowed timeout of window.
If Not $hMsgWindow Then
MsgBox(0x40030, #ScriptName, 'Selection Boundary window not detected.')
Exit 1
EndIf
; Activate window, set time and click OK.
If WinActivate($hMsgWindow) Then
; Audacity shows 1000 and focus is on the 1st non zero digit which is 1.
ControlSend($hMsgWindow, '', 'wxWindowNR1', '2'); 2000
ControlClick($hMsgWindow, '', 'Button2'); OK
EndIf
; More code to do.
Sleep(1000)
MsgBox(0x40040, #ScriptName, 'End of automation.' & #CRLF & #CRLF & _
'You can close Audacity to finish.')
; Wait for Audacity process to close.
ProcessWaitClose($iPid)
Exit
Func _WelcomeWindow()
; Used by AdlibRegister to handle the Welcome window.
; Welcome window hides if closed so need to check if exist and is visible (2).
If WinExists('Welcome to Audacity') Then
If BitAND(WinGetState('Welcome to Audacity'), 2) Then
WinClose('Welcome to Audacity')
Else
AdlibUnRegister('_WelcomeWindow')
EndIf
EndIf
EndFunc
Func _SplashScreen($bDisable = False)
; Write to audacity.cfg to disable splash screen.
Local $sIniFile = #AppDataDir & '\Audacity\audacity.cfg'
If IniRead($sIniFile, 'GUI', 'ShowSplashScreen', '1') = '1' Then
If $bDisable Then
; Return 1 if ini file change is success.
If IniWrite($sIniFile, 'GUI', 'ShowSplashScreen', '0') Then
Return 1
EndIf
Else
; Return 1 if check for splash screen is enabled.
Return 1
EndIf
EndIf
EndFunc
Opt() is used to slow down the wait of windows and the sends.
Also added Opt('TrayIconDebug', 1) for debugging though if
the script is considered good then you can remove that Opt().
ControlSend() is used instead of Send() as ControlSend()
targets windows and controls based of title, text, etc.
The Opt() delays are not required though was added to
demonstrate the usage, though perhaps Audacity may struggle
to keep with the speed that AutoIt can automate.
If possible, suggest use of Control*() functions for automation.
Storing window handles in a variable can help save retyping titles
in the code. WinWait() returns a window handle which is ideal and
if the timeout parameter is used, then 0 indicates the window not
found so automation can be aborted.
The Classname of the main window is not enough on its own as
Audacity creates many invisible windows with the same Classname.
So, the title may need to be used as well. The title could be
used alone though titled by filename may not be unique at times.
See Window Titles and Text Advanced for usage.
WinActivate() is used on the Boundary windows although it
may not be needed as control*() usually do not need active
windows. Standard Msgboxes in comparison may require to be
active to accept messages sent to them.
ShellExecuteWait() and RunWait() are no good for automation
as they block the script from continuing until the executed
process has finished.
So use ShellExecute() or Run() instead.
The repetitive use of RunWait("Audacity") seems like
desperation to correct the behavior perhaps, though flawed.
Waiting for windows to appear is how to control flow and then
functions such as ControlCommand() can detect state of controls.
ControlClick() is used on the buttons.
CtrlID of Classname Button2 is used though if the script
is always for English users then you can use the text which
would be OK for the OK button.
The ProcessWaitClose($iPid) is optional.
It is sometimes useful to wait for the program
being automated to exit before the script exits.
You comment "get the dialogue box to go away" in you code
after starting Audacity. You can change the setting on the
dialogue box or Preferences -> Interface options. Advice
disabling as it is a future problem to keep handling.
I added some code to disable the setting in the
audacity.cfg file. If not preferred to disable with
_SplashScreen(True) or done manually then
the AdLibRegister('_WelcomeWindow') call will handle
closing the window. Note that the Welcome window does
not close but rather hides.
_SplashScreen(True) changes splash setting to 0 to disable the splash.
_SplashScreen(False) or _SplashScreen() does no change of settings.
The call returns 1 if splash is enabled else 0.
Is there anything like Console.ReadKey from .NET in Eiffel on Windows?
I need a way to read input from the console without waiting for the user to press Enter.
The function io.read_character cannot be used because it blocks until the user presses Enter.
As explained in answers on SO (here or here) as well as elsewhere, there is no portable way to read a character from a console without waiting. However you can easily use any of the approaches listed in the links by interfacing to external code from Eiffel. The following example demonstrates how to do it on Windows:
read_char: CHARACTER
-- Read a character from a console without waiting for Enter.
external "C inline use <conio.h>"
alias "return getch ();"
end
Then the feature read_char can be called from your code as a regular one:
from
io.put_string ("Press q or Esc to exit.")
io.put_new_line
until
c = 'q' or c = '%/27/'
loop
c := read_char
io.put_string ("You pressed: ")
if c = '%U' or c = '%/224/' then
-- Extended key is pressed, read next character.
c := read_char
io.put_string ("extended key ")
io.put_natural_32 (c.natural_32_code)
else
io.put_character (c)
end
io.put_new_line
end
I'm trying to do a fancy-shmancy tweak in my Tiny Core Linux command line. I decorated my PS1 like this:
http://i.stack.imgur.com/iEBx2.jpg
But here is what I get in most cases:
http://i.stack.imgur.com/FN4dv.png
If I press Tab or Up\Down to scroll history it prints new PS1 strings on top of previous. On the other hand when I press Enter to run a command it prints a new line and it's all OK.
I'm running the Almquist shell (ash, not bash).
Can I implement the next algorithm:
1. If the last key pressed was Enter, then... (do nothing)
2. Else if the last key pressed was another key, then... (position the text pointer one line up to redraw the previous PS1.)
I would implement this right inside the PS1 definition. But how can I get the last key pressed before some action (when the PS1 is printed) using only ash variables and commands?
I want to pause my R script until the user presses a key.
How do I do this?
As someone already wrote in a comment, you don't have to use the cat before readline(). Simply write:
readline(prompt="Press [enter] to continue")
If you don't want to assign it to a variable and don't want a return printed in the console, wrap the readline() in an invisible():
invisible(readline(prompt="Press [enter] to continue"))
Method 1
Waits until you press [enter] in the console:
cat ("Press [enter] to continue")
line <- readline()
Wrapping into a function:
readkey <- function()
{
cat ("Press [enter] to continue")
line <- readline()
}
This function is the best equivalent of Console.ReadKey() in C#.
Method 2
Pause until you type the [enter] keystroke on the keyboard. The disadvantage of this method is that if you type something that is not a number, it will display an error.
print ("Press [enter] to continue")
number <- scan(n=1)
Wrapping into a function:
readkey <- function()
{
cat("[press [enter] to continue]")
number <- scan(n=1)
}
Method 3
Imagine you want to wait for a keypress before plotting another point on a graph. In this case, we can use getGraphicsEvent() to wait for a keypress within a graph.
This sample program illustrates the concept:
readkeygraph <- function(prompt)
{
getGraphicsEvent(prompt = prompt,
onMouseDown = NULL, onMouseMove = NULL,
onMouseUp = NULL, onKeybd = onKeybd,
consolePrompt = "[click on graph then follow top prompt to continue]")
Sys.sleep(0.01)
return(keyPressed)
}
onKeybd <- function(key)
{
keyPressed <<- key
}
xaxis=c(1:10) # Set up the x-axis.
yaxis=runif(10,min=0,max=1) # Set up the y-axis.
plot(xaxis,yaxis)
for (i in xaxis)
{
# On each keypress, color the points on the graph in red, one by one.
points(i,yaxis[i],col="red", pch=19)
keyPressed = readkeygraph("[press any key to continue]")
}
Here you can see the graph, with half of its points colored, waiting for the next keystroke on the keyboard.
Compatibility: Tested under environments use either win.graph or X11. Works with Windows 7 x64 with Revolution R v6.1. Does not work under RStudio (as it doesn't use win.graph).
Here is a little function (using the tcltk package) that will open a small window and wait until you either click on the continue button or press any key (while the small window still has the focus), then it will let your script continue.
library(tcltk)
mywait <- function() {
tt <- tktoplevel()
tkpack( tkbutton(tt, text='Continue', command=function()tkdestroy(tt)),
side='bottom')
tkbind(tt,'<Key>', function()tkdestroy(tt) )
tkwait.window(tt)
}
Just put mywait() in your script anywhere that you want the script to pause.
This works on any platform that supports tcltk (which I think is all the common ones), will respond to any key press (not just enter), and even works when the script is run in batch mode (but it still pauses in batch mode, so if you are not there to continue it it will wait forever). A timer could be added to make it continue after a set amount of time if not clicked or has a key pressed.
It does not return which key was pressed (but could be modified to do so).
R and Rscript both send '' to readline and scan in non-interactive mode (see ? readline). The solution is to force stdin using scan.
cat('Solution to everything? > ')
b <- scan("stdin", character(), n=1)
Example:
$ Rscript t.R
Solution to everything? > 42
Read 1 item
The function keypress() from the package keypress reads a single key stroke instantly, without having to hit enter.
However, it only works in the Unix/OSX terminal or Windows command line. It does not work in Rstudio, the Windows R GUI, an emacs shell buffer etc.
This answer is similar to that of Simon's, but does not require extra input other than a newline.
cat("Press Enter to continue...")
invisible(scan("stdin", character(), nlines = 1, quiet = TRUE))
Using nlines=1 instead of n=1, the user can simply press enter to continue the Rscript.
A way of doing it (kinda, you have to press a button rather than a key, but close enough) is to use shiny:
library(shiny)
ui <- fluidPage(actionButton("button", "Press the button"))
server <- function(input, output) {observeEvent(input$button, {stopApp()})}
runApp(shinyApp(ui = ui, server = server))
print("He waited for you to press the button in order to print this")
To my experience, this has a unique characteristic: even if you ran a script that had code written following the runApp function, it will not run until you've pressed the button in the app (button that stops the apps from inside using stopApp).