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