#!/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: