Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic line wrap in the same indent level? #16

Open
taishi-n opened this issue Dec 5, 2022 · 4 comments
Open

Automatic line wrap in the same indent level? #16

taishi-n opened this issue Dec 5, 2022 · 4 comments

Comments

@taishi-n
Copy link

taishi-n commented Dec 5, 2022

First, thank you for the excellent package!

I tried to write pseudocode with your package in a float environment.
My question: how to wrap lines under the same indent level in float environment?
I looked over your documentation and implementation but could not find an appropriate solution.

Here is a brief example.

\documentclass[10pt]{article}

% math
\usepackage{amsfonts,amsmath,amssymb,amsthm}

% tcolorbox
\usepackage[xparse,breakable,hooks,listingsutf8,documentation]{tcolorbox}
\tcbuselibrary{skins,theorems}
\newtcbtheorem[number within = section]{algorithm}{Algorithm}{pseudo/booktabs, float}{alg}

% pseudo-code
\usepackage{tabularx}

\usepackage{pseudo}
\pseudodefinestyle{fullwidth}{
    begin-tabular =
    \tabularx{\linewidth}[t]{@{}
        r                                      % Labels
        >{\leavevmode\pseudosetup}             % Indent, font, ...
        X                                      % Code (flexible)
        >{\leavevmode\small\color{gray}}       % Comment styling
        p{0.5\linewidth}                       % Comments (fixed)
        @{}},
    end-tabular=\endtabularx,
}
\pseudoset{%
   fullwidth,
   kwfont=\sffamily\bfseries,
   prfont=\textsf,
   indent-mark,
   ref,
}

\begin{document}

Here is our novel strong proposed method summarized in Algorithm \ref{alg:main}.
However some problems occur in the \texttt{float} environment.
\begin{algorithm}{Proposed method}{prop}
  \label{alg:main}
  \begin{pseudo}
    \kw{for} $i = 1, \dots, 100$ \\+
    A short process, this is fine \\
    A really very long long process which was proposed \\
    in a paper published a lot lot years ago. \\
    Manual linebreaking is fine of cource. \\
    \kw{if} some condition is satisfied \\+
    A really very long long process which was proposed in a paper published a lot lot years ago... \\+
    Also I want this line to be wrapped under the same indent level... \\
    I want to get\\
    like this automatically
  \end{pseudo}
\end{algorithm}

\end{document}

Then I got a result like this:
example-output

@mlhetland
Copy link
Owner

mlhetland commented Jan 24, 2023

I'm glad you like the package! Also, thanks for the clear example. (And sorry I didn't notice the issue until now!)

First, a quick tip: You might not want to put the \label command before the pseudocode, there, as you can see that produces extra whitespace. Because you add prop as an argument to the algorithm environment, and alg as the prefix, you should already have the label alg:prop available. If you remove \label{alg:main} and replace \ref{alg:main} with \ref{alg:prop}, the spacing should be corrected – and the reference will also work.

As for the line breaking: Well, that's not really something that's directly supported at the moment, I'm afraid.

I'm sure you've seen the HOWTO on having steps span multiple lines already – and it doesn't really address the issue (as it isn't automatic), but it does at least produce a result similar to what you want. That is, you could use \\* manually, to get down to the next line, and then & to skip the numbering (and get the correct indentation). In your case:

\begin{algorithm}{Proposed method}{prop}
  \begin{pseudo}
    \kw{for} $i = 1, \dots, 100$ \\+
    A short process, this is fine \\
    A really very long long process which was proposed \\
    in a paper published a lot lot years ago. \\
    Manual linebreaking is fine of cource. \\
    \kw{if} some condition is satisfied \\+
    A really very long long process which was proposed in a paper \\*
&   published a lot lot years ago... \\+
    Also I want this line to be wrapped under the same indent \\*
&   level... \\
    I want to get\\
    like this automatically
  \end{pseudo}
\end{algorithm}

Screenshot 2023-01-24 at 13 27 00

Of course this has two distinct disadvantages: (1) It is not automatic, and (2) it leads to ragged-right text (which might not be what you want).

Now, I'm sure there are ways of getting what you want. For example:

  • One might be able to hijack the automatic line breaks, and have them insert the appropriate prefix and setup, just like \\ does (in the pseudo environment); or
  • One might wrap the code line in a box (like a top-aligned) minipage, so it would look like a single line to pseudo, but would contain multiple lines.

I'll look into this – it would be a good feature to have.

@mlhetland
Copy link
Owner

The line break hijacking could perhaps be done in a manner similar to that used in the lineno package. That package does a lot of really clever stuff in the more recent versions, but we probably only need the basic mechanism, found in the original version. Essentially, it's about using \interlinepenalty and \output to insert a hook.

@mlhetland
Copy link
Owner

More relevant explanations of \output: https://tex.stackexchange.com/a/8736/18003

@mlhetland
Copy link
Owner

I've had a look at some mechanisms, here, and it doesn't seem entirely straightforward. I'd still like to get this into the package, but I'm not sure how soon that'll be. For now, my recommended solution is to use \\*& as a manual line break and indent (without inserting a new line number), as described in my answer above.

Some musing on various options below, if you're interested.

Now, if you can work with the manual line breaking, and you can set the width of your main text column manually (or you can at least find its width), you can still manage to get adjusted text. It's not super-elegant, but it works:

\newlength\mywidth
\setlength\mywidth{11.5cm}

\pseudoset{
    indent-mark,
    preamble = {
        @{}
        r
        >{\leavevmode\pseudosetup}
        p{\mywidth}
        @{}
    },
}

\begin{pseudo}
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
tempor invidunt ut labore et dolore magna aliquyam erat. \\+
\makebox[\mywidth - \pseudoindentlength][s]{%
At vero eos et accusam et justo duo dolores et ea rebum. Gubergren,} \\*&
no sea takimata sanctus est Lorem ipsum dolor sit amet.
\end{pseudo}

This produces the following:

Screenshot 2023-01-25 at 15 34 29

The point is simply that the main pseudocode is set in a p column of a known width (rather than an X column, which has a width calculated by repeated typesetting). We can then use a \makebox to stretch out the lines that are broken manually. Their width is the same as that of the entire column (in this case, \mywidth), but we subtract the \pseudoindentlength. If we've indented another level, we'd subtract 2\pseudoindentlength, etc. (There's an internal variable containing the indent level, which could be used for this, to add some automation.)

I could add some functionality for this, I guess, but I'm not yet 100% sure it's really useful, or the right way to go.

Now, if you've got the width of the column, you could also use \parbox or the like to get automatic wrapping:

\begin{pseudo}
% Don't really need a \parbox at the first level …
\parbox[t]{\mywidth}{Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.}
\\+
\parbox[t]{\mywidth - \pseudoindentlength}{At vero eos et accusam et justo duo
dolores et ea rebum. Gubergren, no sea takimata sanctus est Lorem ipsum dolor
sit amet.}
\end{pseudo}

This does work – however it messes with the spacing between the steps (i.e., the numbered "lines"):

Screenshot 2023-01-25 at 15 42 30

Getting the spacing right is probably just a matter of tweaking, so something like this could work.

Another option, which would require restructuring the basic mechanisms of pseudo, would be to use columns for indentation, and to place the code in a \multicolumn. If that had worked with the X columns of tabularx, it might be a good solution – but having the \multicolumn use an X colum doesn't really work, because all X columns have the same width.

Using \output is probably tricky – and even if it could be made to work, it might not be ideal. You can simulate what that solution would probably look like by using \newline\null\pseudoindent as a line break command. At least with the default indent-mark, you end up getting a broken vertical line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants