viminfo: First version of ShaDa file dumping

What works:

1. ShaDa file dumping: header, registers, jump list, history, search patterns,
   substitute strings, variables.
2. ShaDa file reading: registers, global marks, variables.

Most was not tested.

TODO:

1. Merging.
2. Reading history, local marks, jump and buffer lists.
3. Documentation update.
4. Converting some data from &encoding.
5. Safer variant of dumping viminfo (dump to temporary file then rename).
6. Removing old viminfo code (currently masked with `#if 0` in a ShaDa file for
   reference).
This commit is contained in:
ZyX
2015-04-25 18:47:31 +03:00
parent 0fdaab995e
commit 244dbe3a77
38 changed files with 4511 additions and 1848 deletions

73
scripts/shadacat.py Executable file
View File

@ -0,0 +1,73 @@
#!/usr/bin/env python3.4
import sys
import codecs
from enum import Enum
from datetime import datetime
from functools import reduce
import msgpack
class EntryTypes(Enum):
Unknown = -1
Missing = 0
Header = 1
SearchPattern = 2
SubString = 3
HistoryEntry = 4
Register = 5
Variable = 6
GlobalMark = 7
Jump = 8
BufferList = 9
LocalMark = 10
def strtrans_errors(e):
if not isinstance(e, UnicodeDecodeError):
raise NotImplementedError('dont know how to handle {0} error'.format(
e.__class__.__name__))
return '<{0:x}>'.format(reduce((lambda a, b: a*0x100+b),
list(e.object[e.start:e.end]))), e.end
codecs.register_error('strtrans', strtrans_errors)
def idfunc(o):
return o
class CharInt(int):
def __repr__(self):
return super(CharInt, self).__repr__() + ' (\'%s\')' % chr(self)
ctable = {
bytes: lambda s: s.decode('utf-8', 'strtrans'),
dict: lambda d: dict((mnormalize(k), mnormalize(v)) for k, v in d.items()),
list: lambda l: list(mnormalize(i) for i in l),
int: lambda n: CharInt(n) if 0x20 <= n <= 0x7E else n,
}
def mnormalize(o):
return ctable.get(type(o), idfunc)(o)
with open(sys.argv[1], 'rb') as fp:
unpacker = msgpack.Unpacker(file_like=fp)
while True:
try:
typ = EntryTypes(unpacker.unpack())
except msgpack.OutOfData:
break
else:
timestamp = unpacker.unpack()
time = datetime.fromtimestamp(timestamp)
length = unpacker.unpack()
entry = unpacker.unpack()
print('{0:13} {1} {2:5} {3!r}'.format(
typ.name, time.isoformat(), length, mnormalize(entry)))