def Add_Function(lines, sub_n, fname): # This function is passed a list of lines. The first non-comment line must define the header # first let's parse out the header to get the name and the parameters name, params, lin = Get_Name_And_Params(lines, sub_n, fname) if isinstance(params, str): return False, name, params NewCommand = Subroutine(name, params, lines) # Create a new command object for this subroutine if NewCommand: if NewCommand.name in scripts.VALID_COMMANDS: # does this command already exist? old_cmd = scripts.VALID_COMMANDS[NewCommand.name] # get the command we will be replacing else: old_cmd = None # if not, nothing to replace try: scripts.Add_command(NewCommand) # Add the command before we parse (to allow recursion) script_validation = NewCommand.btn.Validate_script()# and validate with the internal btn held in the command. except: print("[subroutines] Fatal error while attempting to validate script.\nPlease see LPHK.log for more information.") raise if script_validation != True: # if thre is an error in validation if old_cmd: # and there is a replaced command scripts.Add_command(NewCommand) # put the old command back pass # @@@ there must be more to do! :-) This is the error return else: pass # @@@ this is the success return. There must be more to do! return True, NewCommand.name, params
" - Too many arguments for command '" + split_line[0] + "'.", btn.Line(idx)) try: temp = float(split_line[1]) except: return ("Line:" + str(idx + 1) + " - Delay time '" + split_line[1] + "' not valid.", btn.Line(idx)) return True def Run( self, btn, idx: int, # The current line number split_line # The current line, split ): print("[" + lib + "] " + btn.coords + " Line:" + str(idx + 1) + " Delay for " + split_line[1] + " seconds") delay = float(split_line[1]) if not btn.Safe_sleep(delay): return -1 return idx + 1 scripts.Add_command(Pause_Delay()) # register the command
except: rval = dialog.DR_ABORT # otherwise we'll substitute an abort code if rval == dialog.DR_OK: # if we got OK self.Set_param( btn, 2, dialog.DR_OK) # set the return value to OK (if we can) elif self.Param_count( btn) == 2: # otherwise, if there were 2 parameters self.Set_param(btn, 2, dialog.DR_CANCEL) # return cancel else: # if only 1 parameter and no return parameter btn.root.thread.kill.set() # then kill the thread return -1 scripts.Add_command(Dialog_Ok_Cancel()) # register the command # class that defines an info dialog command class Dialog_Info(command_base.Command_Basic): def __init__(self, ): super().__init__( "DIALOG_INFO, A simple informational dialog", LIB, ( # Desc Opt Var type p1_val p2_val ("Title", False, AVV_NO, PT_STR, None, None), ("Message", False, AVV_NO, PT_STR, None, None), ), ( # How to log runtime execution
def Partial_run_step_get(self, ret, btn, idx, split_line): # This gets the values as normal, then modifies them as required ret = super().Partial_run_step_get(ret, btn, idx, split_line) link = split_line[1] if "http" not in link: split_line[1] = "http://" + link return ret def Process(self, btn, idx, split_line): webbrowser.open(btn.symbols[SYM_PARAMS][1]) scripts.Add_command(External_Web()) # register the command # ################################################## # ### CLASS External_Web_New ### # ################################################## # class that defines the WEB_NEW command. @@@ this should be updated to use the more modern interface class External_Web_New(External_Web): def __init__(self, ): super().__init__() self.name = "WEB_NEW" # the name of the command as you have to enter it in the code self.info_msg = " Open website '{1}' in a new browser"
# Dummy validate routine. Simply says all is OK (unless you try to do it in a real button!) def Validate( self, btn, idx: int, # The current line number split_line, # The current line, split pass_no # interpreter pass (1=gather symbols & check syntax, 2=check symbol references) ): if pass_no == 1: if btn.is_button: return ("Line:" + str(idx+1) + " - The header '" + split_line[0] + "' is only permitted in a subroutine.", btn.Line(idx)) return True scripts.Add_command(Header_Sub_Name()) # register the header # ################################################## # ### CLASS Subroutine_Define ### # ################################################## # class that defines the CALL:xxxx command (runs a subroutine). This parses the routine (pass 1 and 2 validation) # and adds it as a command if the parsing suceeds. It can then be called just like any other command class Subroutine(command_base.Command_Basic): def __init__( self, Name, # The name of the command Params, # The parameter tuple Lines # The text of the subroutine/function ):
pass_no # interpreter pass (1=gather symbols & check syntax, 2=check symbol references) ): if pass_no == 1: if idx > 0: # headers normally have to check the line number return ("Line:" + str(idx + 1) + " - " + self.name + " must appear on the first line.", btn.Line(0)) if len(split_line) > 1: return ("Line:" + str(idx + 1) + " - " + self.name + " takes no arguments.", btn.Line(idx)) return True scripts.Add_command(Header_Async()) # register the header # ################################################## # ### CLASS Header_Simple ### # ################################################## class Header_Simple(command_base.Command_Header_Run): def __init__(self, ): super().__init__( "@SIMPLE" ) # the name of the header as you have to enter it in the code def Validate( self,
def Partial_run_step_info(self, ret, btn, idx, split_line): print( AM_PREFIX.format(self.lib, btn.coords, str(idx + 1)) + " Wait for script key to be unpressed") def Process(self, btn, idx, split_line): while lp_events.pressed[btn.x][btn.y]: sleep(DELAY_EXIT_CHECK) if btn.Check_kill(): return idx + 1 return idx + 1 scripts.Add_command(Keys_Wait_Pressed()) # register the command # ################################################## # ### CLASS Keys_Tap ### # ################################################## # class that defines the TAP command (tap button a button) class Keys_Tap(command_base.Command_Basic): def __init__(self, ): super().__init__( "TAP", # the name of the command as you have to enter it in the code LIB, ( # Desc Opt Var type p1_val p2_val
finally: win32process.AttachThreadInput( current_thread, fg_thread, False) # and always detatch from the other thread return res # and this is where the text cursor is def Process(self, btn, idx, split_line): x, y = self.get_cursor( ) # get x,y position of text cursor on fg window self.Set_param(btn, 1, x) # store the result self.Set_param(btn, 2, y) scripts.Add_command(Win32_Get_Caret()) # register the command # ################################################## # ### CLASS W_GET_FG_HWND ### # ################################################## # class that defines the W_GET_FG_HWND command - gets the handle of the current foreground window class Win32_Get_Fg_Hwnd(Command_Win32): def __init__(self, ): super().__init__( "W_GET_FG_HWND", # the name of the command as you have to enter it in the code LIB, ( # Desc Opt Var type p1_val p2_val
# Desc Opt Var type p1_val p2_val (trailing comma is important) ("X value", False, AVV_NO, PT_INT, None, None), ("Y value", False, AVV_NO, PT_INT, None, None), ), ( # How to log runtime execution # num params, format string (trailing comma is important) (2, " Relative mouse movement ({1}, {2})"), )) def Process(self, btn, idx, split_line): x = self.Get_param(btn, 1) y = self.Get_param(btn, 1) ms.move_to_pos(x, y) scripts.Add_command(Mouse_Move()) # register the command # ################################################## # ### CLASS Mouse_Set ### # ################################################## # class that defines the M_SET command (put the mouse somewhere) class Mouse_Set(command_base.Command_Basic): def __init__(self, ): super().__init__( "M_SET, Set mouse position", LIB, ( # Desc Opt Var type p1_val p2_val
def __init__(self, ): super().__init__( "TEST_01, Test for single optional integer constant parameter", LIB, ( # Desc Opt Var type p1_val p2_val ("Param_1", True, AVV_NO, PT_INT, None, None), ), ( # How to log runtime execution # num params, format string (trailing comma is important) (1, " Param {1}"), )) self.one = 1 scripts.Add_command(Test_01()) # register the command class Test_02(Test_XX): def __init__(self, ): super().__init__( "TEST_02, Test for single optional float constant parameter", LIB, ( # Desc Opt Var type p1_val p2_val ("Param_1", True, AVV_NO, PT_FLOAT, None, None), ), ( # How to log runtime execution # num params, format string (trailing comma is important) (1, " Param {1}"), ))
def is_global_not_def(self, symbols, cmd, cmds): # only continue if the variable is not defined globally ret = 1 ret, v = variables.next_cmd(ret, cmds) with symbols[SYM_GLOBAL][0]: # lock the globals while we do this if not variables.is_defined(v, symbols[SYM_GLOBAL][1]): return ret else: return len(cmds) + 1 def abort_script(self, symbols, cmd, cmds): # cause the script to be aborted return False scripts.Add_command(Rpn_Eval()) # register the command # ################################################## # ### CLASS RPN_SET ### # ################################################## # class that defines the RPN_SET command -- Sets a variable to a string value (or a heap of appended string values) class Rpn_Set(command_base.Command_Basic): def __init__(self, ): super().__init__( "RPN_SET", # the name of the command as you have to enter it in the code LIB, ( # Desc Opt Var type p1_val p2_val
# ################################################## # ### CLASS Control_Comment ### # ################################################## # class that defines the comment command (single quote at beginning of line) # this is special because it has some different handling in the main code # to allow it to work without a space following it class Control_Comment(command_base.Command_Text_Basic): def __init__(self, ): super().__init__("-, Comment", LIB, "-") scripts.Add_command(Control_Comment()) # register the command # ################################################## # ### CLASS Control_Label ### # ################################################## # class that defines the LABEL command (a target of GOTO's etc) class Control_Label(command_base.Command_Basic): def __init__(self): super().__init__( "LABEL, Target for jumps (goto, loops, etc)", LIB, ( # Desc Opt Var type p1_val p2_val