Welcome, Guest. Please Login or Register
Tinderbox
  News:
Visit the Tinderbox Cookbook for tons of examples.
  HomeHelpSearchLoginRegister  
 
Pages: 1 2 
Send Topic Print
Export BibTex using $KeyAttibutes (Read 12391 times)
Sumner Gerard
Full Member
*
Offline



Posts: 347

Re: Export BibTex using $KeyAttibutes
Reply #15 - Sep 19th, 2011, 6:02pm
 
Amazing wizardry with format(), a do() and .replace()!

I've attached a demo tbx showing a much less elegant and more verbose (but, for me, easier to replicate and in some ways possibly more flexible, e.g. can get a line break where needed) "loop" method, similar to that described here.

Three code notes do the work:

'cLoopInit' sets things up and uses MarkA's nifty method to exclude certain key attributes with replace().

Code:
$MyTempString=;$MyTempList=;$LoopCtr=0;
$MyExportSet=$KeyAttributes.replace("citeinessay|citetype|nickname","");
$LoopSize=$MyExportSet.size;
action($Text("cLoop")); 



'cLoop' uses the .at() operator with the loop counter attribute to cycle through the items in list of key attributes. For each key attribute that has a value in that note (the if(eval()) is testing to make sure it is not empty) a temporary string is populated with the attribute name and attribute value.  Then this temporary string is added to a temporary list.

Code:
if($LoopCtr<$LoopSize) {
$CurrListItem=$MyExportSet.at($LoopCtr);
if(eval('$'+$CurrListItem)){$MyTempString=$CurrListItem+"={"+eval('$'+$CurrListItem)+"}"}else{$MyTempString=;};
$MyTempList=$MyTempList+$MyTempString;
$LoopCtr=$LoopCtr+1;
action($Text("cLoop"));
}
else {
action($Text("cMakeReport"))
} 



'cMakeReport' formats the temporary list with line breaks, adds some stuff before and after that I understand BibTex needs, replaces some values, and places the result in $Text, from where it can be viewed and exported.  The effects can be seen dynamically by opening the 'test-reference' and inserting/changing values for the key attributes. (The text updates immediately if one File/Saves without closing the note.)

Code:
$Text="@"+$citetype+"{"+$nickname+",
";
$Text=$Text+$MyTempList.format(",\n");
$Text=$Text.replace("URL","howpublished");
$Text=$Text+"
}"; 



In practice one would probably want to add a "guard attribute" with conditional or some other mechanism so that the loop doesn't continually run. Here, I've got a stamp that can turn off the rule.

Some complications/questions:

1) Should TB always evaluate 'year' and 'month' as -1 and 6?  (see the eval() in 'cLoop') That's what I got for the values when I had the attribute names as 'year' and 'month' even when no values had been entered for those two attributes in the current note. I got around the problem by renaming the attributes 'byear' and 'bmonth' but then had to add the .replace() to 'cMakeReport' to change the names to what (presumably...I haven't used it) BibTex expects. (Am thinking problem may be because there should be an escaped $ within the second eval() but not sure how to do that).
Edited:
Adding '$'+ within eval() seems to work. Changed attribute names back to $year and $month.
 

2) If had attributes 'byear' and 'bmonth' could these be replaced by 'year' and 'month' in one replace()?  I see aTbRef mentions multiple back-references with .replace() but don't know how that might work in this case.

As always, interested in suggestions/critique.
Back to top
 
« Last Edit: Sep 19th, 2011, 10:59pm by Sumner Gerard »  
  IP Logged
Mark Anderson
YaBB Administrator
*
Offline

User - not staff!

Posts: 4469
Southsea, UK
Re: Export BibTex using $KeyAttibutes
Reply #16 - Sep 20th, 2011, 4:06am
 
without the pre-cghange version, I'm note 100% sure but if you changed code like
  eval($CurrListItem)
to
  eval("$"+$CurrListItem)
it would make sense.

The reason is $CurrListItem holds the string literal name of an attribute ("year") and not a reference ("$year"). If you use the first example above with "year") TB is likely trying to figure what you meant by supplying the year() action operator with no parameters. Incidentally, I realise Sumner is only following Sebastian's original attribute naming. This is another good reason why I try to persuade people to follow TB conventions with attribute naming as it avoids such predictable code ambiguities. If $String's value is "Year" or "YearDate", $String.lowercase() gives "year" or "yeardate" so needing lowercase names in export isn't a reason to use all-lowercase TB attribute names.

I realise Sebastian used $URL in his original TBX but with it unnecessary. Easier would be to make a custom URL-type attribute $howpublished. Of course, given the above, more sensible naming would be $HowPublished.

