comparison frontends/src/jp/cmd_blog.py @ 1885:edd8dc8df1b9

jp (blog/preview): open and preview commands can be changed in sat.conf with "blog_preview_open_cmd" and "blog_preview_update_cmd" in [jp] section + don't convert syntax when content is empty
author Goffi <goffi@goffi.org>
date Sat, 05 Mar 2016 19:21:35 +0100
parents abb2f253188e
children f3db27508b31
comparison
equal deleted inserted replaced
1884:0fe69871b71f 1885:edd8dc8df1b9
99 return k 99 return k
100 100
101 # if not found, we use current syntax 101 # if not found, we use current syntax
102 return self.host.bridge.getParamA("Syntax", "Composition", "value", self.profile) 102 return self.host.bridge.getParamA("Syntax", "Composition", "value", self.profile)
103 103
104 def parse_args(self, cmd_line, **format_kw):
105 """Parse command arguments
106
107 @param cmd_line(unicode): command line as found in sat.conf
108 @param format_kw: keywords used for formmating
109 @return (list(unicode)): list of arguments to pass to subprocess function
110 """
111 try:
112 # we split the arguments and add the known fields
113 # we split arguments first to avoid escaping issues in file names
114 return [a.format(**format_kw) for a in shlex.split(cmd_line)]
115 except ValueError as e:
116 self.disp(u"Couldn't parse editor cmd [{cmd}]: {reason}".format(cmd=cmd_line, reason=e))
117 return []
118
104 119
105 class Edit(base.CommandBase, BlogCommon): 120 class Edit(base.CommandBase, BlogCommon):
106 121
107 def __init__(self, host): 122 def __init__(self, host):
108 super(Edit, self).__init__(host, 'edit', use_verbose=True, help=_(u'edit an existing or new blog post')) 123 super(Edit, self).__init__(host, 'edit', use_verbose=True, help=_(u'edit an existing or new blog post'))
203 # is there custom arguments in sat.conf ? 218 # is there custom arguments in sat.conf ?
204 editor_args = config.getConfig(sat_conf, 'jp', 'blog_editor_args', Exception) 219 editor_args = config.getConfig(sat_conf, 'jp', 'blog_editor_args', Exception)
205 except (NoOptionError, NoSectionError): 220 except (NoOptionError, NoSectionError):
206 # no, we check if we know the editor and have special arguments 221 # no, we check if we know the editor and have special arguments
207 editor_args = EDITOR_ARGS_MAGIC.get(os.path.basename(editor), '') 222 editor_args = EDITOR_ARGS_MAGIC.get(os.path.basename(editor), '')
208 try: 223 args = self.parse_args(editor_args, content_file=content_file_path, metadata_file=meta_file_path)
209 # we split the arguments and add the known fields
210 # we split arguments first to avoid escaping issues in file names
211 args = [a.format(content_file=content_file_path, metadata_file=meta_file_path) for a in shlex.split(editor_args)]
212 except ValueError as e:
213 self.disp(u"Couldn't parse editor cmd [{cmd}]: {reason}".format(cmd=editor_args, reason=e))
214 args = []
215 if not args: 224 if not args:
216 args = [content_file_path] 225 args = [content_file_path]
217 editor_exit = subprocess.call([editor] + args) 226 editor_exit = subprocess.call([editor] + args)
218 227
219 # we send the file if edition was a success 228 # we send the file if edition was a success
301 except Exception as e: 310 except Exception as e:
302 self.disp(u"Error while retrieving last comment: {}".format(e)) 311 self.disp(u"Error while retrieving last comment: {}".format(e))
303 self.host.quit(1) 312 self.host.quit(1)
304 313
305 content = mb_data['content_xhtml'] 314 content = mb_data['content_xhtml']
306 if current_syntax != 'XHTML': 315 if content and current_syntax != 'XHTML':
307 content = self.host.bridge.syntaxConvert(content, 'XHTML', current_syntax, False, self.profile) 316 content = self.host.bridge.syntaxConvert(content, 'XHTML', current_syntax, False, self.profile)
308 content_file_obj.write(content.encode('utf-8')) 317 content_file_obj.write(content.encode('utf-8'))
309 content_file_obj.seek(0) 318 content_file_obj.seek(0)
310 319
311 self.edit(sat_conf, content_file_path, content_file_obj, mb_data=mb_data) 320 self.edit(sat_conf, content_file_path, content_file_obj, mb_data=mb_data)
324 # we implement showPreview here so we don't have to import webbroser and urllib 333 # we implement showPreview here so we don't have to import webbroser and urllib
325 # when preview is not used 334 # when preview is not used
326 url = 'file:{}'.format(self.urllib.quote(self.preview_file_path)) 335 url = 'file:{}'.format(self.urllib.quote(self.preview_file_path))
327 self.webbrowser.open_new_tab(url) 336 self.webbrowser.open_new_tab(url)
328 337
338 def _launchPreviewExt(self, cmd_line, opt_name):
339 url = 'file:{}'.format(self.urllib.quote(self.preview_file_path))
340 args = self.parse_args(cmd_line, url=url, preview_file=self.preview_file_path)
341 if not args:
342 self.disp(u"Couln't find command in \"{name}\", abording".format(name=opt_name), error=True)
343 self.host.quit(1)
344 subprocess.Popen(args)
345
346 def openPreviewExt(self):
347 self._launchPreviewExt(self.open_cb_cmd, "blog_preview_open_cmd")
348
349 def updatePreviewExt(self):
350 self._launchPreviewExt(self.update_cb_cmd, "blog_preview_update_cmd")
351
329 def updateContent(self): 352 def updateContent(self):
330 with open(self.current_file_path, 'rb') as f: 353 with open(self.content_file_path, 'rb') as f:
331 content_xhtml = f.read().decode('utf-8') 354 content = f.read().decode('utf-8')
332 if self.syntax != 'XHTML': 355 if content and self.syntax != 'XHTML':
333 # we use safe=True because we want to have a preview as close as possible to what the 356 # we use safe=True because we want to have a preview as close as possible to what the
334 # people will see 357 # people will see
335 content_xhtml = self.host.bridge.syntaxConvert(content_xhtml, self.syntax, 'XHTML', True, self.profile) 358 content = self.host.bridge.syntaxConvert(content, self.syntax, 'XHTML', True, self.profile)
336 359
337 xhtml = (u'<html xmlns="http://www.w3.org/1999/xhtml">' + 360 xhtml = (u'<html xmlns="http://www.w3.org/1999/xhtml">' +
338 u'<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /></head>'+ 361 u'<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /></head>'+
339 '<body>{}</body>' + 362 '<body>{}</body>' +
340 u'</html>').format(content_xhtml) 363 u'</html>').format(content)
341 364
342 with open(self.preview_file_path, 'wb') as f: 365 with open(self.preview_file_path, 'wb') as f:
343 f.write(xhtml.encode('utf-8')) 366 f.write(xhtml.encode('utf-8'))
344 367
345 def start(self): 368 def start(self):
368 inotify=None 391 inotify=None
369 392
370 sat_conf = config.parseMainConf() 393 sat_conf = config.parseMainConf()
371 SYNTAX_EXT.update(config.getConfig(sat_conf, 'jp', CONF_SYNTAX_EXT, {})) 394 SYNTAX_EXT.update(config.getConfig(sat_conf, 'jp', CONF_SYNTAX_EXT, {}))
372 395
373 open_cb = self.showPreview 396 try:
374 update_cb = self.showPreview 397 self.open_cb_cmd = config.getConfig(sat_conf, 'jp', "blog_preview_open_cmd", Exception)
398 except (NoOptionError, NoSectionError):
399 self.open_cb_cmd = None
400 open_cb = self.showPreview
401 else:
402 open_cb = self.openPreviewExt
403
404 self.update_cb_cmd = config.getConfig(sat_conf, 'jp', "blog_preview_update_cmd", self.open_cb_cmd)
405 if self.update_cb_cmd is None:
406 update_cb = self.showPreview
407 else:
408 update_cb = self.updatePreviewExt
375 409
376 # which file do we need to edit? 410 # which file do we need to edit?
377 if self.args.file == 'current': 411 if self.args.file == 'current':
378 self.current_file_path = self.getCurrentFile(sat_conf) 412 self.content_file_path = self.getCurrentFile(sat_conf)
379 else: 413 else:
380 self.current_file_path = os.path.abspath(self.args.file) 414 self.content_file_path = os.path.abspath(self.args.file)
381 415
382 self.syntax = self.guessSyntaxFromPath(sat_conf, self.current_file_path) 416 self.syntax = self.guessSyntaxFromPath(sat_conf, self.content_file_path)
383 417
384 418
385 # at this point the syntax is converted, we can display the preview 419 # at this point the syntax is converted, we can display the preview
386 preview_file = tempfile.NamedTemporaryFile(suffix='.xhtml', delete=False) 420 preview_file = tempfile.NamedTemporaryFile(suffix='.xhtml', delete=False)
387 self.preview_file_path = preview_file.name 421 self.preview_file_path = preview_file.name