Source code for pywikibot.editor

"""Text editor class for your favourite editor."""
# (C) Pywikibot team, 2004-2020
# Distributed under the terms of the MIT license.
import codecs
import os
import subprocess
import tempfile

from sys import platform
from textwrap import fill
from typing import Optional

import pywikibot

from pywikibot import config

    from pywikibot.userinterfaces import gui
except ImportError as e:
    gui = e

[docs]class TextEditor: """Text editor.""" def _command(self, file_name, text, jump_index=None): """Return editor selected in""" if jump_index: # Some editors make it possible to mark occurrences of substrings, # or to jump to the line of the first occurrence. # TODO: Find a better solution than hardcoding these, e.g. a config # option. line = text[:jump_index].count('\n') column = jump_index - (text[:jump_index].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' % (line + 1), '-c', '%i' % (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 else: command = [] # See T102465 for problems relating to using config.editor unparsed. command = [config.editor] + command + [file_name] pywikibot.log('Running editor: %s' % TextEditor._concat(command)) return command @staticmethod def _concat(command): return ' '.join("'{0}'".format(part) if ' ' in part else part for part in command)
[docs] def edit(self, text: str, jumpIndex: Optional[int] = None, highlight: Optional[str] = None) -> Optional[str]: """ Call the editor and thus allows the user to change the text. Halts the thread's operation until the editor is closed. @param text: the text to be edited @param jumpIndex: position at which to put the caret @param highlight: each occurrence of this substring will be highlighted @return: the modified text, or None if the user didn't save the text file in his text editor """ if config.editor: handle, tempFilename = tempfile.mkstemp() tempFilename = '{}.{}'.format(tempFilename, config.editor_filename_extension) try: with, 'w', encoding=config.editor_encoding) as tempFile: tempFile.write(text) creationDate = os.stat(tempFilename).st_mtime cmd = self._command(tempFilename, text, jumpIndex), shell=platform == 'win32') lastChangeDate = os.stat(tempFilename).st_mtime if lastChangeDate == creationDate: # Nothing changed return None with, 'r', encoding=config.editor_encoding) as temp_file: newcontent = return newcontent finally: os.close(handle) os.unlink(tempFilename) if isinstance(gui, ImportError): raise ImportError(fill( 'Could not load GUI modules: {}. No editor available. ' 'Set your favourite editor in "editor", ' 'or install python packages tkinter and idlelib, which ' 'are typically part of Python but may be packaged separately ' 'on your platform.'.format(gui)) + '\n') return pywikibot.ui.editText(text, jumpIndex=jumpIndex, highlight=highlight)