[sword-devel] Tagging verses and verse lists

DM Smith dmsmith at crosswire.org
Mon Mar 9 09:36:46 MST 2009

This has come at a good time. I am working on implementing a book mark 
facility for JSword.

See below for more...

Peter von Kaehne wrote:
> The thread I pull up here has some relevance
> 1) it was never concluded in theory and certainly no conclusions ever
> put into practice
> 2) With more and more applications becoming crossplatform there will be
> a growing and quite reasonable expectation by users to switch
> applications and be able to make use of their old bookmarks in some form.
> 3) looking at the wiki page on comparison, it is clear that there is a
> semblance of practical consensus between the various implementations of
> the feature
> a) bookmarks should be hierarchical,
> b) should be user editable/arrangable,
> c) should allow for some comment
> d) should allow both bulk addition via searches and by-hand addition
> e) should be exportable/sharable
> Eeli suggested in this thread that an editable GenBook with some special
> features is the overarching  best representation. I agree with this and
> suggested the same on gnomesword-devel, where Eeli referred me back to
> this old thread.
> So, is it time to resume the debate and bring it to a conclusion?
Here is what I'd like to see in a Bookmark facility (I'll use book 
rather than module below.):
* The user can bookmark a specific view of a book. The book may or may 
not be a Bible. It could just as well be a commentary or a dictionary.
* The view of a book might be a single keyed entry, a passage (from one 
keyed entry to another, inclusive) or might be a collection of passages.
* This view might be created by a search request.
* The view might have some options on and others off. (E.g. font info, 
headings, transliteration from Greek to Latin, and footnotes are on, 
rest off)
* The view might be of parallel bibles or linked to a companion.

For BD, we are talking about alternative ways of presenting a book's 
text and these have impact on the notion of a Bookmark.
For a dictionary, all entries are shown in a list that scrolls from 
first to last. The list dynamically loads only what is currently viewed.
For a Bible, the text that the user wants to see, even if it is the 
entire Bible is in a single pane, which dynamically loads only what is 
currently viewed.
Based on this:
* The view includes a notion of what (approximately) is being shown.

There are some minimal behaviors that make a Bookmark useful:
* It can be named.
* It can be used.
* It can be saved.
* When it is no longer needed, it can be deleted.

I think these are the core characteristics of what is tagged.

There are other ideas related to this core facility that we hope to use:

History and Navigation:
As a user jumps around in a particular view of a book (say by clicking 
on a cross-reference in a Bible) we have history events.

Applying the view of one book to another:
For example, having a Bookmark against a version of a Bible, it's keys 
can be applied against another book that understands Book/Chapter/Verse, 
such as a commentary.

Topic tagging and sub tagging:
Several users have asked for a way of creating a topical Bible. To them 
a topic is ultimately a named list of Bible keys. If the topic is large, 
it might have sub-topics.
One of the key characteristics of a topic is that it can be used in a 
search as a filter. That is the name of a Bookmark (or sub-bookmark) can 
be used to specify a collection of verses to search.

This is the ability to add comments:
a) to a Bookmark
b) to an entry in a Bookmark
The facility to annotate might also be presented to the user that they 
are highlighting some portion of text (perhaps spanning several keyed 
entries) and adding a comment to it. A particular entry might have 
several, possibly overlapping, annotations. It would be reasonable to 
add these to a specific bookmark, or named set of annotations.
These comments can be searched, just like notes.

Several users have asked for the application to start up at the place 
where it was last shutdown. I see shutdown as creating a bookmark set 
representing the state of the application and startup as using that 
state. Since, the user can have more than one instance of the 
application running at a time, that has to be managed. (I think Xiphos 
and BibleTime do something similar).

There are some additional features that are probably needed:
* The user can edit a particular BookMark.
* The user might want to export all or part of one or more Bookmarks to 
a particular context, e.g. a word processor, the clip board, to another 

Most of our applications already have some kind of book mark facility 
and therefore
* Existing bookmarks continue to work.

IMHO, in order for it to be useful across platforms, it should have a 
well defined file layout that allows arbitrary features to be present 
that are ignored unless understood. I was planning on using XML with 
it's own schema.

As to using current module types, the drawback is that each write of the 
same key, orphans the old text of the key, appends the text to the 
module and points the key to that new offset and size. The RawCom, 
manages each keyed entry as a separate file, so it doesn't have this 
grow on all edits problem. However, it cannot be used for bookmarking a 
dictionary as it is limited to KJV versification. I'm not sure that 
OSIS, ThML, TEI or GBF are up to the task of holding bookmarks.

In Him,

