-
Notifications
You must be signed in to change notification settings - Fork 6
/
editarticle.py
199 lines (176 loc) · 6.91 KB
/
editarticle.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Edit a Wikipedia article with your favourite editor.
"""
#
# (C) Gerrit Holl 2004
# (C) Pywikipedia team, 2004-2011
#
__version__ = "$Id: editarticle.py 9370 2011-07-13 06:39:47Z xqt $"
#
# Distributed under the terms of the MIT license.
#
# Version 0.4.
#
# TODO: - non existing pages
# - edit conflicts
# - minor edits
# - watch/unwatch
# - ...
__metaclass__ = type
import sys
import os
import string
import optparse
import tempfile
import wikipedia as pywikibot
from pywikibot import i18n
import config
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 + 1, column + 1)
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(
pywikibot.ui.editText(text, jumpIndex=jumpIndex,
highlight=highlight))
class ArticleEditor:
# join lines if line starts with this ones
joinchars = string.letters + '[]' + string.digits
def __init__(self, *args):
self.set_options(*args)
self.setpage()
self.site = pywikibot.getSite()
def set_options(self, *args):
"""Parse commandline and set options attribute"""
my_args = []
for arg in pywikibot.handleArgs(*args):
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 = pywikibot.getSite()
pageTitle = self.options.page or pywikibot.input(u"Page to edit:")
self.page = pywikibot.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()
pywikibot.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 pywikibot.NoPage:
old = ""
textEditor = TextEditor()
new = textEditor.edit(old)
if new and old != new:
pywikibot.showDiff(old, new)
changes = pywikibot.input(u"What did you change?")
comment = i18n.twtranslate(pywikibot.getSite(), 'editarticle-edit',
{'description': changes})
try:
self.page.put(new, comment=comment, minorEdit=False,
watchArticle=self.options.watch)
except pywikibot.EditConflict:
self.handle_edit_conflict(new)
else:
pywikibot.output(u"Nothing changed")
def main(*args):
app = ArticleEditor(*args)
app.run()
if __name__ == "__main__":
try:
main()
finally:
pywikibot.stopme()