Not ignoring the other stuff but not time now to explore. I'm going try and merge my demo with Sumner's and use sensible attribute names, but it may take a while and i'm busy just now.
Back to top
 
 

--
Mark Anderson
TB user and Wiki Gardener
aTbRef v5
(TB consulting - email me)
WWW shoantel   IP Logged
Sumner Gerard
Full Member
*
Offline



Posts: 347

Re: Export BibTex using $KeyAttibutes
Reply #17 - Sep 20th, 2011, 11:58am
 
Quote:
eval("$"+$CurrListItem) ... would make sense

Ah, hadn't thought of confusion with year() and month() action operators! Without parameters perhaps they default to -1 and 6.  Can now see need to prefix '$' in the expression.  Ended up using single quotes because double quotes were already used.

Quote:
I'm going try and merge my demo with Sumner's and use sensible attribute names

That would be great!  Finally see a practical application for lowercase().
Back to top
 
 
  IP Logged
Mark Anderson
YaBB Administrator
*
Offline

User - not staff!

Posts: 4469
Southsea, UK
Re: Export BibTex using $KeyAttibutes
Reply #18 - Sep 21st, 2011, 5:44am
 
Some progress at last. First the preps. Attribute names are now:
  • Key attributes: CiteInEssay (Boolean), CiteType (String), NickName (String), Author (String), Editor (String), BookTitle (String), Title (String), Edition (String), Series (String), Pages (String), Month (String), Year (String), HowPublished (URL), Publisher (String), Address (use existing System String attribute: $Address), Note (String).
  • For export process: LoopCtr (Number), LoopSize (Number), MyExportSet (Set), MyExportString (String), MyTempList (List), MyTempString (String).
A prototype (BibTeX-Ref) is used to set up both the key attributes and the export template (export-ref). The prototype also has $HTMLExportExtension changed from '.html' to '.txt' as this is a more likely useful extension of what will be a UTF-8 plain text format export. The names of either of those can be easily changed for your own use/naming conventions.

Using Sumner's model (thanks!) there are still 3 code notes.

cLoopInit:
Code:
$MyTempString=;$MyTempList=;$LoopCtr=0;$MyExportString=;
$MyExportSet=$KeyAttributes.replace("CiteInEssay|CiteType|NickName","");
$LoopSize=$MyExportSet.size;
action($Text("cLoop")); 


cLoop:
Code:
if($LoopCtr<$LoopSize) {
	$CurrListItem=$MyExportSet.at($LoopCtr);
	if(eval('$'+$CurrListItem)){
		$MyTempString=$CurrListItem.lowercase()+"={"+eval('$'+$CurrListItem)+"}"
	} else {
		$MyTempString=;
	};
	$MyTempList=$MyTempList+$MyTempString;
	$LoopCtr=$LoopCtr+1;
	action($Text("cLoop"));
} else {
	action($Text("cMakeReport"))
}  


cMakeReport:
Code:
$MyExportString="@"+$CiteType+"{"+$NickName+",
";
$MyExportString=$MyExportString+$MyTempList.format(",\n");
$MyExportString=$MyExportString+"
}"; 


Meanwhile the export template now calls the export process - initialing the loop and zero-ing out all the variables after use - storing each full exported reference value strikes me as file bloat as it's recreated on next export. Template export-ref:
Code:
^action(action($Text("cLoopInit")))^^value($MyExportString)^
^action($MyExportString=;$MyTempList=;$MyExportSet=;$MyTempString=;$LoopCtr=;$LoopSize=;)^ 



I think the looping has been discussed elsewhere - noting the added use of .lowercase() to lowercase the attribute names. Apart from laying out the if() structures in the loop to show the branching (the extra whitespace has no effect on export) the process is as Sumner's concept.

