Source code for diffmap

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# (abbrevx-single-replace "@package@" "::ide::")
# Copyright (C) 2023, Wolfgang Scherer, <Wolfgang.Scherer at gmx.de>

# This file is part of @Package@.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# (progn (forward-line 1) (snip-insert "py_doc.main" t t "python") (insert "\n"))
r"""diffmap.py - generate line mapping from target to source from diff(1) output

======  ====================
usage:  diffmap.py [OPTIONS] source-or-diff-output [target]
or      import diffmap
======  ====================

:rem:`|||:sec:|||`\ Options
===========================

.. compound::

   ===================== ==================================================
   -q, --quiet           suppress warnings
   -v, --verbose         verbose test output
   -d, --debug           show debug information

   -h, --help            display this help message
   -t, --test            run doc tests
   ===================== ==================================================

.. adhoc Options

   ===================== ==================================================
   --template list       show available templates
   --eide[=COMM]         Emacs IDE template list (implies `--template` list)
   --template[=NAME]     extract named template to standard
                         output; default NAME is ``-``
   --extract[=DIR]       extract adhoc files to directory DIR (default: :file:`.`)
   --explode[=DIR]       explode script with adhoc in directory DIR
                         (default :file:`__adhoc__`)
   --setup[=install]     explode script into temporary directory and call
                         :command:`python setup.py install`
   --implode             implode script with adhoc
   ===================== ==================================================

:rem:`|||:sec:|||`\ Description
===============================

The diff(1) between two source and transformed file gives an
accurate specification which line numbers of the two files are
correlated.

.. code-block:: sh

   diff -u /home/ws/project/administration/README-redistribution-of-info-items.txt /home/ws/project/administration/doc/redistribution-of-info-items.rst.auto

.. code-block:: text

   @@ -1,7 +1,18 @@

The hunk description specifies, that

- the block of lines in source document consisting of 7 lines starting at line 1, matches with
- the block of lines in target document consisting of 18 lines starting at line 1

see `text processing - How shall I understand the unified format of diff output? - Unix & Linux Stack Exchange <https://unix.stackexchange.com/questions/480443/how-shall-i-understand-the-unified-format-of-diff-output>`_.

The correlation can then be determined from the hunk information
alone, without parsing the input files:

.. uml::
   :caption: Correlate Line Numbers from Diff Output
   :html_format: png
   :latex_format: png
   :scale: 100%

   @startditaa -E
   skinparam defaultFontName Verdana

   +--------+--------+
   | s_from | t_from |
   +--------+--------+
   | 1      | 1 -> 1 |
   +--------+--------+
   | 2      | 2 -> 2 |
   +--------+--------+
   | 3      | 3 -> 3 |
   +--------+--------+
   | 4      | 4 -> 4 |
   +--------+--------+

   ----

   +--------+--------+
   | s_from | t_from |
   +--------+--------+
   | 1      | 1 -> 1 |
   +--------+--------+
   | 2      | 2 -> 2 |
   +--------+--------+
            | 3 -> 2 |
            +--------+
            | 4 -> 2 |
            +--------+

   ----

   +--------+--------+
   | s_from | t_from |
   +--------+--------+
   | 1      | 1 -> 1 |
   +--------+--------+
   | 2      | 2 -> 2 |
   +--------+--------+
   | 3      |
   +--------+
   | 4      |
   +--------+

   @endditaa

.. note:: The mapping is different, depending on a hunk having some
          lines or no lines!

>>> text = '\n'.join(('line ' + str(_i) for _i in xrange(15)))

>>> def write_file(file, line_nos):
...     with open(file, 'w') as _fh:
...         lines = list(text.splitlines())
...         for _i in line_nos:
...             printf(lines[_i], file=_fh)

>>> def dump_file(file):
...     printf('\n'.join([sformat("{0:02d} | {1}", _i + 1, _l)
...                       for _i, _l in
...                       enumerate(open(file, 'r').read().splitlines())]))

:rem:`||:sec:||`\ Line mapping, when source file hunk is completely removed
---------------------------------------------------------------------------

>>> write_file("t1", [1, 2, 3, 7, 8])
>>> write_file("t2", [1, 2, 3, 4, 5, 6, 7, 8])

.. . >>> dump_file("t1")
.. . >>> dump_file("t2")
.. . >>> printf(os.popen("diff --unified=0 't1' 't2'", 'r').read(), end='') #doctest: +ELLIPSIS

.. code-block:: text

   01 | line 1   <-----   01 | line 1
   02 | line 2   <-----   02 | line 2
   03 | line 3   <-----   03 | line 3
                  \----   04 | line 4   \  These are between line 03
                   \---   05 | line 5    > and line 04 of source file
                    \--   06 | line 6   /
   04 | line 7   <-----   07 | line 7
   05 | line 8   <-----   08 | line 8

.. code-block:: diff

   @@ -3,0 +4,3 @@
   +line 4
   +line 5
   +line 6

Lines 00 - 06 of target file map to lines 00 - 03 of source
file. Therefore, lines 04 - 06 all map to line 03. Lines starting at
7 are mapped with an offset of -3 (07 -> 04, 08 -> 05).

>>> dm = DiffMap("t1", "t2")
>>> print(dm)
#    :INF:    s_line         : ]4[
#    :INF:    t_line         : ]7[
#    :INF:    s_line - t_line: ]-3[
#    0 -    6 (   3) =>    0 -    3

:rem:`||:sec:||`\ Line mapping, when target file hunk is completely removed
---------------------------------------------------------------------------

>>> write_file("t1", [1, 2, 3, 4, 5, 6, 7, 8])
>>> write_file("t2", [1, 2, 3, 7, 8])

.. code-block:: text

    01 | line 1   <-----   01 | line 1
    02 | line 2   <-----   02 | line 2
    03 | line 3   <-----   03 | line 3
    04 | line 4   <---/                  \  These are between line 03
    05 | line 5   <--/                    > and line 04 of target file
    06 | line 6   <-/                    /
    07 | line 7   <-----   04 | line 7
    08 | line 8   <-----   05 | line 8

.. code-block:: diff

   --- t1...
   +++ t2...
   @@ -4,3 +3,0 @@
   -line 4
   -line 5
   -line 6

Lines 00 - 03 of target file map to lines 00 - 03 of source
file. Lines starting at 04 are mapped with an offset of +3 (04 -> 07,
05 -> 08).

>>> dm = DiffMap("t1", "t2")
>>> print(dm)
#    :INF:    s_line         : ]7[
#    :INF:    t_line         : ]4[
#    :INF:    s_line - t_line: ]3[
#    0 -    3 (   3) =>    0 -    3

:rem:`||:sec:||`\ Line mapping, when source and target file hunk overlap
------------------------------------------------------------------------

>>> write_file("t1", [1, 2, 3, 4, 5, 6, 7, 8])
>>> write_file("t2", [1, 2, 3, 3, 3, 7, 8])

.. code-block:: text

   01 | line 1   <-----   01 | line 1
   02 | line 2   <-----   02 | line 2
   03 | line 3   <-----   03 | line 3
   04 | line 4   <-----   04 | line 3   \  These lines overlap between
   05 | line 5   <-----   05 | line 3    > source and target file
   06 | line 6   <-/                    /
   07 | line 7   <-----   06 | line 7
   08 | line 8   <-----   07 | line 8

.. code-block:: diff

   --- t1...
   +++ t2...
   @@ -4,3 +4,2 @@
   -line 4
   -line 5
   -line 6
   +line 3
   +line 3

Lines 00 - 05 of target file map to lines 00 - 05 of source
file. Lines starting at 06 are mapped with an offset of +1 (06 -> 07,
07 -> 08).

>>> dm = DiffMap("t1", "t2")
>>> print(dm)
#    :INF:    s_line         : ]7[
#    :INF:    t_line         : ]6[
#    :INF:    s_line - t_line: ]1[
#    0 -    5 (   5) =>    0 -    5

>>> os.unlink('t1')
>>> os.unlink('t2')

:rem:`|||:sec:|||`\ Module
==========================

:rem:`|||:sec:|||`\ Automatic Exports
=====================================

>>> for ex in __all__: printf(sformat('from {0} import {1}', __name__, ex))
from diffmap import DiffMap

:rem:`|||:sec:|||`\ Explicit Exports
====================================

>>> if '__all_internal__' in globals():
...   for ex in __all_internal__:
...     printf(sformat('from {0} import {1}', __name__, ex))

.. _END_OF_HELP_diffmap:

:rem:`|||:sec:|||`\ Details
===========================

"""

