2008-12-06 09:30:38 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
|
|
|
|
2009-09-08 19:58:05 +00:00
|
|
|
###############################################################################
|
|
|
|
# OpenLP - Open Source Lyrics Projection #
|
|
|
|
# --------------------------------------------------------------------------- #
|
2009-12-31 12:52:01 +00:00
|
|
|
# Copyright (c) 2008-2010 Raoul Snyman #
|
|
|
|
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
|
2010-07-24 22:10:47 +00:00
|
|
|
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
|
|
|
|
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
|
|
|
|
# Carsten Tinggaard, Frode Woldsund #
|
2009-09-08 19:58:05 +00:00
|
|
|
# --------------------------------------------------------------------------- #
|
|
|
|
# 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; version 2 of the License. #
|
|
|
|
# #
|
|
|
|
# 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, write to the Free Software Foundation, Inc., 59 #
|
|
|
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
|
|
|
###############################################################################
|
2010-07-29 14:36:02 +00:00
|
|
|
"""
|
|
|
|
The :mod:`lib` module contains all the library functionality for the bibles
|
|
|
|
plugin.
|
|
|
|
"""
|
|
|
|
import logging
|
|
|
|
import re
|
|
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
2010-12-17 13:21:55 +00:00
|
|
|
def get_reference_match(match_type):
|
|
|
|
local_separator = unicode(u':;;\s*[:vV]\s*;;-;;\s*-\s*;;,;;\s*,\s*;;end'
|
|
|
|
).split(u';;') # English
|
|
|
|
# local_separator = unicode(u',;;\s*,\s*;;-;;\s*-\s*;;.;;\.;;[Ee]nde'
|
|
|
|
# ).split(u';;') # German
|
|
|
|
separators = {
|
|
|
|
u'sep_v_display': local_separator[0], u'sep_v': local_separator[1],
|
|
|
|
u'sep_r_display': local_separator[2], u'sep_r': local_separator[3],
|
|
|
|
u'sep_l_display': local_separator[4], u'sep_l': local_separator[5],
|
|
|
|
u'sep_e': local_separator[6]}
|
|
|
|
|
|
|
|
# verse range match: (<chapter>:)?<verse>(-(<chapter>:)?<verse>?)?
|
|
|
|
range_string = str(r'(?:(?P<from_chapter>[0-9]+)%(sep_v)s)?(?P<from_verse>'
|
|
|
|
r'[0-9]+)(?P<range_to>%(sep_r)s(?:(?:(?P<to_chapter>[0-9]+)%(sep_v)s)?'
|
|
|
|
r'(?P<to_verse>[0-9]+)|%(sep_e)s)?)?' % separators)
|
|
|
|
if match_type == u'range':
|
|
|
|
return re.compile(r'^\s*' + range_string + r'\s*$', re.UNICODE)
|
|
|
|
elif match_type == u'range_separator':
|
|
|
|
return re.compile(separators[u'sep_l'])
|
|
|
|
elif match_type == u'full':
|
|
|
|
# full reference match: <book>(<range>(,|(?=$)))+
|
|
|
|
return re.compile(str(r'^\s*(?!\s)(?P<book>[\d]*[^\d]+)(?<!\s)\s*'
|
|
|
|
r'(?P<ranges>(?:' + range_string + r'(?:%(sep_l)s|(?=\s*$)))+)\s*$')
|
|
|
|
% separators, re.UNICODE)
|
|
|
|
else:
|
|
|
|
return separators[match_type]
|
2010-12-13 19:06:07 +00:00
|
|
|
|
2010-12-16 20:00:01 +00:00
|
|
|
def parse_reference(reference):
|
2010-12-13 19:06:07 +00:00
|
|
|
"""
|
|
|
|
This is the next generation über-awesome function that takes a person's
|
|
|
|
typed in string and converts it to a reference list, a list of references to
|
|
|
|
be queried from the Bible database files.
|
|
|
|
|
2010-12-16 20:00:01 +00:00
|
|
|
This is a user manual like description, how the references are working.
|
|
|
|
|
|
|
|
- Each reference starts with the book name. A chapter name is manditory.
|
|
|
|
``John 3`` refers to Gospel of John chapter 3
|
|
|
|
- A reference range can be given after a range seperator.
|
|
|
|
``John 3-5`` refers to John chapters 3 to 5
|
|
|
|
- Single verses can be addressed after a verse seperator
|
|
|
|
``John 3:16`` refers to John chapter 3 verse 16
|
|
|
|
``John 3:16-4:3`` refers to John chapter 3 verse 16 to chapter 4 verse 3
|
|
|
|
- After a verse reference all further single values are treat as verse in
|
|
|
|
the last selected chapter.
|
|
|
|
``John 3:16-18`` refers to John chapter 3 verses 16 to 18
|
|
|
|
- After a list separator it is possible to refer to additional verses. They
|
|
|
|
are build analog to the first ones. This way it is possible to define each
|
|
|
|
number of verse references. It is not possible to refer to verses in
|
|
|
|
additional books.
|
|
|
|
``John 3:16,18`` refers to John chapter 3 verses 16 and 18
|
|
|
|
``John 3:16-18,20`` refers to John chapter 3 verses 16 to 18 to 20
|
|
|
|
``John 3:16-18,4:1`` refers to John chapter 3 verses 16 to 18 and
|
|
|
|
chapter 3 verse 1
|
|
|
|
- If there is a range separator without further verse declaration the last
|
|
|
|
refered chapter is addressed until the end.
|
|
|
|
|
2010-12-17 13:21:55 +00:00
|
|
|
``range_string`` is a regular expression which matches for verse range
|
2010-12-13 19:06:07 +00:00
|
|
|
declarations:
|
|
|
|
|
|
|
|
1. ``(?:(?P<from_chapter>[0-9]+)%(sep_v)s)?'
|
|
|
|
It starts with a optional chapter reference ``from_chapter`` followed by
|
|
|
|
a verse separator.
|
|
|
|
2. ``(?P<from_verse>[0-9]+)``
|
|
|
|
The verse reference ``from_verse`` is manditory
|
2010-12-17 13:21:55 +00:00
|
|
|
3. ``(?P<range_to>%(sep_r)s(?:`` ... ``|%(sep_e)s)?)?``
|
2010-12-16 20:00:01 +00:00
|
|
|
A ``range_to`` declaration is optional. It starts with a range seperator
|
2010-12-17 13:21:55 +00:00
|
|
|
and contains optional a chapter and verse declaration or a end
|
|
|
|
separator.
|
2010-12-16 20:00:01 +00:00
|
|
|
4. ``(?:(?P<to_chapter>[0-9]+)%(sep_v)s)?``
|
2010-12-13 19:06:07 +00:00
|
|
|
The ``to_chapter`` reference with seperator is equivalent to group 1.
|
2010-12-17 13:21:55 +00:00
|
|
|
5. ``(?P<to_verse>[0-9]+)``
|
2010-12-13 19:06:07 +00:00
|
|
|
The ``to_verse`` reference is equivalent to group 2.
|
|
|
|
|
2010-12-17 13:21:55 +00:00
|
|
|
The full reference is matched against get_reference_match(u'full'). This
|
|
|
|
regular expression looks like this:
|
2010-12-13 19:06:07 +00:00
|
|
|
|
2010-12-16 20:00:01 +00:00
|
|
|
1. ``^\s*(?!\s)(?P<book>[\d]*[^\d]+)(?<!\s)\s*``
|
2010-12-13 19:06:07 +00:00
|
|
|
The ``book`` group starts with the first non-whitespace character. There
|
|
|
|
are optional leading digits followed by non-digits. The group ends
|
|
|
|
before the whitspace in front of the next digit.
|
2010-12-17 13:21:55 +00:00
|
|
|
2. ``(?P<ranges>(?:`` + range_string + ``(?:%(sep_l)s|(?=\s*$)))+)\s*$``
|
|
|
|
The second group contains all ``ranges``. This can be multiple
|
|
|
|
declarations of a range_string separated by a list separator.
|
2010-12-13 19:06:07 +00:00
|
|
|
|
|
|
|
The reference list is a list of tuples, with each tuple structured like
|
|
|
|
this::
|
|
|
|
|
|
|
|
(book, chapter, from_verse, to_verse)
|
|
|
|
|
|
|
|
``reference``
|
|
|
|
The bible reference to parse.
|
|
|
|
|
|
|
|
Returns None or a reference list.
|
|
|
|
"""
|
|
|
|
|
|
|
|
log.debug('parse_reference("%s")', reference)
|
2010-12-17 13:21:55 +00:00
|
|
|
match = get_reference_match(u'full').match(reference)
|
2010-12-13 19:06:07 +00:00
|
|
|
if match:
|
|
|
|
log.debug(u'Matched reference %s' % reference)
|
|
|
|
book = match.group(u'book')
|
2010-12-17 13:21:55 +00:00
|
|
|
ranges = match.group(u'ranges')
|
|
|
|
range_list = get_reference_match(u'range_separator').split(ranges)
|
2010-12-16 20:00:01 +00:00
|
|
|
ref_list = []
|
2010-12-13 19:06:07 +00:00
|
|
|
chapter = 0
|
2010-12-17 13:21:55 +00:00
|
|
|
for this_range in range_list:
|
|
|
|
range_match = get_reference_match(u'range').match(this_range)
|
|
|
|
from_chapter = range_match.group(u'from_chapter')
|
|
|
|
from_verse = range_match.group(u'from_verse')
|
|
|
|
has_range = range_match.group(u'range_to')
|
|
|
|
to_chapter = range_match.group(u'to_chapter')
|
|
|
|
to_verse = range_match.group(u'to_verse')
|
2010-12-16 20:00:01 +00:00
|
|
|
if from_chapter:
|
|
|
|
from_chapter = int(from_chapter)
|
|
|
|
if from_verse:
|
|
|
|
from_verse = int(from_verse)
|
|
|
|
if to_chapter:
|
|
|
|
to_chapter = int(to_chapter)
|
|
|
|
if to_verse:
|
|
|
|
to_verse = int(to_verse)
|
2010-12-17 13:21:55 +00:00
|
|
|
# Fill chapter fields with reasonable values.
|
2010-12-13 19:06:07 +00:00
|
|
|
if from_chapter:
|
|
|
|
chapter = from_chapter
|
2010-12-16 20:00:01 +00:00
|
|
|
elif chapter:
|
2010-12-13 19:06:07 +00:00
|
|
|
from_chapter = chapter
|
2010-12-16 20:00:01 +00:00
|
|
|
else:
|
|
|
|
from_chapter = from_verse
|
|
|
|
from_verse = None
|
2010-12-13 19:06:07 +00:00
|
|
|
if to_chapter:
|
2010-12-16 20:00:01 +00:00
|
|
|
if to_chapter < from_chapter:
|
|
|
|
continue
|
|
|
|
else:
|
|
|
|
chapter = to_chapter
|
|
|
|
elif to_verse:
|
|
|
|
if chapter:
|
|
|
|
to_chapter = chapter
|
|
|
|
else:
|
|
|
|
to_chapter = to_verse
|
|
|
|
# Append references to the list
|
|
|
|
if has_range:
|
|
|
|
if not from_verse:
|
|
|
|
from_verse = 1
|
|
|
|
if not to_verse:
|
|
|
|
to_verse = -1
|
2010-12-13 19:06:07 +00:00
|
|
|
if to_chapter > from_chapter:
|
|
|
|
ref_list.append((book, from_chapter, from_verse, -1))
|
2010-12-17 13:21:55 +00:00
|
|
|
for i in range(from_chapter + 1, to_chapter - 1):
|
2010-12-13 19:06:07 +00:00
|
|
|
ref_list.append((book, i, 1, -1))
|
|
|
|
ref_list.append((book, to_chapter, 1, to_verse))
|
2010-12-17 13:21:55 +00:00
|
|
|
elif to_verse >= from_verse or to_verse == -1:
|
2010-12-13 19:06:07 +00:00
|
|
|
ref_list.append((book, from_chapter, from_verse, to_verse))
|
2010-12-16 20:00:01 +00:00
|
|
|
elif from_verse:
|
|
|
|
ref_list.append((book, from_chapter, from_verse, from_verse))
|
2010-12-13 19:06:07 +00:00
|
|
|
else:
|
2010-12-16 20:00:01 +00:00
|
|
|
ref_list.append((book, from_chapter, 1, -1))
|
|
|
|
return ref_list
|
2010-07-29 14:36:02 +00:00
|
|
|
else:
|
|
|
|
log.debug(u'Invalid reference: %s' % reference)
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
class SearchResults(object):
|
|
|
|
"""
|
2010-10-11 20:47:00 +00:00
|
|
|
Encapsulate a set of search results. This is Bible-type independent.
|
2010-07-29 14:36:02 +00:00
|
|
|
"""
|
|
|
|
def __init__(self, book, chapter, verselist):
|
|
|
|
"""
|
|
|
|
Create the search result object.
|
|
|
|
|
|
|
|
``book``
|
|
|
|
The book of the Bible.
|
|
|
|
|
|
|
|
``chapter``
|
|
|
|
The chapter of the book.
|
|
|
|
|
|
|
|
``verselist``
|
|
|
|
The list of verses for this reading
|
|
|
|
"""
|
|
|
|
self.book = book
|
|
|
|
self.chapter = chapter
|
|
|
|
self.verselist = verselist
|
|
|
|
|
|
|
|
def has_verselist(self):
|
|
|
|
"""
|
|
|
|
Returns whether or not the verse list contains verses.
|
|
|
|
"""
|
|
|
|
return len(self.verselist) > 0
|
|
|
|
|
2008-12-06 09:30:38 +00:00
|
|
|
|
2009-01-20 19:50:37 +00:00
|
|
|
from manager import BibleManager
|
2009-02-28 23:19:45 +00:00
|
|
|
from biblestab import BiblesTab
|
2010-07-27 09:32:52 +00:00
|
|
|
from mediaitem import BibleMediaItem
|