The main difference is now the export template calls the first action.  Note how to call an action from a template we needs 'double' call ^action(action(...))^. This might seem counter-intuitive but ^action()^ simple runs action code without returning anything (to the template. Of course action() is itself action code, thus the apparent 'doubling' of the word action in the call. The ^value()^ call is not on its own line as otherwise the end of the action line emits a line return causing the export file to have a blank first line. as some importers are very specific this might cause an import failure, so we put the two codes on the same line. The second line simply resets all the export variables now we're done.  Most don't really matter, but $MyExportString could certainly be holding a lot of data, bloating the TBX. Anyway, it seems sensible to clear out the export-only attributes now we're done exporting.

Demo file of above code: BibTeX2.zip
Back to top
 
 

--
Mark Anderson
TB user and Wiki Gardener
aTbRef v5
(TB consulting - email me)
WWW shoantel   IP Logged
Mark Anderson
YaBB Administrator
*
Offline

User - not staff!

Posts: 4469
Southsea, UK
Re: Export BibTex using $KeyAttibutes
Reply #19 - Sep 22nd, 2011, 1:02pm
 
To make a few less moving parts, we can merge the 'make report' code with the loop, like so:

Code:
if($LoopCtr<$LoopSize) {
	$CurrListItem=$MyExportSet.at($LoopCtr);
	if(eval('$'+$CurrListItem)){
		$MyTempString=$CurrListItem.lowercase()+"={"+eval('$'+$CurrListItem)+"}"
	} else {
		$MyTempString=;
	};
	$MyTempList=$MyTempList+$MyTempString;
	$LoopCtr=$LoopCtr+1;
	action($Text("cLoop"));
} else {
	$MyExportString="@"+$CiteType+"{"+$NickName+",
";
	$MyExportString=$MyExportString+$MyTempList.format(",\n");
	$MyExportString=$MyExportString+"
}";
}
$MyExportString=;
$MyTempList=;
$MyExportSet=;
$MyTempString=;
$LoopCtr=;
$LoopSize=;
 


Now we've reset the in-loop and loop control variables at the end. We can't remove the last ^action^ call from the export template, as we can reset $MyExportString before we use it. The template is now:

Code:
^action(action($Text("cLoopInit")))^^value($MyExportString)^
^action($MyExportString=;)^  


Edited:
The last line above, pre-edit, included unnecessary items now in cLoop

The outcome is exactly the same as in the last post, but we've one less code note, which I feel is a little tidier. As ever, there's more than one way...
Back to top
 
« Last Edit: Sep 22nd, 2011, 4:45pm by Mark Anderson »  

--
Mark Anderson
TB user and Wiki Gardener
aTbRef v5
(TB consulting - email me)
WWW shoantel   IP Logged
Sumner Gerard
Full Member
*
Offline



Posts: 347

Re: Export BibTex using $KeyAttibutes
Reply #20 - Sep 22nd, 2011, 4:38pm
 
Very instructive. Thanks!

In the 'export-ref' template it seems you no longer need the second line that clears the variables.  Perhaps a typo, since the template appears unchanged from earlier post?

Very basic question, stemming from lingering export anxiety: what are the main advantages of calling the action code from an export template rather than a rule?  

In this case it seems more "natural", because this is, after all, export to another application. And it avoids cluttering up notes with rules.  

Is there also a performance advantage in that, unlike rules, export templates (presumably) don't run the code automatically each cycle, only when needed in an export context? I noticed when a new HTML View is opened on 'Test Ref" and I make changes to the values in any of the key attributes there, the output in the HTML View window updates immediately after I click on the window, but not before.
Back to top
 
 
  IP Logged
Mark Anderson
YaBB Administrator
*
Offline

User - not staff!

Posts: 4469
Southsea, UK
Re: Export BibTex using $KeyAttibutes
Reply #21 - Sep 22nd, 2011, 4:59pm
 
Oops, edit made above!

Quote:
Very basic question, stemming from lingering export anxiety: what are the main advantages of calling the action code from an export template rather than a rule?  

In this case it seems more "natural", because this is, after all, export to another application. And it avoids cluttering up notes with rules.  


I think you answered the question. In this case, as we're doing export, it makes more sense to only run the code during export (open HTML view does the same). By the same token, there's no point in storing  temporary values used for the export process.  Were the data being used internally, it might be a different deal.  Also consider an agent action vs. per-note rules. Why? An agent can be turned off. Inefficiencies that won't show with a one or two note test may, with thousands of notes, slow up operations; there are no hard-and-fast metrics lest someone lask. Ergo it's best to make code as efficient as possible so scaling doesn't have undue effect. One good rule of thumb is to limit scope; don't apply a rule to 50 notes when only one really needs to use the code (e.g. prototypes). Conditional if() tests can also help block inappropriate running of longer sections of code - i.e. 100s of notes might run the test but only few meet the condition and run the main branch of code. The same concept applies to queries:

Worse:   $Color=="blue" & descendedFrom("Test")

Better:   descendedFrom("Test") & $Color=="blue"

Why is the latter better? The first test finds only those notes descended from a given container and only those notes are tested with the rest of the query. The first example tests $Color for every note. Inefficient!

Quote:
I noticed when a new HTML View is opened on 'Test Ref" and I make changes to the values in any of the key attributes there, the output in the HTML View window updates immediately after I click on the window, but not before.


I think that speed/frequency is a pragmatic choice - the same CPU is providing cycles to run UI updates as doing code, etc.  There's a balance of application of effort. nothing sinister, I believe.
Back to top
 
 