# (progn (forward-line 1) (snip-insert "py.b.future.with" t t "python") (insert "\n"))
# for python 2.5
from __future__ import with_statement

# (progn (forward-line 1) (snip-insert "py.main.pyramid.activate" t t "py") (insert ""))

# --------------------------------------------------
# |||:sec:||| COMPATIBILITY
# --------------------------------------------------

import sys
# (progn (forward-line 1) (snip-insert "py.b.printf" t t "py") (insert "\n"))
# adapted from http://www.daniweb.com/software-development/python/code/217214
try:
    printf = eval("print") # python 3.0 case
except SyntaxError:
    printf_dict = dict()
    try:
        exec("from __future__ import print_function\nprintf=print", printf_dict)
        printf = printf_dict["printf"] # 2.6 case
    except SyntaxError:
        def printf(*args, **kwd): # 2.4, 2.5, define our own Print function
            fout = kwd.get("file", sys.stdout)
            w = fout.write
            if args:
                w(str(args[0]))
            sep = kwd.get("sep", " ")
            for a in args[1:]:
                w(sep)
                w(str(a))
            w(kwd.get("end", "\n"))
    del printf_dict

# (progn (forward-line 1) (snip-insert "py.b.sformat" t t "py") (insert "\n"))
try:
    ('{0}').format(0)
    def sformat (fmtspec, *args, **kwargs):
        return fmtspec.format(*args, **kwargs)
except AttributeError:
    try:
        import stringformat
        def sformat (fmtspec, *args, **kwargs):
            return stringformat.FormattableString(fmtspec).format(
                *args, **kwargs)
    except ImportError:
        printf('error: stringformat missing. Try `easy_install stringformat`.', file=sys.stderr)

# (progn (forward-line 1) (snip-insert "py.b.isstring" t t "python" " --key isstring_onlyx") (insert "\n"))
try:
    from ws_seq_type import isstring, issequence, sequence_type, UCHAR_FMT
except ImportError:
    # (progn (forward-line 1) (snip-insert "py.f.isstring" t t "py") (insert "\n"))
    exec('''
    def isstring(obj):
        return isinstance(obj, basestring)
    '''.strip())
    try:
        isstring("")
        UCHAR_FMT = 'u"{0}u{1:04x}"'
    except NameError:
        def isstring(obj):
            return isinstance(obj, str) or isinstance(obj, bytes)
        UCHAR_FMT = '"{0}u{1:04x}"'
    # (progn (forward-line 1) (snip-insert "py.f.issequence" t t "py") (insert "\n"))
    def issequence(arg, or_dict=False, or_seq=True):           # ||:fnc:||
        if not isstring(arg):
            if hasattr(arg, 'items'):
                return or_dict
            if hasattr(arg, '__getitem__'):
                return True
            if hasattr(arg, '__iter__'):
                return or_seq
        return False
    # (progn (forward-line 1) (snip-insert-mode "py.f.sequence_type" t) (insert "\n"))
    _st_strg = (True,  False, False, False)
    _st_list = (False, True,  False, False)
    _st_dict = (False, False, True,  False)
    _st_seq  = (False, False, False, True)
    _st_none = (False, False, False, False)
    def sequence_type(value):                                  # ||:fnc:||
        if isstring(value):
            return _st_strg
        if hasattr(value, 'items'):
            return _st_dict
        if hasattr(value, '__getitem__'):
            return _st_list
        if hasattr(value, '__iter__'):
            return _st_seq
        return _st_none

# (progn (forward-line 1) (snip-insert-mode "py.f.uchar" t) (insert "\n"))
def uchar(num):
    '''Make UNICODE character.'''
    return eval(sformat(UCHAR_FMT,'\\', num))

# (progn (forward-line 1) (snip-insert "py.b.dict.items" t t "py") (insert "\n"))
try:
    getattr(dict(), 'iteritems')
except AttributeError:
    ditems  = lambda d: getattr(d, 'items')()
    dkeys   = lambda d: getattr(d, 'keys')()
    dvalues = lambda d: getattr(d, 'values')()
else:
    ditems  = lambda d: getattr(d, 'iteritems')()
    dkeys   = lambda d: getattr(d, 'iterkeys')()
    dvalues = lambda d: getattr(d, 'itervalues')()

# (progn (forward-line 1) (snip-insert "py.b.xrange" t t "py") (insert "\n"))
# `xrange` returns a generator, which `range` already does for python3
# note: use l.. and g.. to get list/generator versions
try:
    xrange(0)
    lrange = lambda *args, **kwargs: range(*args, **kwargs)
except NameError:
    xrange = range
    lrange = lambda *args, **kwargs: list(range(*args, **kwargs))
grange = xrange

# `xfilter` returns a list, `filter` may return a generator. This is
# different from the range/xrange semantics!
if isinstance(filter(str, []), list):
    xfilter = filter
    gfilter = lambda _f, _s, *args, **kwargs: (_e for _e in _s if _f(_e))
else:
    xfilter = lambda *args, **kwargs: list(filter(*args, **kwargs))
    gfilter = filter
lfilter = xfilter

# `xmap` returns a list, `map` may return a generator. This is
# different from the range/xrange semantics!
if isinstance(map(str, []), list):
    xmap = map
    gmap = lambda _f, _s, *args, **kwargs: (_f(_e) for _e in _s)
else:
    xmap = lambda *args, **kwargs: list(map(*args, **kwargs))
    gmap = map
lmap = xmap

# `long` is gone in python3
try:
    isinstance(int, long)
except NameError:
    long = int

# (progn (forward-line 1) (snip-insert "py_f.lfind" t t "python") (insert "\n"))
def lfind(l, elt):
    try:
        return l.index(elt)
    except ValueError:
        return -1

import os
import re

# --------------------------------------------------
# |||:sec:||| CONFIGURATION
# --------------------------------------------------

__all__ = []
__all_internal__ = []

# (progn (forward-line 1) (snip-insert "py.b.dbg.def" t t "python") (insert ""))
dbg_fwid = globals().get('dbg_fwid', 15)

# (progn (forward-line 1) (snip-insert "py.b.canonize.module" t t "python") (insert ""))
def _canonize_module_(module_or_name, full=None, drop=None):
    if isstring(module_or_name):
        module = sys.modules[module_or_name]
    else:
        module = module_or_name
    module_name = module.__name__
    # flag for __main__
    _is_main_ = (module_name == '__main__')
    if not hasattr(module, '_is_main_'):
        module._is_main_ = _is_main_
    if not full:
        return _is_main_
    # module file name -> canonical name
    try:
        mfile = module.__file__
    except AttributeError:
        return
    canon_name_ = mfile
    canon_name_ = os.path.basename(canon_name_)
    canon_name_, _ext = os.path.splitext(canon_name_)
    # adhoc compiliation xx_.py -> xx.py
    if canon_name_.endswith('_') and not canon_name_.endswith('__'):
        canon_name_ = canon_name_[:-1]
    canon_name_ = re.sub('[^0-9A-Za-z_]+', '_', canon_name_)
    # find parent module |:check:| distutils/pkg_resources?
    mdir = os.path.abspath(os.path.dirname(mfile))
    mparts = []
    while mdir and os.path.exists(os.path.join(mdir, '__init__.py')):
        mdir, pfx = os.path.split(mdir)
        mparts.insert(0, pfx)
    parent = '.'.join(mparts)
    if canon_name_ != '__init__':
        mparts.append(canon_name_)
    if drop:
        mparts = mparts[:-drop]
    canon_name = '.'.join(mparts)
    if module_name != canon_name:
        if parent != canon_name or drop: # |:check:| why?
            if parent:
                # fix parent module
                exec('import ' + parent)
                if parent in (sys.modules):
                    setattr(sys.modules[parent], canon_name_, module)
            sys.modules[canon_name] = module
        module.__name__ = canon_name
        # adjust module members
        for t in dvalues(vars(module)):
            try:
                if '__module__' in vars(t) and t.__module__ == module_name:
                    t.__module__ = canon_name
            except TypeError:
                pass
    return _is_main_

