| 1 | import sys, os, getopt, traceback |
|---|
| 2 | |
|---|
| 3 | import wx |
|---|
| 4 | |
|---|
| 5 | from WikiExceptions import * |
|---|
| 6 | |
|---|
| 7 | from StringOps import mbcsDec, wikiUrlToPathWordAndAnchor |
|---|
| 8 | |
|---|
| 9 | import PluginManager |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | class CmdLineAction: |
|---|
| 13 | """ |
|---|
| 14 | This class parses command line options, provides necessary information |
|---|
| 15 | and performs actions |
|---|
| 16 | """ |
|---|
| 17 | |
|---|
| 18 | def __init__(self, sargs): |
|---|
| 19 | """ |
|---|
| 20 | sargs -- stripped args (normally sys.args[1:]) |
|---|
| 21 | """ |
|---|
| 22 | self.wikiToOpen = None |
|---|
| 23 | |
|---|
| 24 | self.wikiWordsToOpen = None |
|---|
| 25 | |
|---|
| 26 | self.anchorToOpen = None |
|---|
| 27 | self.exitFinally = False |
|---|
| 28 | |
|---|
| 29 | self.showHelp = False |
|---|
| 30 | self.cmdLineError = False |
|---|
| 31 | self.exportWhat = None |
|---|
| 32 | self.exportType = None |
|---|
| 33 | self.exportDest = None |
|---|
| 34 | self.exportCompFn = False |
|---|
| 35 | self.exportSaved = None |
|---|
| 36 | self.continuousExportSaved = None |
|---|
| 37 | self.rebuild = False |
|---|
| 38 | self.frameToOpen = 1 |
|---|
| 39 | |
|---|
| 40 | self.activeTabNo = -1 |
|---|
| 41 | |
|---|
| 42 | self.lastTabsSubCtrls = None |
|---|
| 43 | |
|---|
| 44 | self.wikiWordsToCreate = None |
|---|
| 45 | self.noRecent = False |
|---|
| 46 | |
|---|
| 47 | if len(sargs) == 0: |
|---|
| 48 | return |
|---|
| 49 | |
|---|
| 50 | if sargs[0][0] != "-": |
|---|
| 51 | |
|---|
| 52 | |
|---|
| 53 | |
|---|
| 54 | sargs = [mbcsDec(a, "replace")[0] for a in sargs] |
|---|
| 55 | self.setWikiToOpen(sargs[0]) |
|---|
| 56 | |
|---|
| 57 | if len(sargs) > 1: |
|---|
| 58 | self.wikiWordsToOpen = (sargs[1],) |
|---|
| 59 | |
|---|
| 60 | return |
|---|
| 61 | |
|---|
| 62 | |
|---|
| 63 | try: |
|---|
| 64 | opts, rargs = getopt.getopt(sargs, "hw:p:x", |
|---|
| 65 | ["help", "wiki=", "page=", "new-page=", "exit", |
|---|
| 66 | "export-what=", "export-type=", "export-dest=", |
|---|
| 67 | "export-compfn", "export-saved=", "continuous-export-saved=", |
|---|
| 68 | "anchor", "rebuild", "no-recent", "preview", "editor"]) |
|---|
| 69 | except getopt.GetoptError: |
|---|
| 70 | self.cmdLineError = True |
|---|
| 71 | return |
|---|
| 72 | |
|---|
| 73 | wikiWordsToOpen = [] |
|---|
| 74 | wikiWordsToCreate = [] |
|---|
| 75 | |
|---|
| 76 | for o, a in opts: |
|---|
| 77 | if o in ("-h", "--help"): |
|---|
| 78 | self.showHelp = True |
|---|
| 79 | elif o in ("-w", "--wiki"): |
|---|
| 80 | self.wikiToOpen = mbcsDec(a, "replace")[0] |
|---|
| 81 | elif o in ("-p", "--page"): |
|---|
| 82 | wikiWordsToOpen.append(mbcsDec(a, "replace")[0]) |
|---|
| 83 | elif o in ("--new-page"): |
|---|
| 84 | wikiWordsToCreate.append(mbcsDec(a, "replace")[0]) |
|---|
| 85 | elif o == "--anchor": |
|---|
| 86 | self.anchorToOpen = mbcsDec(a, "replace")[0] |
|---|
| 87 | elif o in ("-x", "--exit"): |
|---|
| 88 | self.exitFinally = True |
|---|
| 89 | elif o == "--export-what": |
|---|
| 90 | self.exportWhat = mbcsDec(a, "replace")[0] |
|---|
| 91 | elif o == "--export-type": |
|---|
| 92 | self.exportType = mbcsDec(a, "replace")[0] |
|---|
| 93 | elif o == "--export-dest": |
|---|
| 94 | self.exportDest = mbcsDec(a, "replace")[0] |
|---|
| 95 | elif o == "--export-compfn": |
|---|
| 96 | self.exportCompFn = True |
|---|
| 97 | elif o == "--export-saved": |
|---|
| 98 | self.exportSaved = mbcsDec(a, "replace")[0] |
|---|
| 99 | elif o == "--continuous-export-saved": |
|---|
| 100 | self.continuousExportSaved = mbcsDec(a, "replace")[0] |
|---|
| 101 | elif o == "--rebuild": |
|---|
| 102 | self.rebuild = True |
|---|
| 103 | elif o == "--no-recent": |
|---|
| 104 | self.noRecent = True |
|---|
| 105 | elif o == "--preview": |
|---|
| 106 | self._fillLastTabsSubCtrls(len(wikiWordsToOpen), "preview") |
|---|
| 107 | elif o == "--editor": |
|---|
| 108 | self._fillLastTabsSubCtrls(len(wikiWordsToOpen), "textedit") |
|---|
| 109 | |
|---|
| 110 | |
|---|
| 111 | if len(wikiWordsToOpen) > 0: |
|---|
| 112 | self.wikiWordsToOpen = tuple(wikiWordsToOpen) |
|---|
| 113 | |
|---|
| 114 | if len(wikiWordsToCreate) > 0: |
|---|
| 115 | self.wikiWordsToCreate = tuple(wikiWordsToCreate) |
|---|
| 116 | |
|---|
| 117 | self._fillLastTabsSubCtrls(len(wikiWordsToOpen)) |
|---|
| 118 | |
|---|
| 119 | |
|---|
| 120 | def _fillLastTabsSubCtrls(self, wwoLen, newItem=None): |
|---|
| 121 | """ |
|---|
| 122 | If self.lastTabsSubCtrls contains at least one item, fill it up |
|---|
| 123 | to length of wwoLen with last item. If newItem is not None, it is |
|---|
| 124 | appended. |
|---|
| 125 | If newItem is None (done by final call after collecting) self.lastTabsSubCtrls |
|---|
| 126 | shortened to length of wwoLen. If wwoLen is 0, the last item is preserved |
|---|
| 127 | to ensure that the setting "--preview" is processed when opening wiki |
|---|
| 128 | with previously opened words. |
|---|
| 129 | """ |
|---|
| 130 | if not self.lastTabsSubCtrls: |
|---|
| 131 | if newItem is not None: |
|---|
| 132 | |
|---|
| 133 | self.lastTabsSubCtrls = ["textedit"] * wwoLen + [newItem] |
|---|
| 134 | |
|---|
| 135 | return |
|---|
| 136 | |
|---|
| 137 | if len(self.lastTabsSubCtrls) < wwoLen: |
|---|
| 138 | self.lastTabsSubCtrls += [self.lastTabsSubCtrls[-1]] * \ |
|---|
| 139 | (wwoLen - len(self.lastTabsSubCtrls)) |
|---|
| 140 | |
|---|
| 141 | if newItem is not None: |
|---|
| 142 | self.lastTabsSubCtrls.append(newItem) |
|---|
| 143 | else: |
|---|
| 144 | if wwoLen > 0: |
|---|
| 145 | self.lastTabsSubCtrls = self.lastTabsSubCtrls[:wwoLen] |
|---|
| 146 | else: |
|---|
| 147 | self.lastTabsSubCtrls = self.lastTabsSubCtrls[-1:] |
|---|
| 148 | |
|---|
| 149 | if not self.lastTabsSubCtrls: |
|---|
| 150 | self.lastTabsSubCtrls = None |
|---|
| 151 | |
|---|
| 152 | |
|---|
| 153 | def setWikiToOpen(self, wto): |
|---|
| 154 | if wto.startswith("wiki:"): |
|---|
| 155 | self.wikiToOpen, wikiWordToOpen, self.anchorToOpen = \ |
|---|
| 156 | wikiUrlToPathWordAndAnchor(wto) |
|---|
| 157 | |
|---|
| 158 | self.wikiWordsToOpen = (wikiWordToOpen,) |
|---|
| 159 | |
|---|
| 160 | |
|---|
| 161 | else: |
|---|
| 162 | self.wikiToOpen = wto |
|---|
| 163 | |
|---|
| 164 | |
|---|
| 165 | def inheritFrom(self, cmdline): |
|---|
| 166 | """ |
|---|
| 167 | Inherits some settings from another commandline. Some special settings |
|---|
| 168 | should be persistent when opening one frame from another. |
|---|
| 169 | """ |
|---|
| 170 | self.noRecent = cmdline.noRecent |
|---|
| 171 | |
|---|
| 172 | |
|---|
| 173 | def actionBeforeShow(self, pWiki): |
|---|
| 174 | """ |
|---|
| 175 | Actions to do before the main frame is shown |
|---|
| 176 | """ |
|---|
| 177 | self.rebuildAction(pWiki) |
|---|
| 178 | self.exportAction(pWiki) |
|---|
| 179 | self.continuousExportAction(pWiki) |
|---|
| 180 | |
|---|
| 181 | if self.showHelp: |
|---|
| 182 | self.showCmdLineUsage(pWiki) |
|---|
| 183 | |
|---|
| 184 | |
|---|
| 185 | def rebuildAction(self, pWiki): |
|---|
| 186 | if self.rebuild: |
|---|
| 187 | pWiki.rebuildWiki(True) |
|---|
| 188 | |
|---|
| 189 | |
|---|
| 190 | def _runSavedExport(self, pWiki, savedExportName, continuousExport): |
|---|
| 191 | import Serialization, PluginManager, Exporters, SearchAndReplace |
|---|
| 192 | |
|---|
| 193 | exportList = Exporters.retrieveSavedExportsList(pWiki, |
|---|
| 194 | pWiki.getWikiData(), continuousExport) |
|---|
| 195 | xmlNode = None |
|---|
| 196 | for exportName, xn in exportList: |
|---|
| 197 | if exportName == savedExportName: |
|---|
| 198 | xmlNode = xn |
|---|
| 199 | break |
|---|
| 200 | |
|---|
| 201 | if xmlNode is None: |
|---|
| 202 | self.showCmdLineUsage(pWiki, |
|---|
| 203 | _(u"Saved export '%s' is unknown.") % savedExportName + u"\n\n") |
|---|
| 204 | return |
|---|
| 205 | |
|---|
| 206 | |
|---|
| 207 | |
|---|
| 208 | try: |
|---|
| 209 | etypeProfile = Serialization.serFromXmlUnicode(xmlNode, |
|---|
| 210 | u"exportTypeName") |
|---|
| 211 | |
|---|
| 212 | try: |
|---|
| 213 | exporter, etype, desc, panel = PluginManager.getSupportedExportTypes( |
|---|
| 214 | pWiki, None, continuousExport)[etypeProfile] |
|---|
| 215 | except KeyError: |
|---|
| 216 | self.showCmdLineUsage(pWiki, |
|---|
| 217 | _(u"Export type '%s' of saved export is not supported") % |
|---|
| 218 | etypeProfile + u"\n\n") |
|---|
| 219 | return |
|---|
| 220 | |
|---|
| 221 | addOptXml = Serialization.findXmlElementFlat(xmlNode, |
|---|
| 222 | u"additionalOptions") |
|---|
| 223 | |
|---|
| 224 | addOptVersion = int(addOptXml.getAttribute(u"version")) |
|---|
| 225 | |
|---|
| 226 | if addOptVersion != exporter.getAddOptVersion(): |
|---|
| 227 | self.showCmdLineUsage(pWiki, |
|---|
| 228 | _(u"Saved export uses different version for additional " |
|---|
| 229 | "options than current export\nExport type: '%s'\n" |
|---|
| 230 | "Saved export version: %i\nCurrent export version: %i") % |
|---|
| 231 | (etypeProfile, addOptVersion, exporter.getAddOptVersion()) + |
|---|
| 232 | u"\n\n") |
|---|
| 233 | return |
|---|
| 234 | |
|---|
| 235 | if addOptXml.getAttribute(u"type") != u"simpleTuple": |
|---|
| 236 | self.showCmdLineUsage(pWiki, |
|---|
| 237 | _(u"Type of additional option storage ('%s') is unknown") % |
|---|
| 238 | addOptXml.getAttribute(u"type") + u"\n\n") |
|---|
| 239 | return |
|---|
| 240 | |
|---|
| 241 | pageSetXml = Serialization.findXmlElementFlat(xmlNode, u"pageSet") |
|---|
| 242 | |
|---|
| 243 | sarOp = SearchAndReplace.SearchReplaceOperation() |
|---|
| 244 | sarOp.serializeFromXml(pageSetXml) |
|---|
| 245 | |
|---|
| 246 | |
|---|
| 247 | addOpt = Serialization.convertTupleFromXml(addOptXml) |
|---|
| 248 | |
|---|
| 249 | |
|---|
| 250 | |
|---|
| 251 | |
|---|
| 252 | |
|---|
| 253 | exportDest = Serialization.serFromXmlUnicode(xmlNode, |
|---|
| 254 | u"destinationPath") |
|---|
| 255 | |
|---|
| 256 | |
|---|
| 257 | |
|---|
| 258 | except SerializationException, e: |
|---|
| 259 | self.showCmdLineUsage(pWiki, _(u"Error during retrieving " |
|---|
| 260 | "saved export: ") + e.message + u"\n\n") |
|---|
| 261 | |
|---|
| 262 | |
|---|
| 263 | if not continuousExport: |
|---|
| 264 | wordList = pWiki.getWikiDocument().searchWiki(sarOp, |
|---|
| 265 | True) |
|---|
| 266 | try: |
|---|
| 267 | exporter.export(pWiki.getWikiDocument(), wordList, |
|---|
| 268 | etype, exportDest, self.exportCompFn, addOpt, None) |
|---|
| 269 | except (IOError, WindowsError), e: |
|---|
| 270 | traceback.print_exc() |
|---|
| 271 | |
|---|
| 272 | self.showCmdLineUsage(pWiki, str(e) + u"\n\n") |
|---|
| 273 | return |
|---|
| 274 | else: |
|---|
| 275 | exporter.startContinuousExport(pWiki.getWikiDocument(), |
|---|
| 276 | sarOp, etype, exportDest, self.exportCompFn, addOpt, |
|---|
| 277 | None) |
|---|
| 278 | pWiki.continuousExporter = exporter |
|---|
| 279 | |
|---|
| 280 | |
|---|
| 281 | |
|---|
| 282 | def exportAction(self, pWiki): |
|---|
| 283 | if not (self.exportWhat or self.exportType or self.exportDest or |
|---|
| 284 | self.exportSaved): |
|---|
| 285 | return |
|---|
| 286 | |
|---|
| 287 | if self.exportSaved: |
|---|
| 288 | if self.exportWhat or self.exportType or self.exportDest: |
|---|
| 289 | self.showCmdLineUsage(pWiki, |
|---|
| 290 | _(u"If saved export is given, 'what', 'type' and 'dest' aren't allowed.") + |
|---|
| 291 | u"\n\n") |
|---|
| 292 | return |
|---|
| 293 | |
|---|
| 294 | self._runSavedExport(pWiki, self.exportSaved, False) |
|---|
| 295 | return |
|---|
| 296 | |
|---|
| 297 | |
|---|
| 298 | if not (self.exportWhat and self.exportType and self.exportDest): |
|---|
| 299 | |
|---|
| 300 | self.showCmdLineUsage(pWiki, |
|---|
| 301 | _(u"To export, all three export options ('what', 'type' and 'dest') must be set.") + |
|---|
| 302 | u"\n\n") |
|---|
| 303 | return |
|---|
| 304 | |
|---|
| 305 | |
|---|
| 306 | wordList = None |
|---|
| 307 | if self.exportWhat in (u"page", u"word"): |
|---|
| 308 | |
|---|
| 309 | wordList = list(self.wikiWordsToOpen) |
|---|
| 310 | elif self.exportWhat == u"subtree": |
|---|
| 311 | |
|---|
| 312 | wordList = pWiki.getWikiData().getAllSubWords( |
|---|
| 313 | list(self.wikiWordsToOpen)) |
|---|
| 314 | elif self.exportWhat == u"wiki": |
|---|
| 315 | |
|---|
| 316 | wordList = pWiki.getWikiData().getAllDefinedWikiPageNames() |
|---|
| 317 | else: |
|---|
| 318 | self.showCmdLineUsage(pWiki, |
|---|
| 319 | _(u"Value for --export-what can be 'page', 'subtree' or 'wiki'.") + u"\n\n") |
|---|
| 320 | return |
|---|
| 321 | |
|---|
| 322 | |
|---|
| 323 | |
|---|
| 324 | |
|---|
| 325 | |
|---|
| 326 | exporterList = [] |
|---|
| 327 | for obtp in PluginManager.getSupportedExportTypes( |
|---|
| 328 | mainControl, None).values(): |
|---|
| 329 | exporterList.append((obtp[0], obtp[1])) |
|---|
| 330 | |
|---|
| 331 | mainControl.getCollator().sortByItem(exporterList, 1) |
|---|
| 332 | |
|---|
| 333 | exporter = None |
|---|
| 334 | for ei in exporterList: |
|---|
| 335 | if ei[1] == self.exportType: |
|---|
| 336 | exporter = ei[0] |
|---|
| 337 | break |
|---|
| 338 | |
|---|
| 339 | if exporter is None: |
|---|
| 340 | exList = ", ".join([ei[1] for ei in exporterList]) |
|---|
| 341 | |
|---|
| 342 | self.showCmdLineUsage(pWiki, |
|---|
| 343 | _(u"Value for --export-type can be one of:\n%s") % exList) + u"\n\n" |
|---|
| 344 | return |
|---|
| 345 | |
|---|
| 346 | try: |
|---|
| 347 | exporter.export(pWiki.getWikiDocument(), wordList, |
|---|
| 348 | self.exportType, self.exportDest, |
|---|
| 349 | self.exportCompFn, exporter.getAddOpt(None), None) |
|---|
| 350 | except (IOError, WindowsError), e: |
|---|
| 351 | traceback.print_exc() |
|---|
| 352 | |
|---|
| 353 | self.showCmdLineUsage(pWiki, str(e) + u"\n\n") |
|---|
| 354 | return |
|---|
| 355 | |
|---|
| 356 | |
|---|
| 357 | |
|---|
| 358 | def continuousExportAction(self, pWiki): |
|---|
| 359 | if not self.continuousExportSaved: |
|---|
| 360 | return |
|---|
| 361 | |
|---|
| 362 | if self.exitFinally: |
|---|
| 363 | self.showCmdLineUsage(pWiki, |
|---|
| 364 | _(u"Combination of --exit and --continuous-export-saved isn't allowed") + u"\n\n") |
|---|
| 365 | return |
|---|
| 366 | |
|---|
| 367 | self._runSavedExport(pWiki, self.continuousExportSaved, True) |
|---|
| 368 | |
|---|
| 369 | |
|---|
| 370 | |
|---|
| 371 | USAGE = \ |
|---|
| 372 | N_(u"""Options: |
|---|
| 373 | |
|---|
| 374 | -h, --help: Show this message box |
|---|
| 375 | -w, --wiki <wiki path>: set the wiki to open on startup |
|---|
| 376 | -p, --page <page name>: set the page to open on startup |
|---|
| 377 | -x, --exit: exit immediately after performing command line actions |
|---|
| 378 | --export-what <what>: choose if you want to export page, subtree or wiki |
|---|
| 379 | --export-type <type>: tag of the export type |
|---|
| 380 | --export-dest <destination path>: path of destination directory for export |
|---|
| 381 | --export-saved <name of saved export>: alternatively name of saved export to run |
|---|
| 382 | --export-compfn: Use compatible filenames on export |
|---|
| 383 | --continuous-export-saved <name of saved export>: continuous export to start with |
|---|
| 384 | --rebuild: rebuild the Wiki database |
|---|
| 385 | --no-recent: Do not record opened wikis in recently opened wikis list |
|---|
| 386 | --preview: If no pages are given, all opened pages from previous session |
|---|
| 387 | are opened in preview mode. Otherwise all pages given after that |
|---|
| 388 | option are opened in preview mode. |
|---|
| 389 | --editor: Same as --preview but opens in text editor mode. |
|---|
| 390 | |
|---|
| 391 | """) |
|---|
| 392 | |
|---|
| 393 | def showCmdLineUsage(self, pWiki, addRemark=u""): |
|---|
| 394 | """ |
|---|
| 395 | Show dialog with addRemark and command line usage information. |
|---|
| 396 | """ |
|---|
| 397 | wx.MessageBox(addRemark + _(self.USAGE), _(u"Usage information"), |
|---|
| 398 | style=wx.OK, parent=None) |
|---|
| 399 | |
|---|
| 400 | |
|---|
| 401 | |
|---|
| 402 | |
|---|