> Peter
> Troy A. Griffitts wrote:
>> Martin Gruner wrote:
>>> Will this be a part of Sword?
>>> Troy, what do you say?
>> Since most of our frontends have some type of verse list functionality, 
>> I would like for us to have something common in the engine we can all 
>> use.  This will also benefit our users, allowing them to share these 
>> between applications.  We would all have to agree on an interface 
>> though, so I'd appreciate hearing from other frontend developers on the 
>> proposed functionality and interface.  I would be particularly 
>> interested in whether you think a 'list' concept meets enough needs to 
>> warrant a mechanism.  BibleCS has basic verse lists, and also bookmark 
>> trees.  The bookmark trees seem more useful to me, but I would not have 
>> a straight forward path to modify BibleCS to use a 'PassageList' 
>> mechanism for trees.
>> I have some other comments below.
>> SWMgr is probably not the best place for this functionality.  SWMgr was 
>> our first 'manager' create 15+ years ago, and now that the engine has 
>> grown considerably, this should probably be renamed to something like 
>> SWModuleMgr, as its main purpose is to be a factory to hand back virtual 
>> base SWModule * objects.
>> Are we planning to handle any type of key lists with this interface? 
>> e.g., both Verse and GenBook references?
>> We also try to keep the std namespace out of the public interfaces the 
>> best we can.  It makes bindings easier to implement, thus, where the 
>> interface methods accept std::string, they should accept const char * or 
>> SWBuf if they are intentionally non-const.
>> I would suggest something like:
>> class KeyListMgr {
>> public:
>> 	KeyListMgr(cont char *configPath);
>> }
>> modeled after the LocaleMgr.
>> This would add a new subdirectory to our config root (along with 
>> mods.d/, modules/, locales.d/), something like keylists.d/, and I'm sure 
>> everyone would like to honor a ~/.sword/keylists.d/ as well.
>> If we are planning to go all out and extend the list interface to a tree 
>> interface, maybe a more generic name like BookmarkMgr would be better 
>> suited.
>> I realize this doesn't map directly to the purpose that Jonathan 
>> intended.  I don't know if there is an easy delineation to give us 
>> multiple uses.
>> Just my initial thoughts.  Looking forward to the conversation.
>> 	-Troy.
>>>> PassageList API:
>>>> typedef PassageListMap std::map<std::string, sword::PassageList>;
>>>> /**
>>>> Returns the passage list map, which maps unique names to passage lists.
>>>> */
>>>> PassageListMap SWMgr::getPassageLists();
>>>> /**
>>>> Creates a new passage list with the given name, and adds it to the
>>>> passage list map.
>>>> There must not already be a passage list with the given name.
>>>> */
>>>> PassageList SWMgr::addPassageList(std::string name);
>>>> /**
>>>> Creates a new passage list with the given name, and initialises it with the
>>>> given list of passages.
>>>> */
>>>> PassageList SWMgr::addPassageList(std::string name, ListKey passages);
>>>> /**
>>>> Removes the given passage list.
>>>> Returns true on success, and false on failure.
>>>> */
>>>> bool SWMgr::removePassageList(PassageList);
>>>> /**
>>>> Removes the passage list with the given name.
>>>> Returns true on success, and false on failure.
>>>> */
>>>> bool SWMgr::removePassageList(std::string name);
>>>> /**
>>>> A passage list must have a unique name to identify itself.
>>>> It may also have a description of the list, which can be used by the user.
>>>> */
>>>> PassageList
>>>> ===========
>>>> PassageList::get/setName()
>>>> PassageList::get/setDescription()
>>>> /**
>>>> Adds the given passage to the end of the passage list.
>>>> */
>>>> PassageList::addPassage(PassageEntry passage);
>>>> PassageList::addPassage(VerseKey passage);
>>>> PassageList::moveUp(int index);
>>>> PassageList::moveDown(int index);
>>>> /**
>>>> Removes the given passage entry from the list.
>>>> */
>>>> PassageList::removePassage(PassageEntry passage)
>>>> PassageList::removePassage(int index)
>>>> /**
>>>> Sorts the passage list.  At present, this will only support sorting it in
>>>> canonical order, but in the future, other sort orders may be supported.
>>>> */
>>>> void PassageList::sort(PassageListSortOrder order)
>>>> /**
>>>> Gets a list key with all the passages in the passage list.
>>>> */
>>>> ListKey PassageList::getListKey();
>>>> /**
>>>> Creates a new passage list with the same passages as this passage list, but
>>>> with the given new name.
>>>> */
>>>> PassageList PassageList::clone(std::string newName)
>>>> /**
>>>> Returns true if the given verse is contained in the passage list.
>>>> */
>>>> boolean PassageList::containsVerse(VerseKey verse)
>>>> /**
>>>> This class wraps around a VerseKey to allow additional attributes to be
>>>> attached to an entry in a passage list.  At present, the main addition that
>>>> is planned is attaching comments to passage entries.
>>>> */
>>>> PassageEntry
>>>> ============
>>>> /**
>>>> Creates a passage entry from the given verse.
>>>> */
>>>> PassageEntry(VerseKey verse)
>>>> /**
>>>> VerseKey PassageEntry::get/setPassage()
>>>> /**
>>>> For later extension.
>>>> */
>>>> std::string PassageEntry::get/setComment()

More information about the sword-devel mailing list