#_canonize_module_(__name__, __name__ == '__main__')

# (progn (forward-line 1) (snip-insert "py_b.strings" t t "python" " --key skip_for_update --key only_ucsx") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.f.strclean" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.b.logging" t t "python") (insert ""))
# (progn (forward-line 1) (snip-insert "py_b.ordereddict" t t "py" " --key skip_for_update") (insert "\n"))
OrderedDict = dict
_check_data = [(_i * (-1)**_i, None) for _i in reversed(range(5))]
if globals().get('_USE_COLLECTIONS_ORDEREDDICT') or list(ditems(OrderedDict(_check_data))) != _check_data:
    try:
        from collections import OrderedDict
    except ImportError:
        try:
            from ordereddict import OrderedDict
        except ImportError:
            printf('error: ordereddict missing. Try `pip install ordereddict`.', file=sys.stderr)
            sys.exit(1)
        import collections
        collections.OrderedDict = OrderedDict
del(globals()['_check_data'])

# (progn (forward-line 1) (snip-insert "py.b.dbg.setup" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.main.project.libdir" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.main.sql.alchemy" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.main.sql.ws" t t "py") (insert "\n"))

# @:adhoc_run_time:@
#import adhoc                                               # @:adhoc:@

# (progn (forward-line 1) (snip-insert "py.b.posix" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.b.os.system.sh" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.b.prog.path" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_b.line-loop" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_b.table_standalone" t t "python") (insert ""))

# (progn (forward-line 1) (snip-insert "py.wsrfid.pylons.imports" t t "python") (insert ""))
# (progn (forward-line 1) (snip-insert "py.main.wsgi.get.app" t t "python") (insert ""))

# (progn (forward-line 1) (snip-insert "py_wsrfid.config_delayed" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_b.wsrfid.config_translate_shortcuts" t t "python") (insert "\n"))

# (progn (forward-line 1) (snip-insert "py_b.dba_imports" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_b.dba_datainit" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_jsmo.imports" t t "python") (insert "\n"))

# |:here:|

# --------------------------------------------------
# |||:sec:||| DATA
# --------------------------------------------------

# --------------------------------------------------
# |||:sec:||| CLASSES
# --------------------------------------------------

