Register Guidelines E-Books Today's Posts Search

Go Back   MobileRead Forums > E-Book Software > Calibre > Devices

Notices

Reply
 
Thread Tools Search this Thread
Old 02-24-2011, 01:55 PM   #1
Doug-W
Member
Doug-W began at the beginning.
 
Posts: 18
Karma: 10
Join Date: Feb 2011
Device: Nook
Send to device with conditional directories

I'd like to send books to my nook with a semi-dynamic format, if it appears on the goodreads shelf 'to read' it goes to a folder /To Read/Title - Author.file if not, then it goes to /Author_sort/Series/Title - authors.file

The Goodreads section is handled by the wonderful goodreads sync and a custom yes/no field called #gr_2read. I set my send to device filter to be what I think would accomplish this:

Code:
{#gr_2read:test("To Read",{author_sort}/{series})}/{title} - {authors}
However, when I go to send to device, Calibre thinks it's sent, but then if I refresh a search it realizes the file isn't on the device, and indeed it's no where to be found. (I've tested both books that appear with the #gr_2read and without, neither show up.)

Am I misunderstanding how the test function should work or what am I doing wrong?

(EDIT: This was moved from Library Management to Devices, but it's a device independent question as far as I'm aware, I'm just asking how the filter is being applied and how to apply it the way I wish it to be.)

Last edited by Doug-W; 02-24-2011 at 03:36 PM.
Doug-W is offline   Reply With Quote
Old 02-25-2011, 11:51 AM   #2
Doug-W
Member
Doug-W began at the beginning.
 
Posts: 18
Karma: 10
Join Date: Feb 2011
Device: Nook
Quote:
Originally Posted by Doug-W View Post
I'd like to send books to my nook with a semi-dynamic format, if it appears on the goodreads shelf 'to read' it goes to a folder /To Read/Title - Author.file if not, then it goes to /Author_sort/Series/Title - authors.file

The Goodreads section is handled by the wonderful goodreads sync and a custom yes/no field called #gr_2read. I set my send to device filter to be what I think would accomplish this:

Code:
{#gr_2read:test("To Read",{author_sort}/{series})}/{title} - {authors}
However, when I go to send to device, Calibre thinks it's sent, but then if I refresh a search it realizes the file isn't on the device, and indeed it's no where to be found. (I've tested both books that appear with the #gr_2read and without, neither show up.)

Am I misunderstanding how the test function should work or what am I doing wrong?

(EDIT: This was moved from Library Management to Devices, but it's a device independent question as far as I'm aware, I'm just asking how the filter is being applied and how to apply it the way I wish it to be.)
Well I think I figured it out, but can't test it because of http://bugs.calibre-ebook.com/ticket/9161

However my plan is to create two composite fields:

NookDir:{author_Sort}/{series}
ToRead: To Read

And then use the following send to device template:
{#gr_2read:lookup(.,{#ToRead},{#NookDir})}/{title} - {authors}

I didn't notice originally that test is only on raw strings and can't have templates.
Doug-W is offline   Reply With Quote
Advert
Old 02-25-2011, 01:46 PM   #3
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 12,043
Karma: 7548549
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
You should look at "template program mode" in http://calibre-ebook.com/user_manual/template_lang.html. That mode allows you to write more arbitrary programs. For example, your original program could be written as
Code:
{#gr_2read:'test($,"To Read",strcat(field("author_sort"),"/",field("series")))'}/{title} - {authors}
or
Code:
{#gr_2read:'test($,"To Read",template("[[author_sort]]/[[series]]"))'}/{title} - {authors}
Use "general program mode" for even more flexibility.
Code:
program:
  strcat(
    test(field('#gr_2read'), "To Read", template("{author_sort}/{series}")),
    template('/{title} - {authors}')
  )
chaley is offline   Reply With Quote
Old 02-26-2011, 11:16 AM   #4
Doug-W
Member
Doug-W began at the beginning.
 
Posts: 18
Karma: 10
Join Date: Feb 2011
Device: Nook
Thank you, that helped a lot.

I had gone over that page you linked a few dozen times while putting this together, the section on save/send templates is what gave me the idea to construct columns.

One problem though is that it doesn't help when the docs are incorrect For example the largest problem I had was that the docs say:

# test(text if not empty, text if empty) – return text if not empty if the field is not empty, otherwise return text if empty.

Not test(expression_to_test, text if not empty, text if empty) which is how it is apparently used. I thought it took the expression to the left of the test, but now that I understand a bit better I see how the left expression fits in particularly with 'program'

Final question just to be sure, does test take a regex of which a field value just happens to be a static test fed to the regex engine? If so that's kind of neat, I've been using regular expressions for 20 years, and never thought to use '.' for contains data, and '$' for always true.
Doug-W is offline   Reply With Quote
Old 02-26-2011, 11:42 AM   #5
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 12,043
Karma: 7548549
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
Quote:
Originally Posted by Doug-W View Post
One problem though is that it doesn't help when the docs are incorrect For example the largest problem I had was that the docs say:

# test(text if not empty, text if empty) – return text if not empty if the field is not empty, otherwise return text if empty.

Not test(expression_to_test, text if not empty, text if empty) which is how it is apparently used. I thought it took the expression to the left of the test, but now that I understand a bit better I see how the left expression fits in particularly with 'program'
The documentation is correct for the section it is in, single function mode. In that mode, the 'value' is always the field named in the beginning of the template and is never supplied as an argument, no argument is quoted, and spaces are significant. In template program mode or general program mode, the 'value' (first) argument must be provided and all constant arguments must be quoted. In template program mode, the variable '$' is assigned the value of the field used in the template. For example, for {series:'test($, 'A', 'B')'} the $ will be assigned the value contained in the field 'series'.
Quote:
Final question just to be sure, does test take a regex of which a field value just happens to be a static test fed to the regex engine? If so that's kind of neat, I've been using regular expressions for 20 years, and never thought to use '.' for contains data, and '$' for always true.
I don't understand the question.

First, let's assume that we are using general program mode so we don't need to worry about which quote to use.

The 'test' function checks if value is or is not empty. There is no regexp involved. Examples:
Code:
test('', 'A', 'B') will return 'B'
test('something', 'A', 'B') will return 'A'
For completeness: in single-function mode, the template
Code:
{series:test(A,B)}
will return 'A' if the series field is not empty. It is exactly equivalent to the template program mode expression
Code:
{series:'test($, "A", "B")'}
If you want to test using a regexp then the switch function is for you. Examples:
Code:
switch('ABC', '.', 'A', 'B') will return 'A'
switch('ABC', '^$', 'A', 'B') will return 'B'
switch('ABC', 'AB', 'A', 'B') will return 'A'
switch('ABC', '^.*$', 'A', 'B') will return 'A'
chaley is offline   Reply With Quote
Advert
Old 02-26-2011, 01:41 PM   #6
Doug-W
Member
Doug-W began at the beginning.
 
Posts: 18
Karma: 10
Join Date: Feb 2011
Device: Nook
Quote:
Originally Posted by chaley View Post
The documentation is correct for the section it is in, single function mode. In that mode, the 'value' is always the field named in the beginning of the template and is never supplied as an argument, no argument is quoted, and spaces are significant. In template program mode or general program mode, the 'value' (first) argument must be provided and all constant arguments must be quoted. In template program mode, the variable '$' is assigned the value of the field used in the template. For example, for {series:'test($, 'A', 'B')'} the $ will be assigned the value contained in the field 'series'.
But that's the only section that describes test. There's no description on that page of test where it takes 3 values. Indeed nothing in template programming mode section which introduces the $ concept indicates which of the functions introduced in single function mode would now take an additional parameter of the field the expression is to operate on. Would I be correct in assuming that every function introduced in the previous section will take a new 1st parameter which can be '$'?


My confusion was thinking that $ wasn't a default variable but was rather the regex expression for end of line, which would always be true.

Combined with this example:
Quote:
# Set the save template to {series:lookup(.,AA,BB)}. This template chooses composite field AA if series is not empty, and composite field BB if series is empty. We therefore have two completely different save paths, depending on whether or not series is empty.
Which does use a regex for the first parameter, I was just marveling at a different way of expressing a concept of 'always match' vs 'always match if not empty' is all.
Doug-W is offline   Reply With Quote
Old 02-26-2011, 02:36 PM   #7
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 12,043
Karma: 7548549
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
Quote:
Originally Posted by Doug-W View Post
But that's the only section that describes test. There's no description on that page of test where it takes 3 values. Indeed nothing in template programming mode section which introduces the $ concept indicates which of the functions introduced in single function mode would now take an additional parameter of the field the expression is to operate on.
From the documentation for Template Program Mode:
All the functions listed under single-function mode can be used in program mode, noting that unlike the functions described below you must supply a first parameter providing the value the function is to act upon.

The following functions are available in addition to those described in single-function mode. Remember from the example above that the single-function mode functions require an additional first parameter specifying the field to operate on. With the exception of the id parameter of assign, all parameters can be statements (sequences of expressions):
Quote:
Would I be correct in assuming that every function introduced in the previous section will take a new 1st parameter which can be '$'?
Yes
chaley is offline   Reply With Quote
Old 03-06-2011, 11:12 AM   #8
Doug-W
Member
Doug-W began at the beginning.
 
Posts: 18
Karma: 10
Join Date: Feb 2011
Device: Nook
Sorry to bump a slightly older post, I appreciate all the help you'd given (and welcome anyone else to jump in,) but I just saw a problem with the templates specified in here, as I mentioned, #gr_2read is a yes/no custom field, and 'test' is returning True if the field has a value, not if the field has a value and the value is True. So, any book that I've synced to goodreads at all is showing up in To Read, even if it's marked as already read (Custom field #gr_read true, custom field #gr_2read false.) Is there an easy way to test for that?
Doug-W is offline   Reply With Quote
Old 03-06-2011, 11:35 AM   #9
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 12,043
Karma: 7548549
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
Try:
Code:
{#gr_2read:'switch($, "Yes", "To Read", template("[[author_sort]]/[[series]]"))'}/{title} - {authors}
if the CC #gr_2read contains the word "Yes", the constant string "To Read" is returned. If the CC contains anything else (including nothing), the evaluation of the template is returned.

Note that the regexps used by switch are case sensitive, and that the string values of a bool column are Yes, No, and empty. IIRC, Yes and No are translatable, so if you are not running in English, check to see what the text says.

Starting in 0.7.48 (or maybe 47) you can avoid translation by using raw_field, with will return 'True', 'False', and 'None'.
Code:
program:
	strcat(
		switch(raw_field('#gr_2read'), 'True', 'To Read', template('[[author_sort]]/[[series]]')), 
		template('/{title} - {authors}')
	)
chaley is offline   Reply With Quote
Reply


Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Can't Send to device Neelly Devices 3 01-20-2011 09:48 AM
Problem with 'Send to Device' Rolando Calibre 9 10-28-2010 02:14 PM
0.6.20 Send to device - kindle lisa.m Calibre 2 11-05-2009 12:26 PM
Send to device button p3aul Calibre 12 05-23-2009 03:34 AM
LibPRS500 Send To Device pilotbob Calibre 1 04-06-2008 02:53 PM


All times are GMT -4. The time now is 09:53 PM.


MobileRead.com is a privately owned, operated and funded community.