Revision: 6190 Author: russblau Date: 2008-12-23 17:13:12 +0000 (Tue, 23 Dec 2008)
Log Message: ----------- Branch for use in rewrite
Added Paths: ----------- branches/rewrite/pywikibot/scripts/editarticle.py
Copied: branches/rewrite/pywikibot/scripts/editarticle.py (from rev 6189, trunk/pywikipedia/editarticle.py) =================================================================== --- branches/rewrite/pywikibot/scripts/editarticle.py (rev 0) +++ branches/rewrite/pywikibot/scripts/editarticle.py 2008-12-23 17:13:12 UTC (rev 6190) @@ -0,0 +1,190 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Edit a Wikipedia article with your favourite editor. +# +# (C) Gerrit Holl 2004 +# Distributed under the terms of the MIT license. + +# Version 0.4. +# +# TODO: - non existing pages +# - edit conflicts +# - minor edits +# - watch/unwatch +# - ... + +__metaclass__ = type +__version__ = "$Id$" +import sys +import os +import string +import optparse +import tempfile + +import wikipedia +import config + +msg = { + 'ar': u'تعديل يدوي: %s', + 'de': u'Manuelle Bearbeitung: %s', + 'en': u'Manual edit: %s', + 'he': u'עריכה ידנית: %s', + 'ja': u'手動編集: %s', + 'pt': u'Editando manualmente com bot: %s', + 'sv': u'Manuell redigering: %s', + 'is': u'Handvirk breyting: %s', + 'zh': u'手動編輯: %s', +} + +class TextEditor: + def __init__(self): + pass + + def command(self, tempFilename, text, jumpIndex = None): + command = config.editor + if jumpIndex: + # Some editors make it possible to mark occurences of substrings, or + # to jump to the line of the first occurence. + # TODO: Find a better solution than hardcoding these, e.g. a config + # option. + line = text[:jumpIndex].count('\n') + column = jumpIndex - (text[:jumpIndex].rfind('\n') + 1) + else: + line = column = 0 + # Linux editors. We use startswith() because some users might use parameters. + if config.editor.startswith('kate'): + command += " -l %i -c %i" % (line, column) + elif config.editor.startswith('gedit'): + command += " +%i" % (line + 1) # seems not to support columns + elif config.editor.startswith('emacs'): + command += " +%i" % (line + 1) # seems not to support columns + elif config.editor.startswith('jedit'): + command += " +line:%i" % (line + 1) # seems not to support columns + elif config.editor.startswith('vim'): + command += " +%i" % (line + 1) # seems not to support columns + elif config.editor.startswith('nano'): + command += " +%i,%i" % (line + 1, column + 1) + # Windows editors + elif config.editor.lower().endswith('notepad++.exe'): + command += " -n%i" % (line + 1) # seems not to support columns + + command += ' %s' % tempFilename + #print command + return command + + def convertLinebreaks(self, text): + if sys.platform=='win32': + return text.replace('\r\n', '\n') + # TODO: Mac OS handling + return text + + def restoreLinebreaks(self, text): + if text is None: + return None + if sys.platform=='win32': + return text.replace('\n', '\r\n') + # TODO: Mac OS handling + return text + + def edit(self, text, jumpIndex = None, highlight = None): + """ + Calls the editor and thus allows the user to change the text. + Returns the modified text. Halts the thread's operation until the editor + is closed. + + Returns None if the user didn't save the text file in his text editor. + + Parameters: + * text - a Unicode string + * jumpIndex - an integer: position at which to put the caret + * highlight - a substring; each occurence will be highlighted + """ + text = self.convertLinebreaks(text) + if config.editor: + tempFilename = '%s.%s' % (tempfile.mktemp(), config.editor_filename_extension) + tempFile = open(tempFilename, 'w') + tempFile.write(text.encode(config.editor_encoding)) + tempFile.close() + creationDate = os.stat(tempFilename).st_mtime + command = self.command(tempFilename, text, jumpIndex) + os.system(command) + lastChangeDate = os.stat(tempFilename).st_mtime + if lastChangeDate == creationDate: + # Nothing changed + return None + else: + newcontent = open(tempFilename).read().decode(config.editor_encoding) + os.unlink(tempFilename) + return self.restoreLinebreaks(newcontent) + else: + return self.restoreLinebreaks(wikipedia.ui.editText(text, jumpIndex = jumpIndex, highlight = highlight)) + +class ArticleEditor: + joinchars = string.letters + '[]' + string.digits # join lines if line starts with this ones + + def __init__(self): + self.set_options() + self.setpage() + self.site = wikipedia.getSite() + + def set_options(self): + """Parse commandline and set options attribute""" + my_args = [] + for arg in wikipedia.handleArgs(): + my_args.append(arg) + parser = optparse.OptionParser() + parser.add_option("-r", "--edit_redirect", action="store_true", default=False, help="Ignore/edit redirects") + parser.add_option("-p", "--page", help="Page to edit") + parser.add_option("-w", "--watch", action="store_true", default=False, help="Watch article after edit") + #parser.add_option("-n", "--new_data", default="", help="Automatically generated content") + (self.options, args) = parser.parse_args(args=my_args) + + # for convenience, if we have an arg, stuff it into the opt, so we + # can act like a normal editor. + if (len(args) == 1): + self.options.page = args[0] + + def setpage(self): + """Sets page and page title""" + site = wikipedia.getSite() + pageTitle = self.options.page or wikipedia.input(u"Page to edit:") + self.page = wikipedia.Page(site, pageTitle) + if not self.options.edit_redirect and self.page.isRedirectPage(): + self.page = self.page.getRedirectTarget() + + def handle_edit_conflict(self): + fn = os.path.join(tempfile.gettempdir(), self.page.title()) + fp = open(fn, 'w') + fp.write(new) + fp.close() + wikipedia.output(u"An edit conflict has arisen. Your edit has been saved to %s. Please try again." % fn) + + def run(self): + try: + old = self.page.get(get_redirect = self.options.edit_redirect) + except wikipedia.NoPage: + old = "" + textEditor = TextEditor() + new = textEditor.edit(old) + if new and old != new: + wikipedia.showDiff(old, new) + changes = wikipedia.input(u"What did you change?") + comment = wikipedia.translate(wikipedia.getSite(), msg) % changes + try: + self.page.put(new, comment = comment, minorEdit = False, watchArticle=self.options.watch) + except wikipedia.EditConflict: + self.handle_edit_conflict(new) + else: + wikipedia.output(u"Nothing changed") + +def main(): + app = ArticleEditor() + app.run() + +if __name__ == "__main__": + try: + main() + finally: + wikipedia.stopme() +