Quote:
Originally Posted by eschwartz
You can simply include the GPM template directly in the plugboard definition. Right-click and there will be an option to use the Template Editor.
(When saved, it appears as if it is one line, but internally linebreaks are still saved as '\n' -- also, linebreaks may help you read it but they don't affect the parsing.)
|
I just found out there was such a thing as a template editor right before I read your message. Apparently it's even possible to change the template on a custom column without restarting Calibre! Who knew. Anyway. That's jsut my struggle with some UI bits.
Quote:
Again, you just need to feed finish_formatting() with the formatting specification in the custom column.
Code:
{series_index:0>5.2f| – | – }
becomes
Code:
finish_formatting(field('#series'), field('#format_str'), ' – ', ' – ')
|
Okay, so that'd become something like
Code:
program:
strcat(
field('series'),
finish_formatting(field('series_index'), field('#format_str'), ' – ', ' – '),
field('title')
)
, right? And that *almost* works, except that the template really doesn't like actually doing that finish_formatting operation -- "TEMPLATE ERROR unknown format code 'f' for object of type unicode". That was when I moved on to the extra column because that's what the docs seemed to imply.
Hardcoding a format..... right. wait. What that function expects is apparently "05.1f", not "{0:05.1f}". So it might work if I simplified the generating script a little.
Yup.
That does the trick.
So just for documentation purposes, here's my working setup:
Spoiler:
Intention: Series indexes will get a fixed number of digits before the decimal point, filled out with 0s in front whenever necessary. Those books with Integer indexes will get just those as index, and those books in a series that have a fractional index will get those with a number of digits after the decimal point that is also the same per series.
For instance, a series with a couple of fractional books, and mostly just lots of them, might get numbered:
Code:
001
001.5
002
003
003.1
003.2
[...]
011
013.3
801
802
803
803.2
The script to generate the custom formatting column:
Code:
def init_cache(library_path = None):
from calibre.db.backend import DB
from calibre.db.cache import Cache
from calibre.utils.config import prefs
if library_path == None:
library_path = prefs['library_path']
backend = DB(library_path)
cache = Cache(backend)
cache.init()
return cache
cache = init_cache()
#cache = init_cache('/Users/jasper/Documents/Calibre Main Library/')
#cache = init_cache(library_path = '/Users/jasper/Documents/Calibre Test Library/')
#
# The parameter can be empty, for the currently opened library,
# or you can pass a specific Library's path if you wish.
#
#-------------------- Usage specific code starts here ------------------
import math
from collections import defaultdict
series_info = defaultdict(dict)
fract_ids = []
for id_ in cache.all_book_ids():
series = cache.field_for('series', id_)
if series:
sidx = cache.field_for('series_index', id_)
str_sidx = str(sidx)
components = str_sidx.split('.')
if components[1] == '0':
fract_part = 0
else:
fract_part = len(components[1])
fract_ids.append(id_)
val_part = len(components[0])
series_info[series]['val_part'] = max(series_info[series].get('val_part', 0), val_part)
series_info[series]['fract_part'] = max(series_info[series].get('fract_part', 0), fract_part)
for series,sinfo in series_info.iteritems():
fract_part = sinfo['fract_part']
# if fract_part == 1: # Once fractional parts come into play, always have them at least 2 long.
# fract_part = 2 # Not sure yet if I actually want that.
print "Series name:",series
brief_format_str = '0%d.0f'%(sinfo['val_part'])
print "Format String for books without fraction:",brief_format_str
if fract_part > 0:
full_format_str = '0%d.%df'%(sinfo['val_part'] + fract_part + (1 if fract_part > 0 else 0), fract_part)
print "Format string for books with fraction:",full_format_str
sids = cache.search('series:"=' + series + '"')
dct = {}
for book_id in sids:
if book_id in fract_ids:
dct[book_id] = full_format_str
else:
dct[book_id] = brief_format_str
cache.set_field('#format_str', dct)
(I've left in just a couple of the debug prints because, well, I think they're useful)
Custom column #format_str stores the format str, custom column #series_index_formatted stores the formatted series index, templated as
Code:
program:
finish_formatting(field('series_index'), field("#format_str"),'','')
, and the plugboard then becomes
Code:
{series}{#series_index_formatted:| - | - }{title}
(The added templated column may or may not impact the performance in my usecase -- I'm betting not -- but I think the extra elegance of the system as a whole probably is worth it anyway.)
So, wow, that was definitely one of those cases where I was looking for the issue in all the wrong places. Sorry for trying your patience! And definitely thanks for pointing me in the right direction.