__all__.append('DiffMap')
[docs]class DiffMap(OrderedDict): # ||:cls:|| r""" .. uml:: :caption: Correlate Line Numbers from Diff Output @startuml class "DiffMap" { +s_line : integer +t_line : integer +t_to_s_map : dict ==== +__str__() +ranges() +parse_diff(diff_output) ---- +parse(source_file, target_file) +lookup(lookup_t_line) : mapped_s_line } @enduml >>> _debug = sys.modules["__main__"]._debug >>> text = '\n'.join(('line ' + str(_i) for _i in xrange(15))) >>> def write_file(file, line_nos): ... with open(file, 'w') as _fh: ... lines = list(text.splitlines()) ... for _i in line_nos: ... printf(lines[_i], file=_fh) >>> def dump_file(file): ... printf('\n'.join([sformat("{0:02d} | {1}", _i + 1, _l) ... for _i, _l in ... enumerate(open(file, 'r').read().splitlines())])) >>> write_file('/tmp/diffmap-source.txt', list(xrange(15))[1:]) >>> write_file('/tmp/diffmap-target.txt', [1, 2, 3, 4, 4, 5, 5, 6, 7, 11, 12, 13]) >>> dump_file('/tmp/diffmap-source.txt') #doctest: +ELLIPSIS 01 | line 1 02 | line 2 03 | line 3 04 | line 4 05 | line 5 06 | line 6 07 | line 7 08 | line 8 09 | line 9 10 | line 10 11 | line 11 12 | line 12 13 | line 13 14 | line 14 >>> dump_file('/tmp/diffmap-target.txt') #doctest: +ELLIPSIS 01 | line 1 02 | line 2 03 | line 3 04 | line 4 05 | line 4 06 | line 5 07 | line 5 08 | line 6 09 | line 7 10 | line 11 11 | line 12 12 | line 13 >>> printf(os.popen("diff --unified=0 '/tmp/diffmap-source.txt' '/tmp/diffmap-target.txt'", 'r').read(), end='') #doctest: +ELLIPSIS --- /tmp/diffmap-source.txt... +++ /tmp/diffmap-target.txt... @@ -4,0 +5,2 @@ +line 4 +line 5 @@ -8,3 +9,0 @@ -line 8 -line 9 -line 10 @@ -14 +12,0 @@ -line 14 >>> dm = DiffMap('/tmp/diffmap-source.txt', '/tmp/diffmap-target.txt') >>> printf(dm) # :INF: s_line : ]15[ # :INF: t_line : ]13[ # :INF: s_line - t_line: ]2[ # 0 - 6 ( 4) => 0 - 4 # 7 - 9 ( 9) => 5 - 7 # 10 - 12 ( 12) => 11 - 13 >>> for _item in ditems(dm): ... printf(_item) (0, 0) (1, 1) (2, 2) (3, 3) (4, 4) (5, 4) (6, 4) (7, 5) (8, 6) (9, 7) (10, 11) (11, 12) (12, 13) >>> os.unlink('/tmp/diffmap-source.txt') >>> os.unlink('/tmp/diffmap-target.txt') """ s_line = 0 t_line = 0 def __str__(self): # |:mth:| r""" :returns: self for chaining. """ ranges = self.ranges() return '\n'.join(( sformat("# "":INF: {1:<{0}s}: ]{2!s}[", dbg_fwid, "s_line", (self.s_line)), sformat("# "":INF: {1:<{0}s}: ]{2!s}[", dbg_fwid, "t_line", (self.t_line)), sformat("# "":INF: {1:<{0}s}: ]{2!s}[", dbg_fwid, "s_line - t_line", (self.s_line - self.t_line)), "\n".join(("# {0:4d} - {1:4d} ({2:4d}) => {3:4d} - {4:4d}".format(_r[0][0], _r[0][1], _r[0][0] + (_r[1][1] - _r[1][0]), _r[1][0], _r[1][1]) for _r in ranges)), )) def __init__(self, source_or_diff_output=None, target=None): # |:mth:| super(DiffMap, self).__init__() if source_or_diff_output is not None: if target is not None: self.parse(source_or_diff_output, target) else: self.parse(source_or_diff_output)
[docs] def clear(self): # |:mth:| r"""Clear data.""" self.s_line = 0 self.t_line = 0 super(DiffMap, self).clear()
[docs] def ranges(self): # |:mth:| r""" :returns: list of mapped ranges """ _t_first = 0 _s_first = 0 _t_line = 0 _s_line = 0 _in_s_range = False ranges = [] for _item in ditems(self): if _item[0] == 0 and _item[1] == 0: continue _t_line +=1 _s_line +=1 if _item[0] > _t_line: print("oops: t range not contiguous: {0} > {1}".format(_item[0], _t_line)) # printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "_t_line/_s_line", ((_t_line, _item[0]), (_s_line, _item[1])))) if _item[1] == _s_line - 1: # if not _in_s_range: # print("start range: s_line is identical: {0} == {1}".format(_item[1], _s_line - 1)) _in_s_range = True _s_line = _s_line - 1 continue if _in_s_range: ranges.append (((_t_first, _t_line - 1), (_s_first, _s_line - 1))) # print("range is finished s_line no longer identical: {0} != {1}".format(_item[1], _s_line - 1)) _t_first = _item[0] _t_line = _item[0] _s_first = _item[1] _s_line = _item[1] _in_s_range = False continue if _item[1] > _s_line: # print("range is finished s_line: {0} > {1}".format(_item[1], _t_line)) ranges.append (((_t_first, _t_line - 1), (_s_first, _s_line - 1))) _t_first = _item[0] _t_line = _item[0] _s_first = _item[1] _s_line = _item[1] continue ranges.append (((_t_first, _t_line), (_s_first, _s_line))) return ranges
[docs] def parse_diff(self, diff_output): # |:mth:| r"""Parse hunks in diff output. .. code-block:: sh :caption: check for diff edge case empty file printf "%s\n%s\n%s\n" 'hallo' 'hallo' 'hallo' | diff -u /dev/null - .. code-block:: diff :caption: check for diff edge case empty file, diff output --- /dev/null 2022-10-29 11:10:30.081667219 +0200 +++ - 2023-03-08 17:53:12.495842805 +0100 @@ -0,0 +1,3 @@ +hallo +hallo +hallo .. uml:: :caption: Correlate Line Numbers from Diff Output @startuml start :t_to_s_map = dict() s_line = 0 t_line = 0; ' |:here:| while (for each hunk) is (do) :_s_frm = number _s_cnt = default: 1 _t_frm = number _t_cnt = default: 1 _s_ofs = (_s_cnt == 0) + 0 _t_ofs = (_t_cnt == 0) + 0; while (s_line < _s_frm?) is (do) if (t_line < _t_frm + _t_ofs?) then (yes) :t_to_s_map[t_line] = s_line t_line += 1; endif :s_line += 1; endwhile if (_s_ofs?) then (yes) if (t_line < _t_frm + _t_ofs?) then (yes) :t_to_s_map[self.t_line] = s_line t_line += 1; endif endif while (t_line < _t_frm + _t_ofs?) is (do) :t_to_s_map[t_line] = s_line t_line += 1; endwhile while (for _indx in range(min(_s_cnt, _t_cnt))) is (do) :t_to_s_map[t_line] = s_line s_line += 1 t_line += 1; endwhile while (_t_cnt < _s_cnt?) is (do) :s_line += 1 _t_cnt += 1; endwhile while (_s_cnt < _t_cnt ?) is (do) :t_to_s_map[t_line] = s_line t_line += 1 _s_cnt += 1; endwhile if (_s_ofs?) then (yes) :s_line += 1; endif endwhile ://mapped_s_line// for //lookup_t_line >= _t_line_sup// is lookup_t_line + _s_line_sup - _t_line_sup; ' |:here:| stop @enduml """ # _debug = 1 # |:debug:| self.clear() t_to_s_map = self if hasattr(diff_output, 'read'): _fh = diff_output else: _fh = open(diff_output, 'r') for _line in _fh: if _line.startswith('@@'): _line = _line.rstrip() _mo = re.match('@@ *-([0-9]+)(?:,([0-9]+))? [+]([0-9]+)(?:,([0-9]+))? *@@', _line) if not _mo: printe(sformat("# ||"":ERR:|| error: invalid hunk header `{0}`", _line)) continue _s_frm = int(_mo.group(1) or 1) _s_cnt = int(_mo.group(2) or 1) _t_frm = int(_mo.group(3) or 1) _t_cnt = int(_mo.group(4) or 1) _s_ofs = (_s_cnt == 0) + 0 _t_ofs = (_t_cnt == 0) + 0 if _debug: _counts = ((_s_frm, _s_cnt, _s_ofs), (_t_frm, _t_cnt, _t_ofs)) _ident_st = (self.s_line, self.t_line) printe("# --------------------------------------------------") printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "line", (_line))) printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "frm/cnt/ofs", (_counts))) printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "ident s/t", (_ident_st))) while self.s_line < _s_frm: if (self.t_line < _t_frm + _t_ofs): t_to_s_map[self.t_line] = self.s_line self.t_line += 1 self.s_line += 1 if _s_ofs: if (self.t_line < _t_frm + _t_ofs): t_to_s_map[self.t_line] = self.s_line self.t_line += 1 while self.t_line < _t_frm + _t_ofs: t_to_s_map[self.t_line] = self.s_line self.t_line += 1 if _debug: _diff_st = (self.s_line, self.t_line) printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "diff s/t", (_diff_st))) for _indx in range(min(_s_cnt, _t_cnt)): t_to_s_map[self.t_line] = self.s_line self.s_line += 1 self.t_line += 1 while _t_cnt < _s_cnt: self.s_line += 1 _t_cnt += 1 while _s_cnt < _t_cnt: t_to_s_map[self.t_line] = self.s_line self.t_line += 1 _s_cnt += 1 if _s_ofs: self.s_line += 1 if _debug: _diff_end = (self.s_line, self.t_line) printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "end s/t", (_diff_end)))
[docs] def parse(self, source_file, target_file): # |:mth:| r"""Diff source and target file, parse diff output. """ _cmd = "diff --unified=0 {0} {1}".format(single_quote(source_file), single_quote(target_file)) with os.popen(_cmd, 'r') as _ph: self.parse_diff(_ph)
[docs] def lookup(self, t_line): # |:mth:| r"""Lookup target line. :returns: mapped source line for target line. """ s_line = self.get(t_line) if s_line is None: s_line = self.s_line + (t_line - self.t_line) return s_line
# (progn (forward-line -1) (insert "\n") (snip-insert "py.s.meth" t t "py") (backward-symbol-tag 1 "fillme" "::")) # (progn (forward-line -2) (insert "\n") (snip-insert "py.s.property" t t "py") (backward-symbol-tag 1 "fillme" "::")) # (progn (forward-line -1) (insert "\n") (snip-insert "py.s.class" t t "py") (backward-symbol-tag 1 "fillme" "::")) # -------------------------------------------------- # |||:sec:||| FUNCTIONS # -------------------------------------------------- # (progn (forward-line -1) (insert "\n") (snip-insert "py.s.func" t t "py") (backward-symbol-tag 1 "fillme" "::")) # (progn (forward-line 1) (snip-insert "py_wsrfid.customization" t t "python" " --key cust_delayed_skipx") (insert "\n")) # (progn (forward-line 1) (snip-insert "py_b.dba_setup_sql" t t "python") (insert "\n")) # (progn (forward-line 1) (snip-insert "py_b.dba_id_maps" t t "python") (insert "\n")) # (progn (forward-line 1) (snip-insert "py_b.dba_commands_init" t t "python") (insert "\n")) # (progn (forward-line 1) (snip-insert "py.wsrfid.module.route" t t "py") (insert "")) # -------------------------------------------------- # |||:sec:||| UTILITIES # -------------------------------------------------- # (progn (forward-line 1) (snip-insert "py.wsrfid.dispatch.request" t t "py") (insert "")) # (progn (forward-line 1) (snip-insert "py.f.findfile" t t "py") (insert "")) # (progn (forward-line 1) (snip-insert "py_f.next_numfile_seq" t t "python" " --key xwith_docstrings --key xwith_all_append") (insert "\n")) # (progn (forward-line 1) (snip-insert "py_f.add_prefix_indent" t t "python") (insert "\n")) # (progn (forward-line 1) (snip-insert "py.c.placeholder.template" t t "py") (insert "\n")) # (progn (forward-line 1) (snip-insert "py.c.key.hash.ordered.dict" t t "py") (insert "\n")) # (progn (forward-line 1) (snip-insert "py.c.progress" t t "py") (insert "\n")) # (progn (forward-line 1) (snip-insert "py.f.hl" t t "py") (insert "\n")) # (progn (forward-line 1) (snip-insert "py.f.single.quote" t t "py") (insert "\n")) def single_quote(string, enclose=True): _sq = "'" if enclose: pfx=_sq sfx=_sq else: pfx="" sfx="" _repl = "".join((_sq, "\\", _sq, _sq)) return "".join((pfx, re.sub(_sq, _repl, string), sfx)) # (progn (forward-line 1) (snip-insert "py.f.remove.match" t t "py") (insert "\n")) # (progn (forward-line 1) (snip-insert "py.f.printenv" t t "py") (insert "\n")) # (progn (forward-line 1) (snip-insert "py.f.uname.s" t t "py") (insert "\n")) # (progn (forward-line 1) (snip-insert "py_f.decoded_email_headers" t t "python") (insert "\n")) # (progn (forward-line 1) (snip-insert "py_f.print_utf8" t t "python") (insert "\n")) # (progn (forward-line 1) (snip-insert "py.f.printe" t t "py") (insert "")) def printe_(*args, **kwargs): kwargs['file'] = kwargs.get('file', sys.stderr) printf(*args, **kwargs) if 'printe' not in globals(): # or globals().get('_is_main_', (__name__ == '__main__')): printe = printe_ printd = printe_ printw = printe_ printx = printe_ # (progn (forward-line 1) (snip-insert "py.f.dbg.squeeze" t t "py") (insert "\n")) # (progn (forward-line 1) (snip-insert "py.f.dbg.indent" t t "py") (insert "\n")) # (progn (forward-line 1) (snip-insert "py_f.quick_dump" t t "python" " --key skip_for_update --key xfull_code --key xqt_annotator") (insert "\n")) # (progn (forward-line 1) (snip-insert "py_b.all.reverse" t t "python") (insert "\n")) if '__all_internal__' in globals(): import sys if 'sphinx.directives' in sys.modules: __all__[:0] = __all_internal__ __all_internal__ = list(reversed(__all_internal__)) __all__ = list(reversed(__all__)) # (progn (forward-line 1) (snip-insert "py_b.make_parameters" t t "python" " --key skip_for_update --key xfull_code --key xdump_obj_attribs --key xinternal") (insert "\n")) def run(parameters): # ||:fnc:|| r"""Application runner, when called as __main__.""" pred_not_internal_attrib = lambda _it: not _it[0].startswith('adhoc_') and _it[0] not in ('ap_help', 'help', 'test', 'args') # exec ('''for _it in ditems(vars(parameters)):\n if pred_not_internal_attrib(_it):\n printf(sformat(" {0},", _it))'''); return # (progn (forward-line 1) (snip-insert "py.bf.sql.ws" t t "py") (insert "\n")) # (progn (forward-line 1) (snip-insert "py.wsrfid.wsuvv.run" t t "py" " --key py_wsrfid.wsuvv_run --key skip_for_new") (insert "\n")) # (progn (forward-line 1) (snip-insert "py_shell.run" t t "python") (insert "\n")) # from pyjsmo.result import Result, IResult, ERR_NONE # result = IResult() # |:here:| # (progn (forward-line 1) (snip-insert "py_bf.file_arg_loop" t t "py" " --key skip_for_update --key with_decode_buffer") (insert "\n")) diff_map = DiffMap(*parameters.args[:2]) printe(diff_map) printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "2023 =>", (diff_map.lookup(2023)))) printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "2024 =>", (diff_map.lookup(2024)))) printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "2025 =>", (diff_map.lookup(2025)))) # ||:here:|| return # result.report() # return max(result.error, ERR_NONE) # -------------------------------------------------- # |||:sec:||| MAIN # -------------------------------------------------- _quiet = False _verbose = False _debug = False # (progn (forward-line 1) (snip-insert "py_f.argparse_callbacks" t t "python") (insert "\n")) # (progn (forward-line 1) (snip-insert "py_main.py" t t "python" " --key xpy_main_minimal") (insert "\n")) # (progn (forward-line 1) (snip-insert "py_f.setdefaultencoding" t t "python" " --key skip_for_update") (insert "\n")) #file_encoding_is_clean = True def setdefaultencoding(encoding=None, quiet=False, context=None): if context is None: context = globals() if context.get('file_encoding_is_clean'): return if encoding is None: encoding='utf-8' try: isinstance('', basestring) if not hasattr(sys, '_setdefaultencoding'): if not quiet: printf('''\ Add this to /etc/python2.x/sitecustomize.py, or put it in local sitecustomize.py and adjust PYTHONPATH=".:${PYTHONPATH}":: try: import sys setattr(sys, '_setdefaultencoding', getattr(sys, 'setdefaultencoding')) except AttributeError: pass Running with reload(sys) hack ... ''', file=sys.stderr) reload(sys) setattr(sys, '_setdefaultencoding', getattr(sys, 'setdefaultencoding')) sys._setdefaultencoding(encoding) except NameError: # python3 already has utf-8 default encoding ;-) pass def main(argv=None, context=None): # ||:fnc:|| if argv is None: argv = sys.argv if context is None: context = globals() context.get( 'setup_logger', globals().get( 'setup_logger', lambda *args: None))(context, True) try: import argparse except ImportError: printe('error: argparse missing. Try `easy_install argparse`.') sys.exit(1) parser = argparse.ArgumentParser(add_help=False, conflict_handler='resolve') # parser.add_argument('--sum', dest='accumulate', action='store_const', # const=sum, default=max, # help='sum the integers (default: find the max)') # |:opt:| add options context.get('_argparse_begin', lambda _p, *_args: _p)(parser, context) parser.add_argument( '-q', '--quiet', action='store_const', const=-2, dest='debug', default=0, help='suppress warnings') parser.add_argument( '-v', '--verbose', action='store_const', const=-1, dest='debug', default=0, help='verbose test output') parser.add_argument( '-d', '--debug', action='store_true', default=0, help='show debug information') parser.add_argument( '-h', '--help', action='store_true', help="display this help message") parser.add_argument( '-t', '--test', action='store_true', help='run doc tests') class AdHocAction(argparse.Action): options = ('implode', 'setup', 'explode', 'extract', 'template', 'eide') def __call__(self, parser, namespace, values, option_string=None): for _opt in self.options: setattr(namespace, 'adhoc_' + _opt, False) setattr(namespace, 'adhoc_' + option_string[2:], True) setattr(namespace, 'adhoc_arg', values) parser.add_argument( '--implode', nargs=0, action=AdHocAction, dest='adhoc_implode', default=False, help='implode script with adhoc') parser.add_argument( '--setup', nargs='?', action=AdHocAction, type=str, metavar='install', dest='adhoc_setup', default=False, const='install', help='explode script into temporary directory and call' ' `python setup.py install`') parser.add_argument( '--explode', nargs='?', action=AdHocAction, type=str, metavar='DIR', dest='adhoc_explode', default=False, const='__adhoc__', help='explode script with adhoc in directory DIR' ' (default: `__adhoc__`)') parser.add_argument( '--extract', nargs='?', action=AdHocAction, type=str, metavar='DIR', dest='adhoc_extract', default=False, const = '.', help='extract files to directory DIR (default: `.`)') parser.add_argument( '--template', nargs='?', action=AdHocAction, type=str, metavar='NAME', dest='adhoc_template', default=False, const = '-', help='extract named template to standard output. default NAME is ``-``') parser.add_argument( '--eide', nargs='?', action=AdHocAction, type=str, metavar='COMM', dest='adhoc_eide', default=False, const = '', help='Emacs IDE template list (implies --template list).') parser.add_argument( '--ap-help', action='store_true', help="internal help message") context.get('_argparse_end', lambda _p, *_args: _p)(parser, context) if not context.get('_argparse_have_sub_commands'): # all options and arguments are known # all non-option arguments are consumed by `_parameters.args` parser.add_argument( 'args', nargs='*', metavar='arg', #'args', nargs='+', metavar='arg', #type=argparse.FileType('r'), default=sys.stdin, help='a series of arguments') _parameters = parser.parse_args(argv[1:]) else: # (progn (forward-line 1) (snip-insert "py_f.args_split_range" t t "python") (insert "\n")) def args_split_range(args): next_range = [] for arg in args: next_range.append(arg) if not arg.startswith('-'): break if next_range and not next_range[0].startswith('-'): next_range = [] return next_range, args[len(next_range):] # for sub-commands with their own options: pre-parse to first # non-option argument _parameters = None args = argv[1:] while True: next_range, args = args_split_range(args) if not next_range and not _parameters is None: break _parameters, unknown_args = parser.parse_known_args(next_range, _parameters) if unknown_args: unknown_args.extend(args) args = unknown_args next_range = [] break _parameters.args = args # generate argparse help if _parameters.ap_help: parser.print_help() return 0 # standard help if _parameters.help: help_ = re.sub('\n+[.][.] _END_OF_HELP.*(?s)', '', context['__doc__']) sys.stdout.write(help_ + '\n') return 0 context['_debug'] = _parameters.debug if context['_debug'] == True: context['_debug'] = 1 if context['_debug'] > 0: context['_verbose'] = True context['_quiet'] = False elif context['_debug'] < 0: context['_verbose'] = (context['_debug'] == -1) context['_quiet'] = not(context['_verbose']) context['_debug'] = 0 _parameters.debug = context['_debug'] _parameters.verbose = context['_verbose'] _parameters.quiet = context['_quiet'] if context['_debug']: cmd_line = argv sys.stderr.write(sformat( "{0}{3:^{1}} {4:<{2}s}: ]{5!s}[\n", context.get('dbg_comm', '# '), context.get('dbg_twid', 11), context.get('dbg_fwid', 15), ':DBG:', 'cmd_line', cmd_line)) # at least use `quiet` to suppress the setdefaultencoding warning context.get('setdefaultencoding', globals().get('setdefaultencoding', lambda *_a, **_k: None))( quiet=context['_quiet'] or _parameters.test) # |:opt:| handle options # adhoc: implode/setup/explode/extract adhoc_get_opt = lambda opt: getattr( _parameters, 'adhoc_' + opt, None) adhoc_op = sum(((adhoc_get_opt(_opt) and 1) or 0 for _opt in AdHocAction.options)) if adhoc_op: for _opt in AdHocAction.options: setattr(_parameters, _opt, adhoc_get_opt(_opt)) adhoc_export = ( _parameters.setup or _parameters.explode or _parameters.extract) file_ = context['__file__'] source = None have_adhoc = 'AdHoc' in context have_rt_adhoc = 'RtAdHoc' in context # shall adhoc be imported if _parameters.implode or not have_rt_adhoc: # shall this file be compiled adhoc_compile = not (have_rt_adhoc) os_path = os.defpath for pv in ('PATH', 'path'): try: os_path = os.environ[pv] break except KeyError: pass os_path = os_path.split(os.pathsep) for path_dir in os_path: if not path_dir: continue if path_dir not in sys.path: sys.path.append(path_dir) if not have_adhoc: try: import adhoc context['AdHoc'] = adhoc.AdHoc except ImportError: adhoc_compile = False try: from rt_adhoc import RtAdHoc as Adhoc context['AdHoc'] = AdHoc except ImportError: pass else: adhoc_compile = False context['AdHoc'] = context['RtAdHoc'] AdHoc = context['AdHoc'] AdHoc.quiet = context['_quiet'] AdHoc.verbose = context['_verbose'] AdHoc.debug = context['_debug'] AdHoc.include_path.append(os.path.dirname(file_)) AdHoc.extra_templates = [ ] AdHoc.template_process_hooks = { } if _parameters.eide: AdHoc.tt_ide = True AdHoc.tt_comment = _parameters.adhoc_arg or '' AdHoc.tt_prefix = '. (shell-command "' AdHoc.tt_suffix = '")' _parameters.template = True _parameters.adhoc_arg = 'list' if adhoc_compile: ah = AdHoc() source = ah.compileFile(file_) else: file_, source = AdHoc.std_source_param(file_) # implode if _parameters.implode: # @:adhoc_enable:@ # if not context['_quiet']: # map(sys.stderr.write, # ["warning: ", os.path.basename(file_), # " already imploded!\n"]) # @:adhoc_enable:@ AdHoc.write_source('-', source) # explode elif _parameters.setup or _parameters.explode: _here = os.path.abspath('.') _clean_dir = False AdHoc.export_dir = _parameters.adhoc_arg if _parameters.setup: import tempfile _clean_dir = True AdHoc.export_dir = tempfile.mkdtemp('_setup', '__adhoc__') try: AdHoc.export(file_, source) if _parameters.setup: sq = lambda string: ''.join(("'", re.sub("'", """'\\''""", string), "'")) os.chdir(AdHoc.export_dir) os.system(sformat('{0} setup.py {1}', sq(sys.executable), sq(_parameters.adhoc_arg))) finally: if _clean_dir: try: os.chdir(_here) except: pass import shutil shutil.rmtree(AdHoc.export_dir) # extract elif _parameters.extract: AdHoc.extract_dir = _parameters.adhoc_arg AdHoc.extract(file_, source) # template elif _parameters.template: template_name = _parameters.adhoc_arg if not template_name: template_name = '-' if template_name == 'list': sys.stdout.write( '\n'.join(AdHoc.template_table(file_, source)) + '\n') else: template = AdHoc.get_named_template( template_name, file_, source) AdHoc.write_source('-', template) # restore for subsequent calls to main if not have_adhoc: del(AdHoc) return 0 # run doc tests if _parameters.test: import warnings warnings.simplefilter('default') import doctest # for :file:`__init__.py`, :func:`_canonize_module_` does not register the module in `sys.modules`. _canon_name = _module_name = context['__name__'] context.get('_canonize_module_', globals().get( '_canonize_module_', lambda *args: context.__setitem__('__name__', _canon_name)))(context['__name__'], context['__name__'] == '__main__') if context['__name__'] not in sys.modules: sys.modules[context['__name__']] = sys.modules[_module_name] try: logger = logging.getLogger() logger.setLevel(logging.DEBUG) except NameError: pass context.get('_doctest_hook_', lambda *args, **kwargs: None)(context) result = doctest.testmod(sys.modules[context['__name__']], verbose = context['_verbose']) return result.failed # run program final = False ecode = 0 try: try: ecode = context['run'](_parameters) except IOError: (t, e, tb) = sys.exc_info() del(tb) # ignore SIGPIPE import errno if e.errno != errno.EPIPE: raise except SystemExit: raise except: # |:info:| this is used, since module cgitb does not work so well ... (t, e, tb) = sys.exc_info() if not final or context['_debug']: import traceback printf(''.join(traceback.format_tb(tb)), file=sys.stderr, end='') printf(sformat('{0}: {1}', t.__name__, e), file=sys.stderr) del(tb) ecode = 1 return ecode if globals().get('_is_main_', (__name__ == '__main__')): #sys.argv.insert(1, '--debug') # |:debug:| result = main(sys.argv, globals()) sys.exit(result) # |:here:| # (progn (forward-line 1) (snip-insert "py.t.ide" t t "py") (insert "\n")) # # :ide-menu: Emacs IDE Main Menu - Buffer @BUFFER@ # . M-x `eIDE-menu' (eIDE-menu "z") # :ide: CSCOPE ON # . (cscope-minor-mode) # :ide: CSCOPE OFF # . (cscope-minor-mode (quote ( nil ))) # :ide: TAGS: forced update # . (compile (concat "cd /home/ws/project/ws-rfid && make -k FORCED=1 tags")) # :ide: TAGS: update # . (compile (concat "cd /home/ws/project/ws-rfid && make -k tags")) # :ide: +-#+ # . Utilities () # :ide: TOC: Generate TOC with py-toc.py # . (progn (save-buffer) (compile (concat "py-toc.py " (shell-quote-argument (buffer-file-name)) " "))) # :ide: CMD: Fold region with line continuation # . (shell-command-on-region (region-beginning) (region-end) "fold --spaces -width 79 | sed 's, $,,;1!s,^, ,;$!s,$,\\\\,'" nil nil nil t) # :ide: CMD: Fold region and replace with line continuation # . (shell-command-on-region (region-beginning) (region-end) "fold --spaces --width 79 | sed 's, $,,;1!s,^, ,;$!s,$,\\\\,'" t nil nil t) # :ide: +-#+ # . Fold () # :ide: CMD: Remove 8 spaces and add `>>> ' to region # . (shell-command-on-region (region-beginning) (region-end) "sed 's,^ ,,;/^[ ]*##/d;/^[ ]*#/{;s,^ *# *,,p;d;};/^[ ]*$/!s,^,>>> ,'" nil nil nil t) # :ide: CMD: Remove 4 spaces and add `>>> ' to region # . (shell-command-on-region (region-beginning) (region-end) "sed 's,^ ,,;/^[ ]*##/d;/^[ ]*#/{;s,^ *# *,,p;d;};/^[ ]*$/!s,^,>>> ,'" nil nil nil t) # :ide: +-#+ # . Doctest () # :ide: LINT: Check 80 column width ignoring IDE Menus # . (let ((args " | /srv/ftp/pub/check-80-col.sh -")) (compile (concat "sed 's,^\\(\\|. \\|.. \\|... \\)\\(:ide\\|[.] \\).*,,' " (buffer-file-name) " " args " | sed 's,^-," (buffer-file-name) ",'"))) # :ide: LINT: Check 80 column width # . (let ((args "")) (compile (concat "/srv/ftp/pub/check-80-col.sh " (buffer-file-name) " " args))) # :ide: +-#+ # . Lint Tools () # :ide: DELIM: @: SYM :@ @:fillme:@ adhoc tag # . (symbol-tag-normalize-delimiter (cons (cons nil "@:") (cons ":@" nil)) t) # :ide: +-#+ # . Delimiters () # :ide: COMPILE: Run with --ap-help # . (progn (save-buffer) (compile (concat "python2 " (shell-quote-argument (buffer-file-name)) " --ap-help"))) # :ide: COMPILE: Run with --help # . (progn (save-buffer) (compile (concat "python2 " (shell-quote-argument (buffer-file-name)) " --help"))) # :ide: COMPILE: Run with --test # . (progn (save-buffer) (compile (concat "python2 " (shell-quote-argument (buffer-file-name)) " --test"))) # :ide: COMPILE: Run with --test --verbose # . (progn (save-buffer) (compile (concat "python2 " (shell-quote-argument (buffer-file-name)) " --test --verbose"))) # :ide: COMPILE: Run with --debug # . (progn (save-buffer) (compile (concat "python2 " (shell-quote-argument (buffer-file-name)) " --debug"))) # :ide: +-#+ # . Compile with standard arguments () # :ide: OCCUR-OUTLINE: Python Source Code # . (x-symbol-tag-occur-outline "sec" '("|||:" ":|||") (cons (cons "^\\([ \t\r]*\\(def\\|class\\)[ ]+\\|[A-Za-z_]?\\)" nil) (cons nil "\\([ \t\r]*(\\|[ \t]*=\\)"))) # :ide: MENU-OUTLINE: Python Source Code # . (x-eIDE-menu-outline "sec" '("|||:" ":|||") (cons (cons "^\\([ \t\r]*\\(def\\|class\\)[ ]+\\|[A-Za-z_]?\\)" nil) (cons nil "\\([ \t\r]*(\\|[ \t]*=\\)"))) # :ide: +-#+ # . Outline () # :ide: INFO: SQLAlchemy - SQL Expression Language - Reference # . (let ((ref-buffer "*sqa-expr-ref*")) (if (not (get-buffer ref-buffer)) (shell-command (concat "w3m -dump -cols " (number-to-string (1- (window-width))) " 'http://www.sqlalchemy.org/docs/05/reference/sqlalchemy/expressions.html'") ref-buffer) (display-buffer ref-buffer t))) # :ide: INFO: SQLAlchemy - SQL Expression Language - Tutorial # . (let ((ref-buffer "*sqa-expr-tutor*")) (if (not (get-buffer ref-buffer)) (shell-command (concat "w3m -dump -cols " (number-to-string (1- (window-width))) " 'http://www.sqlalchemy.org/docs/05/sqlexpression.html'") ref-buffer) (display-buffer ref-buffer t))) # :ide: INFO: SQLAlchemy - Query # . (let ((ref-buffer "*sqa-query*")) (if (not (get-buffer ref-buffer)) (shell-command (concat "w3m -dump -cols " (number-to-string (1- (window-width))) " 'http://www.sqlalchemy.org/docs/orm/query.html'") ref-buffer) (display-buffer ref-buffer t))) # :ide: +-#+ # . SQLAlchemy Reference () # :ide: INFO: Python - argparse # . (let ((ref-buffer "*python-argparse*")) (if (not (get-buffer ref-buffer)) (shell-command (concat "w3m -dump -cols " (number-to-string (1- (window-width))) " 'http://docs.python.org/library/argparse.html'") ref-buffer) (display-buffer ref-buffer t))) # :ide: INFO: Python Documentation # . (let ((ref-buffer "*w3m*")) (if (get-buffer ref-buffer) (display-buffer ref-buffer t)) (other-window 1) (w3m-goto-url "http://docs.python.org/index.html" nil nil)) # :ide: INFO: Python Reference # . (let* ((ref-buffer "*python-ref*") (local "/home/ws/project/ws-util/python/reference/PQR2.7.html") (url (or (and (file-exists-p local) local) "'http://rgruet.free.fr/PQR27/PQR2.7.html'"))) (unless (get-buffer ref-buffer) (get-buffer-create ref-buffer) (with-current-buffer ref-buffer (shell-command (concat "snc txt.py.reference 2>/dev/null") ref-buffer) (goto-char (point-min)) (if (eobp) (shell-command (concat "w3m -dump -cols " (number-to-string (1- (window-width))) " " url) ref-buffer)))) (display-buffer ref-buffer t)) # :ide: +-#+ # . Python Reference () # :ide: QUO: .. . >>> sys.modules["__main__"]._debug = 1\n.. . >>> _debug # . (insert "\n.. . >>> sys.modules[\"__main__\"]._debug = 1\n.. . >>> _debug = sys.modules[\"__main__\"]._debug\n\n.. . >>> sys.modules[\"__main__\"]._debug = 0\n.. . >>> _debug = sys.modules[\"__main__\"]._debug\n") # :ide: SHELL: Run with --eide # output in separate buffer *@BUFFER@* # . (let* ((args "--eide") (setup "python2 ") (how (quote (s a c g))) (out (quote (b s p))) (f (buffer-file-name)) (b (file-name-nondirectory f)) (n (buffer-name)) (o (cond ((eq (car how) (quote c)) nil) ((eq (car how) (quote g)) nil) ((eq (car out) (quote b)) (concat "*" n "*")) ((eq (car out) (quote p)) t) (t (and (boundp (quote eIDE-current-prefix-arg)) eIDE-current-prefix-arg))))) (save-buffer) (funcall (cond ((eq (car how) (quote a)) (quote async-shell-command)) ((eq (car how) (quote c)) (quote compile)) ((eq (car how) (quote g)) (function (lambda (c o) (grep c)))) (t (quote shell-command))) (concat setup (shell-quote-argument f) " " args) o)) # :ide: COMP: Run with python3 with --test # . (let* ((args "--test") (setup "python3 ") (how (quote (c g s a))) (out (quote (s p b))) (f (buffer-file-name)) (b (file-name-nondirectory f)) (n (buffer-name)) (o (cond ((eq (car how) (quote c)) nil) ((eq (car how) (quote g)) nil) ((eq (car out) (quote b)) (concat "*" n "*")) ((eq (car out) (quote p)) t) (t (and (boundp (quote eIDE-current-prefix-arg)) eIDE-current-prefix-arg))))) (save-buffer) (funcall (cond ((eq (car how) (quote a)) (quote async-shell-command)) ((eq (car how) (quote c)) (quote compile)) ((eq (car how) (quote g)) (function (lambda (c o) (grep c)))) (t (quote shell-command))) (concat setup (shell-quote-argument f) " " args) o)) # :ide: COMP: Run with python3 with/out arguments # . (let* ((args "") (setup "python3 ") (how (quote (c g s a))) (out (quote (s p b))) (f (buffer-file-name)) (b (file-name-nondirectory f)) (n (buffer-name)) (o (cond ((eq (car how) (quote c)) nil) ((eq (car how) (quote g)) nil) ((eq (car out) (quote b)) (concat "*" n "*")) ((eq (car out) (quote p)) t) (t (and (boundp (quote eIDE-current-prefix-arg)) eIDE-current-prefix-arg))))) (save-buffer) (funcall (cond ((eq (car how) (quote a)) (quote async-shell-command)) ((eq (car how) (quote c)) (quote compile)) ((eq (car how) (quote g)) (function (lambda (c o) (grep c)))) (t (quote shell-command))) (concat setup (shell-quote-argument f) " " args) o)) # :ide: COMP: Run with/out arguments # . (let* ((args "") (setup "python2 ") (how (quote (c g s a))) (out (quote (s p b))) (f (buffer-file-name)) (b (file-name-nondirectory f)) (n (buffer-name)) (o (cond ((eq (car how) (quote c)) nil) ((eq (car how) (quote g)) nil) ((eq (car out) (quote b)) (concat "*" n "*")) ((eq (car out) (quote p)) t) (t (and (boundp (quote eIDE-current-prefix-arg)) eIDE-current-prefix-arg))))) (save-buffer) (funcall (cond ((eq (car how) (quote a)) (quote async-shell-command)) ((eq (car how) (quote c)) (quote compile)) ((eq (car how) (quote g)) (function (lambda (c o) (grep c)))) (t (quote shell-command))) (concat setup (shell-quote-argument f) " " args) o)) # :ide: COMP: Run as diff -u0 "${HOME}"'/project/administration/README-redistribution-of-info-items.txt' "${HOME}"'/project/administration/doc/redistribution-of-info-items.rst.auto' # . (let* ((args "\"${HOME}\"'/project/administration/README-redistribution-of-info-items.txt' \"${HOME}\"'/project/administration/doc/redistribution-of-info-items.rst.auto'") (setup (concat "diff -u0 " args "; #" )) (how (quote (c g s a))) (out (quote (s p b))) (f (buffer-file-name)) (b (file-name-nondirectory f)) (n (buffer-name)) (o (cond ((eq (car how) (quote c)) nil) ((eq (car how) (quote g)) nil) ((eq (car out) (quote b)) (concat "*" n "*")) ((eq (car out) (quote p)) t) (t (and (boundp (quote eIDE-current-prefix-arg)) eIDE-current-prefix-arg))))) (save-buffer) (funcall (cond ((eq (car how) (quote a)) (quote async-shell-command)) ((eq (car how) (quote c)) (quote compile)) ((eq (car how) (quote g)) (function (lambda (c o) (grep c)))) (t (quote shell-command))) (concat setup (shell-quote-argument f) " " args) o)) # :ide: COMP: Run with --debug "${HOME}"'/project/administration/README-redistribution-of-info-items.txt' "${HOME}"'/project/administration/doc/redistribution-of-info-items.rst.auto' # . (let* ((args "--debug \"${HOME}\"'/project/administration/README-redistribution-of-info-items.txt' \"${HOME}\"'/project/administration/doc/redistribution-of-info-items.rst.auto'") (setup "python2 ") (how (quote (c g s a))) (out (quote (s p b))) (f (buffer-file-name)) (b (file-name-nondirectory f)) (n (buffer-name)) (o (cond ((eq (car how) (quote c)) nil) ((eq (car how) (quote g)) nil) ((eq (car out) (quote b)) (concat "*" n "*")) ((eq (car out) (quote p)) t) (t (and (boundp (quote eIDE-current-prefix-arg)) eIDE-current-prefix-arg))))) (save-buffer) (funcall (cond ((eq (car how) (quote a)) (quote async-shell-command)) ((eq (car how) (quote c)) (quote compile)) ((eq (car how) (quote g)) (function (lambda (c o) (grep c)))) (t (quote shell-command))) (concat setup (shell-quote-argument f) " " args) o)) # :ide: COMP: Run with --test --debug # . (let* ((args "--test --debug") (setup "python2 ") (how (quote (c g s a))) (out (quote (s p b))) (f (buffer-file-name)) (b (file-name-nondirectory f)) (n (buffer-name)) (o (cond ((eq (car how) (quote c)) nil) ((eq (car how) (quote g)) nil) ((eq (car out) (quote b)) (concat "*" n "*")) ((eq (car out) (quote p)) t) (t (and (boundp (quote eIDE-current-prefix-arg)) eIDE-current-prefix-arg))))) (save-buffer) (funcall (cond ((eq (car how) (quote a)) (quote async-shell-command)) ((eq (car how) (quote c)) (quote compile)) ((eq (car how) (quote g)) (function (lambda (c o) (grep c)))) (t (quote shell-command))) (concat setup (shell-quote-argument f) " " args) o)) # :ide: COMP: Run with --test # . (let* ((args "--test") (setup "python2 ") (how (quote (c g s a))) (out (quote (s p b))) (f (buffer-file-name)) (b (file-name-nondirectory f)) (n (buffer-name)) (o (cond ((eq (car how) (quote c)) nil) ((eq (car how) (quote g)) nil) ((eq (car out) (quote b)) (concat "*" n "*")) ((eq (car out) (quote p)) t) (t (and (boundp (quote eIDE-current-prefix-arg)) eIDE-current-prefix-arg))))) (save-buffer) (funcall (cond ((eq (car how) (quote a)) (quote async-shell-command)) ((eq (car how) (quote c)) (quote compile)) ((eq (car how) (quote g)) (function (lambda (c o) (grep c)))) (t (quote shell-command))) (concat setup (shell-quote-argument f) " " args) o)) # :ide: COMP: Run with "${HOME}"'/project/administration/README-redistribution-of-info-items.txt' "${HOME}"'/project/administration/doc/redistribution-of-info-items.rst.auto' # . (let* ((args "\"${HOME}\"'/project/administration/README-redistribution-of-info-items.txt' \"${HOME}\"'/project/administration/doc/redistribution-of-info-items.rst.auto'") (setup "python2 ") (how (quote (c g s a))) (out (quote (s p b))) (f (buffer-file-name)) (b (file-name-nondirectory f)) (n (buffer-name)) (o (cond ((eq (car how) (quote c)) nil) ((eq (car how) (quote g)) nil) ((eq (car out) (quote b)) (concat "*" n "*")) ((eq (car out) (quote p)) t) (t (and (boundp (quote eIDE-current-prefix-arg)) eIDE-current-prefix-arg))))) (save-buffer) (funcall (cond ((eq (car how) (quote a)) (quote async-shell-command)) ((eq (car how) (quote c)) (quote compile)) ((eq (car how) (quote g)) (function (lambda (c o) (grep c)))) (t (quote shell-command))) (concat setup (shell-quote-argument f) " " args) o)) # :ide: +-#+ # . Compile () # # Local Variables: # mode: python # comment-start: "#" # comment-start-skip: "#+" # comment-column: 0 # truncate-lines: t # End: