How to check the <fo:page-number> is even or odd using xslt 2.0 Is there any way to use <fo:page-number> inside <xsl:if test="fo:page-number mod 2 = 0">
The XSLT stage generates the XSL-FO that the formatter then makes into pages. So, no, you can't get the current page number when you are generating the XSL-FO.
What do you want to change if it is an even-numbered page?
With XSL-FO, you can set up different page masters for odd and even pages (and more besides). The different page masters can have different margins, and you can set things up so that the formatter will direct different content to headers and footers on even pages than is used on odd pages.
See the 'Page Region and Structure' PDF and FO files in the 'XSL-FO Samples Collection' at https://www.antennahouse.com/xsl-fo-samples#structure
What you ask for cannot be done with a true batch formatter in a single pass. It requires "human" intervention to mark only those places where the break needs to occur and not others.
Also, there is no guarantee that one XSL FO formatter might yield different results than another. Because of the complexities in the way some formatters handle "line tightness" (which is very small squeezing of spaces and characters together to fit text within a line) as well as some supporting kerning and others not as well as many other factors, it is not possible to "pre-predict" whether some paragraph will appear/start on a page or not.
Formatting text in true typography is not merely word-space-word-space ... there are many other factors involved that could change the number of lines in a paragraph between one formatter and another which can easily ripple to a known paragraph existing on an even page in one formatter, yet an odd page in a different formatter.
Then you also need other rules like what if your paragraph using your formatter of choice is the first one on your page in which you wish to break. Do you want a blank page? Maybe, who knows?
The only way to accomplish your task is through a multipass approach that could be implemented such that it is generic to any formatter. You would need to format a whole document (or if you are chunking that document with page masters) at least a chunk that starts and ends in page boundaries. Format it, test your condition on the first paragraph. If it passes (meaning if a break is needed), go back to original content (or modify the XSL FO) and mark some attribute that would result in break-before="page" on that structure. Then repeat the process until you reach the end of the document. Some formatters can provide you the area tree and markers you can put in that tree so that you could do this programmatically and not by eye).
If your document is long and in one page-sequence (say like 3000 pages when formatted) and your break condition is frequent, you may have to repeat the process 700+ times.
As stated, some formatters through their API may allow you to control this programmatically. You can examine the area tree, look for your marker and keep count of pages. You may even be able to start formatting again at the break condition and not start over, but you need to program such things.
Suppose I have a logger function, and I called it all over my code. My logs usually show the probability of the existence of a problem or a bug. More actions and investigations needed to confirm the problem or bug. For example, maintainer or tester should grab the input, open it in an editor, and if a specific string is inside the input, The problem or bug is confirmed.
I want to document the procedure of confirming the bug in a comment above of the log function in code. I also want to extract all of these kinds of comments and create, say an HTML table from them. So I can give that table to the tester or maintainer to find correct bugs for me.
I show it in a simple code. I know it's silly, but does the job:
std::ifstream t("file.txt");
std::string input;
// Read the whole file into input string
// DIAGNOSTICS COMMENT
// NOHELLO_BUG
// Diagnostics steps: 1.Open input file file.txt 2. Search hello inside the file, if hello exists inside the file, there should be a bug, send file.txt to the developer!
if (input.find("hello") == std::string::npos)
{
logger::log("hello not found inside input file!");
return false;
}
Is there any command in Doxygen for this purpose, although Any other solution is welcome too. The most obvious way is to write that table by myself, But maintaining that table will be a disaster too.
Doxygen contains a.o. the commands \todo, \bug
From the documentation:
https://www.doxygen.nl/manual/commands.html#cmdtodo
\todo { paragraph describing what is to be done }
Starts a paragraph where a TODO item is described. The description will also add an item to a separate TODO list. The two instances of the description will be cross-referenced. Each item in the TODO list will be preceded by a header that indicates the origin of the item.
\bug https://www.doxygen.nl/manual/commands.html#cmdbug:
\bug { bug description }
Starts a paragraph where one or more bugs may be reported. The paragraph will be indented. The text of the paragraph has no special internal structure. All visual enhancement commands may be used inside the paragraph. Multiple adjacent \bug commands will be joined into a single paragraph. Each bug description will start on a new line. Alternatively, one \bug command may mention several bugs.
Furthermore doxygen contains the command \xreflist with which you can define your own lists.
Small excerpt from the documentation (https://www.doxygen.nl/manual/commands.html#cmdxrefitem):
\xrefitem "(heading)" "(list title)" { text }
This command is a generalization of commands such as \todo and \bug. It can be used to create user-defined text sections which are automatically cross-referenced between the place of occurrence and a related page, which will be generated. On the related page all sections of the same type will be collected.
The first argument is an identifier uniquely representing the type of the section. The second argument is a quoted string representing the heading of the section under which text passed as the fourth argument is put. The third argument (list title) is used as the title for the related page containing all items with the same key. The keys "todo", "test", "bug" and "deprecated" are predefined.
In Doxygen you use reference links: define them separately and then refer to them from within the text.
/**
* This is a documentation. Here I link [std::string] to an external web page.
*
* The next line is the link definition:
*
* [std::string]: http://en.cppreference.com/w/cpp/string/basic_string "std::string documentation"
*/
However it seems that the link definition is seen only within the documentation block. It is not seen even on other documentation blocks on the same page.
I want to define some links once, and then use them everywhere (on different pages).
Is that possible?
Edit (follow-up question)
In order to achieve your aim I think your best bet is to make use of the ALIAS facility.
I have managed to set it up with alias like this:
ALIASES += std_string="std::string "
ALIASES += std_vector="std::vector "
And using it:
#std_string
#std_vector
Basically I have one alias for each link.
Can it be achieved with one alias with parameters? The use would be:
#std_ref std::string
#std_ref std::vector
The problem is that some sort of map is needed between the name (the parameter) and the link:
std::string -> http://en.cppreference.com/w/cpp/string/basic_string
std::vector -> http://en.cppreference.com/w/cpp/container/vector
I know it can be done if one parameter would be the different part of the link, like :
#std_ref std::string string/basic_string
#std_ref std::vector container/vector
But this is ugly, error prone and would require to check each time what the link should be.
It's worth noting that what you are currently using is the notation that comes only with Doxygen's support for Markdown - it's not the doxygen method for external links. The original Doxygen method is to insert an HTML link inline...
link text
... but that makes no difference to your original problem.
In order to achieve your aim I think your best bet is to make use of the ALIAS facility. The relevant manual page is here. Using them, you should be able to define an alias like std-string and have it insert the HTML link everywhere you use the alias.
ALIASES are set up in the doxyfile config file (in this section of the manual)
You could set up aliases manually for every C++ keyword, that you want to link to, but the better way to do this is to use the doxygen TAGFILES feature.
A tag file is basically a compact representation of the entities found in the external sources. Doxygen can both generate and read tag files.
To generate a tag file for your project, simply put the name of the tag file after the GENERATE_TAGFILE option in the configuration file.
To combine the output of one or more external projects with your own project you should specify the name of the tag files after the TAGFILES option in the configuration file.
Doxygen has a whole page dedicated to explaining how to link to external documentation
And cppreference.com has already setup a tag file for you with some basic instructions.
For the impatient:
Download File:cppreference-doxygen-web.tag.xml for linking directly to cppreference.com website.
Add this line to your Doxyfile:
TAGFILES += "location/of/cppreference-doxygen-web.tag.xml=http://en.cppreference.com/w/"
I'm running into a problem with the doxygen documentation.
In the "Files" section, is it possible to remove the functions list at the top of the page with a flag in the doxyfile ?
If not, is there a way to insert a section (with a doxygen command in my source code in cpp) before this "Functions" list.
Set EXTRACT_ALL to NO.
Set HIDE_UNDOC_MEMBERS to YES.
Don't document the members you want hidden.
You can also use EXCLUDE_SYMBOLS to exclude some documented items:
The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names (namespaces, classes, functions, etc.) that should be excluded from the output. The symbol name can be a fully qualified name, a word, or if the wildcard * is used, a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
Please refer to this documentation page:
http://www.doxygen.nl/manual/customize.html
Chapter "Changing the layout of pages" explains how to include/exclude and more generally organize your generated documentation. I had a problem like yours, if I correctly understand, and followed the steps indicated in the above mentioned documentation:
1) By using command "doxygen -l", I obtained a standard "DoxygenLayout.xml" layout file
2) Prepared a custom layout file, by modifying the standard one, by commenting out the whole <memberdecl>...</memberdecl> XML section
3) In my Doxyfile, specified the custom layout file as a value for option "LAYOUT_FILE"
Careful with paths, so that doxygen knows where to find the Doxyfile and the custom layout file.
Closed. This question is opinion-based. It is not currently accepting answers.
Closed 7 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
My team is starting to document our C code using doxygen, paying particular attention to our public API headers. There appears to be a lot of flexibility and different special commands in doxygen, which is great, but it's not clear what's a good thing and what's a bad thing without trial and error.
What are your favourite ways to mark up your code, what are your MUST DOs and DO NOTs?
Please provide your top tips, one per answer to facilitate voting.
I am looking to define our whole approach to API documentation, including providing a template to get the rest of the team started. So far I have something like this:
/**
* #file example_action.h
* #Author Me (me#example.com)
* #date September, 2008
* #brief Brief description of file.
*
* Detailed description of file.
*/
/**
* #name Example API Actions
* #brief Example actions available.
* #ingroup example
*
* This API provides certain actions as an example.
*
* #param [in] repeat Number of times to do nothing.
*
* #retval TRUE Successfully did nothing.
* #retval FALSE Oops, did something.
*
* Example Usage:
* #code
* example_nada(3); // Do nothing 3 times.
* #endcode
*/
boolean example(int repeat);
You don't need and should not write the name of the file in the #file directive, doxygen reads the name of the file automatically. The problem with writing the name of the file is that when you rename the file you will have to change the #file directive as well.
Providing #author and #date information is also useless most of the time since the source control system does it a lot better than someone editing the files manually.
You also don't have to write #brief if you use the following Doxygen syntax and enable JAVADOC_AUTOBRIEF in doxygen's configuration:
/*! Short Description on the first line
Detailed description...
...
*/
void foo(void) {}
The #name directive for functions is also 100% redundant most of the time and completely useless. It only brings errors when someone modifies the name of the function and not the doxygen #name.
Write a descriptive home page using #mainpage (in a separate header file just for this purpose). Consider, as shown in my example, making it a guide to your main classes/functions and modules.
Another Sample
Whilst I was getting the above-linked main oofile doxygen content back online, here's an example from some current client work using Markdown format. Using Markdown you can refer to a mainpage in markdown (in the Doxygen settings) which is great for the typical readme.md file included in open-source projects.
Lingopal
========
Developer Documentation started when Andy Dent took over support in May 2014.
There are a number of pages in Markdown format which explain key aspects:
- #ref doc/LingopalBuilding.md
- #ref doc/LingopalSigning.md
- #ref doc/LingopalDatabases.md
- #ref doc/LingopalExternals.md
See the Related Pages list for more.
-------------
_Note_
These pages, whilst readable by themselves, are designed to be run through the [Doxygen](http://www.doxygen.com) code documentation engine which builds an entire local cross-referenced set of docs. It uses a minor [extension of Markdown formatting.](http://www.stack.nl/~dimitri/doxygen/manual/markdown.html)
The settings to generate the documentation are `Lingopal.doxy` and `LingopalDocOnly.doxy`. The latter is used for quick re-generation of just these additional pages.
Use Groups to organise your code into modules.
Remember that you can put almost everything into multiple groups so they can be used to provide semantic tagging like the tags in Stack Overflow. For example, you might tag things as specific to a given platform.
You can also use groups to match a folder hierarchy within an IDE, as shown in my RB2Doxy sample output.
Groups work well when nested - I have a large example for the OOFILE source.
Some commands i use in my code :
\todo { paragraph describing what is to be done } Useful to keep track of todos, a page will be created in final documentation containing your todo list.
\c <word> Displays the argument using a typewriter font. Use this to refer to a word of code. I would use it before "TRUE" and "FALSE" in your example.
\a , \warning , \see : see http://www.stack.nl/~dimitri/doxygen/commands.html#cmdc for description
A good "best practice" (though not always achievable) is to provide short, working examples for every API, and pull them into the help using \includelineno (or \include for no line numbers). These can be unit tests, if they're written so users can understand them (ie, not hooked into a larger test harness). As a nice side effect, changes to the API will break the samples, so they have to be kept up to date.
You can describe an API in words, but there's nothing like seeing the actual code to understand how to use it.
As I find myself editing code on higher-resolution screens I've moved from using the backslash to the # prefix on Doxygen commands. Not so noisy backslash has found itself now too damned hard to make out the Doxygen commands.
If you are sure your team will follow such a heavyweight template, fine, use it as shown.
Otherwise, it looks like JavaDoc. One of the nice things about Doxygen is how good a job it does without having to use use such strong markup. You don't need to use #name and with the JAVADOC_AUTOBRIEF setting you can skip #brief - just make sure the first line of the comment is a reasonable brief description.
I prefer descriptive names over enforcing documentation and encouraging people to add comments only when they add significant value. That way, the valuable comments aren't drowned out by all the noise.
If you have bugs located in the code or you find bugs you can also tag in the code like this:
/** #bug The text explaining the bug */
When you then run doxygen you get a seperate Bug List alongside lists like Todo List
If you have a really, really big project -- big enough that Doxygen runs take over an hour -- you can cut it up into multiple modules that Doxygen later links together using tag files.
For example, if you have a big MSVC solution with twenty projects in it, you can make directory be its own Doxygen run, and then use tag-files to glue together the output the same way a linker glues together .libs to make an executable.
You can even take the linking metaphor more literally and make each Doxy config file correspond to a .vcproj file, so that each project (eg .lib or .dll) gets its own Doxy output.
I use a subversion post-commit hook to pull out the directories that have changed, write them to a file and then every night I automatically re-generate the doxygen html on our webserver so we always have up-to-date docco.
Every project I want documented has a little project.doxy file that contains the per-project settings and an include to the main doxygen settings - eg:
PROJECT_NAME = "AlertServer"
PROJECT_NUMBER = 8.1.2
INPUT = "C:/Dev/src/8.1.2/Common/AlertServer"
HTML_OUTPUT = "AlertServer"
#INCLUDE = "c:\dev\CommonConfig.doxy"
For Windows SVN server, use the hook:
#echo off
for /F "eol=¬ delims=¬" %%A in ('svnlook dirs-changed %1 -r %2') do echo %%A >> c:\svn_exports\export.txt
and then run this nightly:
#echo off
rem ---------------
rem remove duplicates.
type nul> %TEMP%.\TEMP.txt
for /F "eol=¬ delims=¬" %%a in (c:\svn_exports\export.txt) do (
findstr /L /C:"%%a" < %TEMP%.\TEMP.txt > nul
if errorlevel=1 echo %%a>> %TEMP%.\TEMP.txt
)
copy /y %TEMP%.\TEMP.txt export_uniq.cmd >nul
if exist %TEMP%.\TEMP.txt del %TEMP%.\TEMP.txt
rem ---------------
rem fetch all the recently changed directories into the svn_exports directory
for /F "eol=¬ delims=¬" %%A in (c:\svn_exports\export_uniq.cmd) do (
svn export "file:///d:/repos/MyRepo/%%A" "c:/svn_exports/%%A" --force
)
rem ---------------
rem search through all dirs for any config files, if found run doxygen
for /R c:\svn_exports %%i in (*.doxy) do c:\tools\doxygen\bin\doxygen.exe "%i"
rem ---------------
rem now remove the directories to be generated.
del /F c:\svn_exports
this removes duplicate entries, finds all projects that have a .doxy project file, and runs doxygen on them. Voila: fully documented, always up-to-date code on a webserver.
For complex projects it may be useful to have a separate file for module management, which controls the groups and subgroups. The whole hierarchy can be in one place and then each file can simply stuff to the child groups. e.g.:
/**
* #defgroup example Top Level Example Group
* #brief The Example module.
*
* #{
*/
/**
* #defgroup example_child1 First Child of Example
* #brief 1st of 2 example children.
*/
/**
* #defgroup example_child2 Second Child of Example
* #brief 2nd of 2 example children.
*/
// #}
Simply including the definition of a group within the { } of another group makes it a child of that group. Then in the code and header files functions can just be tagged as part of whatever group they are in and it all just works in the finished documentation. It makes refactoring the documentation to match the refactor code much easier.
Uses lots and lots of links. This can be done using see also links (\see or #see if you prefer), and making sure that you use any references to other class names in documentation by their correct class name. For example if you refer to class FUZZYObject as an "object", then write immediately after it the name of the class (e.g. "frazzle the objects (FUZZYObject)").
Automatically build and publish your documentation. As part of automatically building the documentation, pay attention to the warnings, its very easy to write badly structure doxygen comments.
Use \example as much as you can. It auto-links API elements to example code.
Don't bother with #author or #date (#date was mentioned in another post). These are both handled by a revision control system.
Always include a description with your classes. Try to say how a class is used, or why it is used, not just what it is (which usually just reflects the name anyway).
Group your member functions and fields if it makes sense to do so with \defgroup. This is very helpful, even if you don't say much.
If you are worried that some team members will avoid documenting or you just want a working minimal sets of documentation, you can enable these in your doxygen configuration.
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
As part of your doxygen build process save the warnings to a file and try to get and keep the warning count as low as possible (0 if that is reasonable). If you do this, every public and protected class member will need at least an #brief, #param for each function argument and an #return. This is good enough to describe most APIs and not too much to encumber other living codebases.
You should, of course, encourage people to document as much as they feel is required on a case by case basis, as long as they meet the minimum project standards. Don't set the minimum too high though, then you may not get useful documentation in the end.
For example, in our project, everything another coder is likely to touch should be documented. Enabling the warnings let see how close that goal we are. We also try to use #internal to describe what/why we do what we do with some of our private members.
If you find that the configuration directive INLINE_SOURCES puts too much code in the documentation, you can manually quote specific portions of the code using the \snippet command.
/**
* Requirment XYZ is implemented by the following code.
*
* \snippet file.c CODE_LABEL
*/
int D()
{
//[CODE_LABEL]
if( A )
{
B= C();
}
//[CODE_LABEL]
}
note: snippet gets its files from the EXAMPLE_PATH, not where the source path is. You will have to put the same list of files and paths from INPUT directive on the EXAMPLE_PATH directive.
For larger projects taking 5+min to generate, I found it useful to quicly be able to generate doxygen for a single file and view it in a web browser.
While references to anything outside the file won't resolve, it can still useful to see the basic formatting is ok.
This script takes a single file and the projects doxy config and runs doxygen, I've set this up to run from my IDE.
#!/usr/bin/env python3
"""
This script takes 2-3 args: [--browse] <Doxyfile> <sourcefile>
--browse will open the resulting docs in a web browser.
"""
import sys
import os
import subprocess
import tempfile
doxyfile, sourcefile = sys.argv[-2:]
tempfile = tempfile.NamedTemporaryFile(mode='w+b')
doxyfile_tmp = tempfile.name
tempfile.write(open(doxyfile, "r+b").read())
tempfile.write(b'\n\n')
tempfile.write(b'INPUT=' + os.fsencode(sourcefile) + b'\n')
tempfile.flush()
subprocess.call(("doxygen", doxyfile_tmp))
del tempfile
# Maybe handy, but also annoying as default.
if "--browse" in sys.argv:
import webbrowser
webbrowser.open("html/files.html")