--
Mark Anderson
TB user and Wiki Gardener
aTbRef v5
(TB consulting - email me)
WWW shoantel   IP Logged
Sumner Gerard
Full Member
*
Offline



Posts: 347

Re: Export BibTex using $KeyAttibutes
Reply #22 - Sep 22nd, 2011, 6:12pm
 
Great practical tips on agent use and limiting scope.

Quote:
makes more sense to only run the code during export (open HTML view does the same)

So the export "angsted" question I was trying to articulate is whether opening HTML View and subsequently clicking on that view after an update to an attribute value in the note is basically the same (in terms of triggering action code called by an export template) as actually doing an export. Or, put another way, if I had not opened HTML View and clicked on it, then is it correct to say that the code called by the export template would not run each cycle (as it does when called by a rule as I originally had it above) but instead would run only when triggered by an actual export?  If true, then of course that is a very desirable thing in this context.
Back to top
 
 
  IP Logged
Mark Anderson
YaBB Administrator
*
Offline

User - not staff!

Posts: 4469
Southsea, UK
Re: Export BibTex using $KeyAttibutes
Reply #23 - Sep 23rd, 2011, 4:25am
 
In my revised version, cLoopInit is called from the template.  The template is only evaluated if Export as HTML (full doc export) is called or a note's HTML view is opened. In the latter case this is necessary as it needs to show you the output code - i.e. the processed result of the template. In full export the call will be once per template, in HTML view it may occur repetitively whilst the view is open - changes affecting the output are detected. An exception in this context is that HTML view does not show the full result of $HTMLExportCommand as that command line is run on the output file from export - i.e. run on the code as seen in HTML view. In HTML view if that note is set to use an $HTMLExportCommand and if either the Preview or Export buttons are pushed then the code as seen in the code pane would be post-processed and thus different from the actual exported code.

By comparison, triggering this whole loop process in a Rule means it's firing every update cycle for every note using the Rule.  I think you'll agree that's more activity overall. Clearly, in a small test we won't see much impact but on a big file a Rule is probably a wasteful method if the loop is only needed for export purposes.

For non-export use, you could 'gate' the call to the looping code behind a Boolean as in: if($DoLoop){… That way, cLoopInit only gets called if $DoLoop is true. so the Rule might get run in many places but with little impact as $DoLoop would in most cases be false meaning the loop call code would not run.

Incidentally, if you wanted to use both internal and export method, then a further boolean could control, in the loop code 'else' branch whether $MyExportString is just send to export or whether it is also sent to $Text or some other String attribute for internal use.

There's no single right way - it depends what you're trying to do. The only central tenet is thinking about not running more code than needed more often than needed. The more complex the code the more getting it wrong may affect general performance.

Footnote - FWIW I'd still like to see TB get a List.loop() function that makes this more accessible to the general user who doesn't code and to whom loop counters, etc., mean nothing.

Edited:
Fix typos, clarify first paragraph.
Back to top
 
« Last Edit: Dec 13th, 2011, 4:46am by Mark Anderson »  

--
Mark Anderson
TB user and Wiki Gardener
aTbRef v5
(TB consulting - email me)
WWW shoantel   IP Logged
Sumner Gerard
Full Member
*
Offline



Posts: 347

Re: Export BibTex using $KeyAttibutes
Reply #24 - Sep 23rd, 2011, 12:43pm
 
I now see the performance advantages of triggering the action code from an export template rather than a rule that fires each update cycle.

Hope ^action(action())^ isn't scheduled to be retired as seems to be suggested could happen here.

It seems ^value()^ in export code is roughly equivalent to eval() in action code, while ^action()^ is equivalent to action().  Both are useful. At times one needs a value returned. At times one wants a block of code to run.

Wonder how a loop() function (or whatever it would be called) would look.  Looping through members of a list or set does seem to be a common problem.
Back to top
 
 
  IP Logged
Mark Anderson
YaBB Administrator
*
Offline

User - not staff!

Posts: 4469
Southsea, UK
Re: Export BibTex using $KeyAttibutes
Reply #25 - Sep 23rd, 2011, 4:08pm
 
Deprecation of ^action()^ has actually been removed as the difference in function from ^value()^ has become clearer - for the reasons you describe.  I'd already changed that but the old page was still on the website - I've checked and corrected the page.

How might a loop() look -assuming there is one? I think that's still an open field. I'm sure input is welcome.
Back to top
 
 

--
Mark Anderson
TB user and Wiki Gardener
aTbRef v5
(TB consulting - email me)
WWW shoantel   IP Logged
Pages: 1 2 
Send Topic Print