Added modular directory structure.
[hooke.git] / hooke / plugin / macro.py
1 '''
2 COMMAND MACRO PLUGIN FOR HOOKE
3
4 Records, saves and executes batches of commands
5 (c)Alberto Gomez-Casado 2008
6 '''
7
8 import os.path
9 import string
10
11 from .. import libhookecurve as lhc
12 from .. import libinput as linput
13
14 class macroCommands(object):
15
16         currentmacro=[]
17         pause=0
18         auxprompt=[]
19         macrodir=None
20         
21
22         def _plug_init(self):
23                 self.currentmacro=[]
24                 self.auxprompt=self.prompt
25                 self.macrodir=self.config['workdir']
26                 if not os.path.exists(os.path.join(self.macrodir,'macros')):
27                     try:
28                         os.mkdir('macros')
29                     except:
30                         print 'Warning: cannot create macros folder.'
31                         print 'Probably you do not have permissions in your Hooke folder, use macro at your own risk.'
32                 self.macrodir=os.path.join(self.macrodir,'macros')
33
34         def collect(self):
35                                 
36                 print 'Enter STOP / PAUSE to go back to normal mode\nUNDO to remove last command'
37                 line=[]
38                 while not(line=='STOP' or line=='PAUSE'):
39                         line=raw_input('hooke (macroREC): ')
40                         if line=='PAUSE':
41                                 self.pause=1
42                                 self.prompt='hooke (macroPAUSE): '
43                                 break
44                         if line=='STOP':
45                                 self.prompt=self.auxprompt
46                                 self.do_recordmacro('stop')
47                                 break
48                         if line=='UNDO':
49                                 self.currentmacro.pop()
50                                 continue
51                         param=line.split()
52
53                         #FIXME check if accessing param[2] when it doesnt exist breaks something
54                         if param[0] =='export':
55                                 exportline=param[0]+' __curve__ '
56                                 if len(param)==3:
57                                         exportline=exportline+param[2]
58                                 self.currentmacro.append(exportline)
59                                 self.onecmd(line)
60                                 continue
61                         
62                         if param[0] =='txt':
63                                 exportline=param[0]
64                                 if len(param)==3:
65                                         exportline=exportline+' '+param[2]
66                                 exportline=exportline+'__curve__'
67                                 self.currentmacro.append(exportline)
68                                 self.onecmd(line)
69                                 continue
70
71                         self.onecmd(line)
72                         
73                         self.currentmacro.append(line)
74                 
75
76         def do_recordmacro(self, args):
77                 '''RECORDMACRO
78                 Stores input commands to create script files
79                 -------
80                 Syntax: recordmacro [start / stop]
81                 If a macro is currently paused start resumes recording
82                 '''
83                 
84                 
85                 if len(args)==0:
86                         args='start'
87
88                 if args=='stop':
89                         self.pause=0
90                         self.prompt=self.auxprompt
91                         if len(self.currentmacro) != 0:
92                                 answer=linput.safeinput('Do you want to save this macro? ',['y'])
93                                 if answer[0].lower() == 'y':
94                                         self.do_savemacro('')
95                                 else:
96                                         print 'Macro discarded'
97                                         self.currentmacro=[]
98                         else:
99                                 print 'Macro was empty' 
100
101                 if args=='start':       
102
103                         if self.pause==1:
104                                 self.pause=0    
105                                 self.collect()  
106                         else:
107                                 if len(self.currentmacro) != 0:
108                                         answer=linput.safeinput('Another macro is already beign recorded\nDo you want to save it?',['y'])
109                                         if answer[0].lower() == 'y':
110                                                 self.do_savemacro('')
111                                         else:
112                                                 print 'Old macro discarded, you can start recording the new one'
113                         
114                                 self.currentmacro=[]
115                                 self.collect()
116                 
117
118         def do_savemacro(self, macroname):
119
120                 '''SAVEMACRO
121                 Saves previously recorded macro into a script file for future use
122                 -------
123                 Syntax: savemacro [macroname]
124                 If no macroname is supplied one will be interactively asked
125                 '''
126
127                 saved_ok=0
128                 if self.currentmacro==None:
129                         print 'No macro is being recorded!'
130                         return 0
131                 if len(macroname)==0:
132                         macroname=linput.safeinput('Enter new macro name: ')
133                         if len(macroname) == 0:
134                                 print 'Invalid name'
135                                 
136                 macroname=os.path.join(self.macrodir,macroname+'.hkm')
137                 if os.path.exists(macroname):
138                         overwrite=linput.safeinput('That name is in use, overwrite?',['n'])
139                         if overwrite[0].lower()!='y':
140                                 print 'Cancelled save'
141                                 return 0
142                 txtfile=open(macroname,'w+')
143                 self.currentmacro='\n'.join(self.currentmacro)
144                 txtfile.write(self.currentmacro)
145                 txtfile.close()
146                 print 'Saved on '+macroname
147                 self.currentmacro=[]
148
149         def do_execmacro (self, args):
150                 
151                 '''EXECMACRO
152                 Loads a macro and executes it over current curve / playlist
153                 -----
154                 Syntax: execmacro macroname [playlist] [v]
155
156                 macroname.hkm should be present at [hooke]/macros directory
157                 By default the macro will be executed over current curve
158                 passing 'playlist' word as second argument executes macroname
159                 over all curves
160                 By default curve(s) will be processed silently, passing 'v'
161                 as second/third argument will print each command that is
162                 executed
163
164                 Note that macros applied to playlists should end by export
165                 commands so the processed curves are not lost
166                 '''
167                 verbose=0
168                 cycle=0
169                 curve=None              
170
171                 if len(self.currentmacro) != 0:
172                         print 'Warning!: you are calling a macro while recording other'
173                 if len(args) == 0:
174                         print 'You must provide a macro name'
175                         return 0
176                 args=args.split()
177
178                 #print 'args ' + ' '.join(args)
179                 
180                 if len(args)>1:
181                         if args[1] == 'playlist':
182                                 cycle=1
183                                 print 'Remember! macros applied over playlists should include export orders'
184                                 if len(args)>2 and args[2] == 'v':
185                                         verbose=1
186                         else:
187                                 if args[1] == 'v':
188                                         verbose=1       
189                 #print cycle
190                 #print verbose  
191
192                 macropath=os.path.join(self.macrodir,args[0]+'.hkm')
193                 if not os.path.exists(macropath):
194                         print 'Could not find a macro named '+macropath
195                         return 0
196                 txtfile=open(macropath)
197                 if cycle ==1:
198                         #print self.current_list
199                         for item in self.current_list:
200                                 self.current=item
201                                 self.do_plot(0)
202
203                                 for command in txtfile:
204
205                                         if verbose==1:
206                                                 print 'Executing command '+command
207                                         testcmd=command.split()
208                                         w=0
209                                         for word in testcmd:
210                                                 if word=='__curve__':
211                                                         testcmd[w]=os.path.splitext(os.path.basename(item.path))[0]
212                                                 w=w+1
213                                         self.onecmd(' '.join(testcmd))
214                                 self.current.curve.close_all()
215                                 txtfile.seek(0)
216                 else:
217                         for command in txtfile:
218                                         testcmd=command.split()
219                                         w=0
220                                         for word in testcmd:
221                                                 if word=='__curve__':
222                                                         w=w+1
223                                                         testcmd[w]=os.path.splitext(os.path.basename(self.current.path))[0]+'-'+string.lstrip(os.path.splitext(os.path.basename(self.current.path))[1],'.')
224                                         if verbose==1:
225                                                 print 'Executing command '+' '.join(testcmd)
226                                         self.onecmd(' '.join(testcmd))