I'm finally giving up the angle bracket tax imposed on me by Microsoft's XML documentation format (and what's the point, since the MSVC environment still doesn't do anything fancy with it for C++ projects) and switching my current project to using Doxygen with a Javadoc style syntax.
It is fantastic. The inline documentation is much easier to read and type, and the generated output is so much more useful and versatile. In particular, I have the MULTILINE_CPP_IS_BRIEF option turned on, which allows me to write as long of a "brief" description as I want, and then break up my "details" documentation into paragraphs using blank lines. In other words:
/// Changes the active viewing area of the currently selected region.
///
/// The modification is merely enqueued. This function has no effect until the
/// FlushRegion() function is called.
///
/// Newly-exposed regions will not be repainted automatically. The user must also
/// call the UpdateRegion() function on these regions to cause their contents to
/// be redrawn.
///
/// #param dx The amount, in pixels, to shift the visible region horizontally.
/// #param dy The amount, in pixels, to shift the visible region vertically.
///
/// #remarks
/// Note that this function is reentrant, but not thread-safe!
void ScrollRegion(int dx, int dy);
This gives me exactly the output I desire, while keeping down the number of noisy meta-commands like #brief and \details that I have to use.
The problem comes when I try to include a second paragraph in my "remarks" section, just like I did (implicitly) for the "details" section. For example:
/// Changes the active viewing area of the currently selected region.
///
/// The modification is merely enqueued. This function has no effect until the
/// FlushRegion() function is called.
///
/// Newly-exposed regions will not be repainted automatically. The user must also
/// call the UpdateRegion() function on these regions to cause their contents to
/// be redrawn.
///
/// #param dx The amount, in pixels, to shift the visible region horizontally.
/// #param dy The amount, in pixels, to shift the visible region vertically.
///
/// #remarks
/// Note that this function is reentrant, but not thread-safe!
///
/// If thread safety is required, the user must handle locking and unlocking
/// the region manually.
void ScrollRegion(int dx, int dy);
The generated output does not interpret the second paragraph in the #remarks section as part of the remarks. I can tell because it is not indented to the same level in the HTML output, and it is not located under the <simplesect kind="remark"> tag in the XML output.
I tried adding a #par command to the beginning of the second paragraph, but that didn't do what I wanted, either. The new paragraph is still not a child of the "remarks" section. In the XML output, it is getting placed inside of a new <simplesect kind="para"> tag that is a sibling of the original <simplesect kind="remark"> tag.
While researching this, I saw that someone else had duplicated the #remarks command:
/// Changes the active viewing area of the currently selected region.
///
/// The modification is merely enqueued. This function has no effect until the
/// FlushRegion() function is called.
///
/// Newly-exposed regions will not be repainted automatically. The user must also
/// call the UpdateRegion() function on these regions to cause their contents to
/// be redrawn.
///
/// #param dx The amount, in pixels, to shift the visible region horizontally.
/// #param dy The amount, in pixels, to shift the visible region vertically.
///
/// #remarks
/// Note that this function is reentrant, but not thread-safe!
/// #remarks
/// If thread safety is required, the user must handle locking and unlocking
/// the region manually.
void ScrollRegion(int dx, int dy);
That does produce the output that I desire. Both paragraphs are nested in <para> tags under the <simplesect kind="remark"> tag in the XML output, and the visual relationship is correct in the HTML output. But that's ugly and looks like a mistake to me.
Is there a standard way to do this that I'm missing? Surely I'm not the first person to want multiple paragraphs in the "remarks" section of my documentation... And this isn't limited to #remarks; the same thing happens with #internal, for example.
I have the latest version of Doxygen installed (1.8.2), but I very much doubt that this is version-specific.
Your final example code, that is
/// #remarks
/// Note that this function is reentrant, but not thread-safe!
/// #remarks
/// If thread safety is required, the user must handle locking and unlocking
/// the region manually.
is exactly the expected use of \remarks for multi-paragraph comment blocks. From the doxygen manual (emphasis mine):
\remark { remark text }
Starts a paragraph where one or more remarks may be entered. 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 \remark commands will be joined into a single paragraph. Each remark will start on a new line. Alternatively, one \remark command may mention several remarks. The \remark command ends when a blank line or some other sectioning command is encountered.
So \remark (and \remarks, which is just the same as \remark) ends at the end of a paragraph, but adjacent \remarks will be stitched together to form one \remark block.
You are right to say that this behaviour is not limited to \remarks and \remark. The same applies to any command that takes a paragraph of text as an argument, see, for example, \bug, \todo, \warning etc.
One solution that seems to work that I haven't seen mentioned here, is to end your lines with \n. This will keep everything grouped together, while putting in the white space you may want to see.
If you want a blank line, make sure the line above has \n, and you have a blank line with \n on it.
In your example, you would want:
/// #remarks
/// Note that this function is reentrant, but not thread-safe!\n
/// \n
/// If thread safety is required, the user must handle locking and unlocking
/// the region manually.
And that should make it appear as you want it to appear.
If you don't like having multiple #remarks lines in your source for your multi-paragraph remarks, I think you can use #parblock & #endparblock to include multiple paragraphs for a single #remark.
The solutions can be generalized (doxygen 1.8.9.1). I used:
/// \par Title
/// text of paragraph 1\n
///
/// text of paragraph 2\n
///
/// ~~~
/// Some code / sketch
/// ~~~
kjkAe4Wbasj6
The three paragraphs are indented and the header Title is printed in bold letters above them. Of course, \par Title can be replaced with \remark. The magic phrase is the \n at the end of the paragraphs and blank lines can be inserted optionally. No \n is required in the blank lines. Unfortunately I have not found a way to append another indented text paragraph following the code section.
Related
I have a string of text that dynamically resizes. At its core its basically a Text widget in a SizedBox in a Column.
When it resizes, the words wrap to the next as you typically expect...it breaks to the next line by using the 'SPACES' between words (as opposed to breaking up words character by character).
However, an email address can be a very long string without spaces. When it no longer fits within the bounds of the box it begins to resize itself by breaking on individual characters and moving into the next line.
It's a minor issue, but not visually appealing.
How might one create breakpoints within the String to resize itself by wrapping to the next line based on custom characters? For example, in an email address I'd prefer it break on the '#' and/or '.' before resorting to breaking up the String on individual characters.
I want to describe a half-opened period [start, end) in a comment where both, start and end refer to a parameter of a method:
/// Gets all items within period [[start],[end])
Which is displayed by intelij like this:
Using \ as escape character has the same problem:
What is the escape character in dart comments? The official documentation seems not to state how to escape the [.
I don't know the escape character you're talking about, but you can add an extra pair of brackets after the single bracket you want to show:
/// Gets all items within period [[][start],[end])
It will look like this:
and when you hover your mouse over the method:
Normally square brackets denote identifiers that dartdoc should automatically generate links for. If you want literal square brackets in the generated documentation, you can escape them with a backslash:
/// Gets all items within period \[[start],[end])
For example, the following comment:
/// A fraction in the range \[0, 1\] that represents what proportion of the
/// widget is visible (assuming rectangular bounding boxes).
Generates:
https://pub.dev/documentation/visibility_detector/latest/visibility_detector/VisibilityInfo/visibleFraction.html
I also need to comment brackets as part of a range.
I ended up escaping the whole line with 3 backticks (```)
The disadvantage is I cannot refer to any parameters/methods in that (code) comment, but on the bright side the comment is still very readable in the code.
If you need to refer the parameters, an extra line might be added to do this
E.g.:
/// ```
/// Gets all items within period [start,end]
/// ```
///
/// The referred values are [start], [end]
The TextAffinity enum in Flutter has the following documentation description:
A way to disambiguate a TextPosition when its offset could match two
different locations in the rendered string.
For example, at an offset where the rendered text wraps, there are two
visual positions that the offset could represent: one prior to the
line break (at the end of the first line) and one after the line break
(at the start of the second line). A text affinity disambiguates
between these two cases.
This affects only line breaks caused by wrapping, not explicit newline
characters. For newline characters, the position is fully specified by
the offset alone, and there is no ambiguity.
TextAffinity also affects bidirectional text at the interface between
LTR and RTL text. Consider the following string, where the lowercase
letters will be displayed as LTR and the uppercase letters RTL:
"helloHELLO". When rendered, the string would appear visually as
"helloOLLEH". An offset of 5 would be ambiguous without a
corresponding TextAffinity. Looking at the string in code, the offset
represents the position just after the "o" and just before the "H".
When rendered, this offset could be either in the middle of the string
to the right of the "o" or at the end of the string to the right of
the "H".
This kind of makes sense but it's still a little confusing. For example "helloHELLO" isn't actually bidirectional text. How is offset 5 ambiguous? Do you have a visual example?
I'm adding my answer below.
TextAffinity disambiguates text position for soft wraps and bidirectional text boundaries. The affinity can be either upstream or downstream. Downstream is the default.
Soft wrap position
Given the string 0123456789 whose last character soft-wraps to the next line, you can choose the cursor position as follows. Both positions are at offset 9:
Downstream
Upstream
Bidirectional text boundary
Given the string Helloשלום where Hello is LRT text and שלום is RTL text, you can choose the cursor position at the boundary between them as follows. Both positions are at offset 5:
Downstream
Upstream
Going on
I write about this in more detail here.
I’m trying to create a rectangle box on screen in PTB wherein the participant can type text that is wrapped inside this box. So I would like to get the string input to be drawn on screen while typing in a rectangular box where the text input is wrapped to avoid it continuing outside the border of this box. I have been searching for a while now and haven’t found anything that works or anyone who did this before. I assume I might be overlooking something very simple.
I have tried using:
% Textbox
Screen('FrameRect',window, white, [300 300 1600 600],4);
message = [‘Your comments: ‘];
replySubj = Ask(window, message, white, black, 'GetChar',[300 225 1600 600]);
The response input is nicely drawn on screen while typing, but only on one line that is not wrapped when I reach the side of the box, or even my screen. Is their a way to wrap the text (e.g. by integrating WrapString.m) so it stays inside a specified rectangle on screen, and continues to a new line if the text is too long for one line?
Any help is very much appreciated.
Looking at the GetEchoString function, it does the following upon each character strike (to the best of my understanding of how the display is managed):
if it is Ctrl-C, Enter, or Return: exit;
if it is Backspace, issue command to re-draw the previous full string (prompt + user input) with the same colour as the background to erase it ; then remove the last character from the stored full string;
else append the character to the stored full string.
Then issue the command to draw the resulting updated full string in the specified colour, and finally update the screen following the previous commands, with the option dontclearset to 1 (incremental drawing, cf. Screen('Flip', windowPtr, 0, 1) call).
To add wrapping capabilities, we can thus modify GetEchoString as follows:
comment out the re-drawing commands when Backspace is hit, simply updating the stored string (see below);
add a call to WrapString on the updated string to wrap it;
used DrawFormattedText to issue command to display the wrapped string;
finally, call Screen('Flip', windowPtr) that is update the screen with dontclearset to 0 (default).
The relevant part of the function are now thus:
% adapted from PTB3 GetEchoString
while true
if useKbCheck
char = GetKbChar(varargin{:});
else
char = GetChar;
end
if isempty(char)
string = '';
break;
end
switch (abs(char))
case {13, 3, 10}
% ctrl-C, enter, or return
break;
case 8
% backspace
if ~isempty(string)
% Remove last character from string:
string = string(1:length(string)-1);
end
otherwise
string = [string, char];
end
output = [msg, ' ', string];
output=WrapString(output,maxNumChar);
DrawFormattedText(windowPtr,output,x,y,textColor,[],0,0,vLineSpacing);
Screen('Flip',windowPtr);
end
Where maxNumChar and vLineSpacing are to be defined depending on your needs.
This will take care of the horizontal wrapping of the text, while keeping the Backspace function working. Note however that you could still overflow vertically if the whole screen is filled.
I am trying to simulate Word's displaying of non-printing characters. There is no problem with all of them but anchors and I didn't found any info related to them. Is anchor special character placed in text or is it parameter of floating object and just displayed as special character?
Thank you for answer
The anchor, unlike most non-printing characters, can never print. It's merely a visual aid to inform the user with which paragraph or character a graphic with text flow formatting is associated. It's not possible to detect an anchor directly in the document text using Word's API (object model). It's bound to the graphic and would require analyzing the properties of the Shape object.
It could be determined by analyzing the document's WordOpenXML, although the term "anchor" is not used. The information could be deduced from the location and settings of the nodes that define where and how the graphic appears.
Is anchor special character placed in text or is it parameter of floating object and just displayed as special character?
I'm going to try to answer the "is it in text" question.
If, while debugging, you try to get a textual character for an anchor from a range's text, it won't be there. There won't even be a 0-width non-visible character there, like when you move a text cursor to the right past a non-printable character, but it doesn't actually move because there's something there (this may be editor-dependent, I have Notepad++ in mind).
So no, it's not in text.
But, at the same time, it will interfere with searches. E.g. If you put the word "text" on a line, put a text box on that line to create an anchor, and then search for "^13text" (with wildcards enabled, ^13 means the end-of-paragraph mark), it won't find it.
So yes, it must be in text because it interferes with searches.
So this might be a contradiction, but let's keep going. If it's in text, where is it? If you place the text cursor on the previous line, hold shift, and move it once to the right, the text box will be highlighted.
So it must be at the start.
But, there is also evidence that contradicts this. If you have a field at the start of the line with text on it, you can move it once to the right as before, and then once to the left, and though you have part of the line highlighted, the text box won't be part of the selection.
So, I really have no idea whether it's text or not, or where it is if so, but hopefully this helps someone else.