Bug 604255

Summary: Problem with callouts
Product: [Community] Publican Reporter: Jonathan Robie <jonathan.robie>
Component: publicanAssignee: Jeff Fearn 🐞 <jfearn>
Status: CLOSED ERRATA QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: low    
Version: 1.6CC: gsim, jfearn, mmcallis, publican-list, rlandman+disabled, rlandman
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: publican-2.2-0.fc13 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2010-10-10 23:26:05 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
Example of HTML layout none

Description Jonathan Robie 2010-06-15 17:58:46 UTC
Callouts aren't working properly.

Here is an example that illustrates the problem - the callouts are not displayed in the output.

<example>
  <title>"Hello world!" in C++</title>
  <programlisting lang="c++"><![CDATA[
#include <qpid/messaging/Connection.h>
#include <qpid/messaging/Message.h>
#include <qpid/messaging/Receiver.h>
#include <qpid/messaging/Sender.h>
#include <qpid/messaging/Session.h>

#include <iostream>]]>

using namespace qpid::messaging;

int main(int argc, char** argv) {
    std::string broker = argc > 1 ? argv[1] : "localhost:5672";
    std::string address = argc > 2 ? argv[2] : "amq.topic";
    Connection connection(broker); 
    try {
        connection.open();  <co id="hello-cpp-open" linkends="callout-cpp-open"/>
        Session session = connection.createSession(); <co id="hello-cpp-session" linkends="callout-cpp-session"/>

        Receiver receiver = session.createReceiver(address); <co id="hello-cpp-receiver" linkends="callout-cpp-receiver"/>
        Sender sender = session.createSender(address); <co id="hello-cpp-sender" linkends="callout-cpp-sender"/>

        sender.send(Message("Hello world!"));

        Message message = receiver.fetch(Duration::SECOND * 1); <co id="hello-cpp-fetch" linkends="callout-cpp-fetch"/>
        <![CDATA[std::cout << message.getContent() << std::endl;]]>
        session.acknowledge(); <co id="hello-cpp-acknowledge" linkends="callout-cpp-acknowledge"/>
        
        connection.close(); <co id="hello-cpp-close" linkends="callout-cpp-close"/>
        return 0;
    } catch(const std::exception&amp; error) {
        <![CDATA[std::cerr << error.what() << std::endl;]]>
        connection.close();
        return 1;   
    }
  }</programlisting>

  <calloutlist>
    <callout id="callout-cpp-open" arearefs="hello-cpp-open">
      <para>Establishes the connection with the messaging broker.</para>
    </callout>
    <callout id="callout-cpp-session" arearefs="hello-cpp-session">
      <para>Creates a session object, which maintains the state of all interactions with the messaging broker, and manages senders and receivers.</para>
    </callout>
    <callout id="callout-cpp-receiver" arearefs="hello-cpp-receiver">
      <para>Creates a receiver that reads from the given address.</para>
    </callout>
    <callout id="callout-cpp-sender" arearefs="hello-cpp-sender">
      <para>Creates a sender that sends to the given address.</para>
    </callout>
    <callout id="callout-cpp-fetch" arearefs="hello-cpp-fetch">
      <para>Reads the next message. The duration is optional, if omitted, will wait indefinitely for the next message.</para>
    </callout>
    <callout id="callout-cpp-acknowledge" arearefs="hello-cpp-acknowledge">
      <para>Acknowledges messages that have been read. To guarantee delivery, a message remains on the messaging broker until it is acknowledged by a client. session.acknowledge() acknowledges all unacknowledged messages for the given session&mdash;this allows acknowledgements to be batched, which is  more efficient than acknowledging messages individually.</para>
    </callout>
    <callout id="callout-cpp-close" arearefs="hello-cpp-close">
      <para>Closes the connection, all sessions managed by the connection, and all senders and receivers managed by each session.</para>
    </callout>
  </calloutlist>
</example>

Comment 1 Jeff Fearn 🐞 2010-06-15 23:26:55 UTC
Using current 1.6.x branch (which has fixes to callouts not in 1.6.3):

-   <programlisting lang="c++"><![CDATA[
+   <programlisting language="C++"><![CDATA[

No callout numbers in the program listing.

-   <programlisting language="C++"><![CDATA[
+   <programlisting"><![CDATA[

Callout numbers appear, but no highlighting.

Looks like the highlighting module is eating the COs :(

Workarounds:

1: do not set language, avoids highlighting code
2: use an areaset, avoids inline COs

I'll see if I can beat the highlighting code in to submission.

Comment 2 Jeff Fearn 🐞 2010-06-16 00:34:29 UTC
Due to the way the XSL gets processed the tags inside the program listing are processed before the highlighting callback gets called; the COs have already been converted to the output format, be it HTML or XML:FO.

This means we'd have to try and exclude some part of the input being from highlighted, and the mask of that content would change based on what the output format is. Of course if you were trying to highlight HTML or XML source then there probably isn't a reliable way to differentiate call-out markup Vs any other markup.

If it's possible, it's definitely going to take some time to be able to support the combination of highlighting and inline COs.

Comment 3 Jonathan Robie 2010-06-16 13:31:24 UTC
I don't know exactly how syntax highlighting is implemented. 

Does syntax highlighting ignore characters like these?

DINGBAT NEGATIVE CIRCLED DIGIT ONE
U+2776, character ❶, decimal 10102, hex 0x2776

DINGBAT NEGATIVE CIRCLED DIGIT TWO
U+2777, character ❷, decimal 10103, hex 0x2777

DINGBAT NEGATIVE CIRCLED DIGIT THREE
U+2778, character ❸, decimal 10104, hex 0x2778

Downside: there are only ten of them.
Upside: they might pass through.

Comment 4 Jeff Fearn 🐞 2010-06-16 23:40:46 UTC
We use a CPAN module for the highlighting, I don't think it ignores anything, I haven't found anything to allow specifying things to ignore, so it probably comes down to how the particular language is being parsed.

I think it's safer ATM to say "If you want call-outs and code highlighting, then you have to use an areaspec".

Here is an example of how I'd structure this.

First, I'd move the code out of the XML, having all that XML related stuff buried in your code increases the opportunity of adding typos. It's also annoying to have to take chunks of code and XMLify them.

e.g.

mkdir en-US/extras
gvim en-US/extras/hello.cpp
-- make hello.cpp pure C++ --

Then I'd use an areaspec and xi:include the new cpp file, leaving you with:

<example>
  <title>"Hello world!" in C++</title>
  <programlistingco>
    <areaspec>
      <area id="hello-cpp-open" coords='16'/>
      <area id="hello-cpp-session" coords='17'/>
      <area id="hello-cpp-receiver" coords='19'/>
      <area id="hello-cpp-sender" coords='20'/>
      <area id="hello-cpp-fetch" coords='24'/>
      <area id="hello-cpp-acknowledge" coords='26'/>
      <area id="hello-cpp-close" coords='28'/>
    </areaspec>
<programlisting language="C++"><xi:include parse="text" href="extras/hello.cpp" xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
    <calloutlist>
** SNIP There are no changes to the callout list **
    </calloutlist>
  </programlistingco>
</example>

I've gone for the simple coords usage here, just specifying the line number, the callout code will default to lining all the numbers up. You can uses coords='16 34' if you want to override this behavior and specify the line and the column.

Note how programlisting and the xi:include are on the same line, this means the line numbers you use in coords start from line zero. If you had a newline between them, then you'd have to start the line number count from 1.

YMMV, I find keeping the code in a file and only ever treating it as code greatly simplifies the process and allows me to validate the code as code ... not that I make manly typos!

Comment 5 Jeff Fearn 🐞 2010-06-17 00:16:16 UTC
Created attachment 424618 [details]
Example of HTML layout

Hi, I just thought I'd provide a screen shot of the default output as per my example, built from the latest 1.6 branch.

Comment 6 Jonathan Robie 2010-06-17 12:35:58 UTC
Nice! 

That satisfies my needs. The main disadvantage is that if you add a blank line or something, the callouts can be in the wrong place, but this is plenty good enough for my needs.

Comment 7 Ruediger Landmann 2010-08-05 04:25:50 UTC
(In reply to comment #6)

> That satisfies my needs. The main disadvantage is that if you add a blank line
> or something, the callouts can be in the wrong place, but this is plenty good
> enough for my needs.    

Glad to hear that helps; I'll note the limitation in the User Guide. --Rudi

Comment 8 Ruediger Landmann 2010-08-07 12:50:12 UTC
Expanded the previous FAQ entry on adding code samples into a new section: "3.3. Adding code samples" and discussed recommended callout usage per comment #4.