mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Support for editing RTF metadata and documentation updates.
This commit is contained in:
parent
f119bb5994
commit
3bab77322e
@ -13,7 +13,7 @@
|
|||||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
''' E-book management software'''
|
''' E-book management software'''
|
||||||
__version__ = "0.3.44"
|
__version__ = "0.3.45"
|
||||||
__docformat__ = "epytext"
|
__docformat__ = "epytext"
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
|
|
||||||
|
@ -95,7 +95,8 @@ class TransferBuffer(list):
|
|||||||
"""
|
"""
|
||||||
Return a string representation of this buffer.
|
Return a string representation of this buffer.
|
||||||
|
|
||||||
Packets are represented as hex strings, in 2-byte pairs, S{<=} 16 bytes to a line. An ASCII representation is included. For example::
|
Packets are represented as hex strings, in 2-byte pairs, S{<=} 16 bytes to a line.
|
||||||
|
An ASCII representation is included. For example::
|
||||||
0700 0100 0000 0000 0000 0000 0c00 0000 ................
|
0700 0100 0000 0000 0000 0000 0c00 0000 ................
|
||||||
0200 0000 0400 0000 4461 7461 ........Data
|
0200 0000 0400 0000 4461 7461 ........Data
|
||||||
"""
|
"""
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
"""
|
"""
|
||||||
This package contains logic to read and write LRF files. The LRF file format is documented at U{http://www.sven.de/librie/Librie/LrfFormat}.
|
This package contains logic to read and write LRF files.
|
||||||
At the time fo writing, this package only supports reading and writing LRF meat information. See L{meta}.
|
The LRF file format is documented at U{http://www.sven.de/librie/Librie/LrfFormat}.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from optparse import OptionParser, OptionValueError
|
from optparse import OptionParser, OptionValueError
|
||||||
@ -53,8 +53,8 @@ def option_parser(usage):
|
|||||||
dest="title", help="Set the title. Default: filename.")
|
dest="title", help="Set the title. Default: filename.")
|
||||||
metadata.add_option("-a", "--author", action="store", type="string", \
|
metadata.add_option("-a", "--author", action="store", type="string", \
|
||||||
dest="author", help="Set the author. Default: %default", default='Unknown')
|
dest="author", help="Set the author. Default: %default", default='Unknown')
|
||||||
metadata.add_option("--freetext", action="store", type="string", \
|
metadata.add_option("--comment", action="store", type="string", \
|
||||||
dest="freetext", help="Set the comments.", default=' ')
|
dest="freetext", help="Set the comment.", default=' ')
|
||||||
metadata.add_option("--category", action="store", type="string", \
|
metadata.add_option("--category", action="store", type="string", \
|
||||||
dest="category", help="Set the category", default=' ')
|
dest="category", help="Set the category", default=' ')
|
||||||
metadata.add_option('--title-sort', action='store', default='', dest='title_sort',
|
metadata.add_option('--title-sort', action='store', default='', dest='title_sort',
|
||||||
|
@ -19,8 +19,26 @@ the L{libprs500.lrf.meta} module.
|
|||||||
__docformat__ = "epytext"
|
__docformat__ = "epytext"
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
|
|
||||||
|
from optparse import OptionParser
|
||||||
|
from libprs500 import __version__ as VERSION
|
||||||
|
|
||||||
|
def get_parser(extension):
|
||||||
|
''' Return an option parser with the basic metadata options already setup'''
|
||||||
|
parser = OptionParser(version='libprs500 version: '+VERSION,
|
||||||
|
usage='''%prog [options] myfile.'''+extension)
|
||||||
|
parser.add_option("-t", "--title", action="store", type="string", \
|
||||||
|
dest="title", help="Set the book title")
|
||||||
|
parser.add_option("-a", "--authors", action="store", type="string", \
|
||||||
|
dest="authors", help="Set the authors", default=None)
|
||||||
|
parser.add_option("-c", "--category", action="store", type="string", \
|
||||||
|
dest="category", help="The category this book belongs"+\
|
||||||
|
" to. E.g.: History", default=None)
|
||||||
|
parser.add_option('--comment', dest='comment', default=None, action='store',
|
||||||
|
help='Set the comment')
|
||||||
|
return parser
|
||||||
|
|
||||||
class MetaInformation(object):
|
class MetaInformation(object):
|
||||||
|
'''Convenient encapsulation of book metadata'''
|
||||||
|
|
||||||
def __init__(self, title, author):
|
def __init__(self, title, author):
|
||||||
self.title = title
|
self.title = title
|
||||||
|
@ -13,11 +13,11 @@
|
|||||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
"""
|
"""
|
||||||
Read metadata from RTF files.
|
Edit metadata in RTF files.
|
||||||
"""
|
"""
|
||||||
import re, cStringIO
|
import re, cStringIO, sys
|
||||||
|
|
||||||
from libprs500.ebooks.metadata import MetaInformation
|
from libprs500.ebooks.metadata import MetaInformation, get_parser
|
||||||
|
|
||||||
title_pat = re.compile(r'\{\\info.*?\{\\title(.*?)(?<!\\)\}', re.DOTALL)
|
title_pat = re.compile(r'\{\\info.*?\{\\title(.*?)(?<!\\)\}', re.DOTALL)
|
||||||
author_pat = re.compile(r'\{\\info.*?\{\\author(.*?)(?<!\\)\}', re.DOTALL)
|
author_pat = re.compile(r'\{\\info.*?\{\\author(.*?)(?<!\\)\}', re.DOTALL)
|
||||||
@ -27,7 +27,7 @@ category_pat = re.compile(r'\{\\info.*?\{\\category(.*?)(?<!\\)\}', re.DOTALL)
|
|||||||
def get_document_info(stream):
|
def get_document_info(stream):
|
||||||
"""
|
"""
|
||||||
Extract the \info block from an RTF file.
|
Extract the \info block from an RTF file.
|
||||||
Return the info block as a stringa and the position in the file at which it
|
Return the info block as a string and the position in the file at which it
|
||||||
starts.
|
starts.
|
||||||
@param stream: File like object pointing to the RTF file.
|
@param stream: File like object pointing to the RTF file.
|
||||||
"""
|
"""
|
||||||
@ -81,7 +81,7 @@ def get_metadata(stream):
|
|||||||
author = author_match.group(1).strip()
|
author = author_match.group(1).strip()
|
||||||
comment_match = comment_pat.search(block)
|
comment_match = comment_pat.search(block)
|
||||||
if comment_match:
|
if comment_match:
|
||||||
title = comment_match.group(1).strip()
|
comment = comment_match.group(1).strip()
|
||||||
category_match = category_pat.search(block)
|
category_match = category_pat.search(block)
|
||||||
if category_match:
|
if category_match:
|
||||||
category = category_match.group(1).strip()
|
category = category_match.group(1).strip()
|
||||||
@ -90,12 +90,67 @@ def get_metadata(stream):
|
|||||||
mi.category = category
|
mi.category = category
|
||||||
return mi
|
return mi
|
||||||
|
|
||||||
def main():
|
def set_metadata(stream, options):
|
||||||
import sys
|
'''
|
||||||
if len(sys.argv) != 2:
|
Modify/add RTF metadata in stream
|
||||||
print >> sys.stderr, "Usage:", sys.argv[0], " mybook.rtf"
|
@param options: Object with metadata attributes title, author, comment, category
|
||||||
|
'''
|
||||||
|
def add_metadata_item(src, name, val):
|
||||||
|
index = src.rindex('}')
|
||||||
|
return src[:index] + r'{\ '[:-1] + name + ' ' + val + '}}'
|
||||||
|
src, pos = get_document_info(stream)
|
||||||
|
olen = len(src)
|
||||||
|
base_pat = r'\{\\name(.*?)(?<!\\)\}'
|
||||||
|
title = options.title
|
||||||
|
if title != None:
|
||||||
|
title = title.encode('ascii', 'replace')
|
||||||
|
pat = re.compile(base_pat.replace('name', 'title'), re.DOTALL)
|
||||||
|
if pat.search(src):
|
||||||
|
src = pat.sub(r'{\\title ' + title + r'}', src)
|
||||||
|
else:
|
||||||
|
src = add_metadata_item(src, 'title', title)
|
||||||
|
comment = options.comment
|
||||||
|
if comment != None:
|
||||||
|
comment = comment.encode('ascii', 'replace')
|
||||||
|
pat = re.compile(base_pat.replace('name', 'subject'), re.DOTALL)
|
||||||
|
if pat.search(src):
|
||||||
|
src = pat.sub(r'{\\subject ' + comment + r'}', src)
|
||||||
|
else:
|
||||||
|
src = add_metadata_item(src, 'subject', comment)
|
||||||
|
author = options.authors
|
||||||
|
if author != None:
|
||||||
|
author = author.encode('ascii', 'replace')
|
||||||
|
pat = re.compile(base_pat.replace('name', 'author'), re.DOTALL)
|
||||||
|
if pat.search(src):
|
||||||
|
src = pat.sub(r'{\\author ' + author + r'}', src)
|
||||||
|
else:
|
||||||
|
src = add_metadata_item(src, 'author', author)
|
||||||
|
category = options.category
|
||||||
|
if category != None:
|
||||||
|
category = category.encode('ascii', 'replace')
|
||||||
|
pat = re.compile(base_pat.replace('name', 'category'), re.DOTALL)
|
||||||
|
if pat.search(src):
|
||||||
|
src = pat.sub(r'{\\category ' + category + r'}', src)
|
||||||
|
else:
|
||||||
|
src = add_metadata_item(src, 'category', category)
|
||||||
|
stream.seek(pos + olen)
|
||||||
|
after = stream.read()
|
||||||
|
stream.seek(pos)
|
||||||
|
stream.truncate()
|
||||||
|
stream.write(src)
|
||||||
|
stream.write(after)
|
||||||
|
|
||||||
|
|
||||||
|
def main(args=sys.argv):
|
||||||
|
parser = get_parser('rtf')
|
||||||
|
options, args = parser.parse_args(args)
|
||||||
|
if len(args) != 2:
|
||||||
|
parser.print_help()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
print get_metadata(open(sys.argv[1]))
|
stream = open(args[1], 'r+b')
|
||||||
|
set_metadata(stream, options)
|
||||||
|
mi = get_metadata(stream)
|
||||||
|
return mi
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
Loading…
x
Reference in New Issue
Block a user