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

[Feature] Provide a Way to Escape Blocks of Content #8

Closed
zicklag opened this issue Nov 8, 2019 · 24 comments
Closed

[Feature] Provide a Way to Escape Blocks of Content #8

zicklag opened this issue Nov 8, 2019 · 24 comments

Comments

@zicklag
Copy link

zicklag commented Nov 8, 2019

I am trying to create manpage-like help pages using Termimad and I want to be able to inline the Clap commandline argument help into the document, but the styling for the help message gets a little confused because Termimad is interpreting the indentation in the help message as code blocks.

Could there be a way to make a whole block of the document so that it is taken literally instead of interpreted as Markdown syntax?

Maybe something like this:

\\\
Literal block here.

    This won't be interpreted as a codeblock because it is in the literal block section
\\\
@Canop
Copy link
Owner

Canop commented Nov 8, 2019

You might be interested by that:

fn main() {
    let mut skin = MadSkin::default();
    skin.bold.set_fg(Yellow);
    skin.inline_code.add_attr(Reverse);
    skin.bold.set_fg(Yellow);

    // with interpolation, after parsing
    mad_print!(&skin, "*count:* **$0**", "27"); // note that only &str is supported now
    println!();

    // another one: see that the arguments aren't interpreted as markdown,
    //  which is convenient for user supplied texts
    mad_print!(&skin, "**Formula for $1:** ` $0 `", "π*r*²", "disk");
    println!();

    // using any Write:
    mad_write!(&mut std::io::stdout(), &skin, "**$0** is *$1*\n", "Meow", "crazy").unwrap();
}

mad

I hope to publish it this weekend (testing it in broot).

In short: mad_print takes as argument a template interpreted as markdown but accepting replacements. The following arguments replace $0, $1, etc. and aren't interpreted as markdown (that's the whole point). The template is also compiled only once (using lazy_static).

@zicklag
Copy link
Author

zicklag commented Nov 8, 2019

That looks great. 👍

One note: I would want to be able to do keyword arguments in the template. So something like $help_message in addition to the $0 syntax.

@Canop
Copy link
Owner

Canop commented Nov 8, 2019

Right now placeholders are $0 to $9 only but accept omissions, repetitions and arbitrary order.

Are named placeholders really necessary ?

@zicklag
Copy link
Author

zicklag commented Nov 8, 2019

I have my docs in separate files like this that I include using include_str! so having a $0 in that would be a little out of context.

Still it wouldn't be a problem for me to have {{help_message}} in the external markdown file and then substitute that with $0 before passing that to the mad_write! macro. That would probably work just fine and not require the keyword replacement in the macro, if I'm not missing something.

@Canop
Copy link
Owner

Canop commented Nov 8, 2019

That wouldn't work with the mad_ macros, as the templace is of type &'static str (so that it's compiled only once).

But:

  • there's a Template type directly usable without macro (losing the convenience of the one liner but probably more suited to big texts anyway)
  • I'll look into named placeholders, I guess...

@zicklag
Copy link
Author

zicklag commented Nov 8, 2019

It probably wouldn't be bad to use the Template type if we had to. It is a more involved setup to use a separate file for the doc anyway.

@Canop
Copy link
Owner

Canop commented Nov 11, 2019

@zicklag FYI I just published 0.7.4 with templates

But it's still not what you need. I must work a little more to determine the exact specification to support named placeholders, whole texts (not just inline snippets), placeholders covering several lines, etc.

@Canop
Copy link
Owner

Canop commented Nov 20, 2019

Templating with names and sub-templates is coming soon.

static TEMPLATE: &str = r#"
# ${app-name} v${app-version}
**${app-name}** is *fantastic*!
## Modules
In a table:
|:-:|:-:|:-:|
|**name**|**path**|**description**|
|-:|:-:|:-|
${module-rows
|**${module-name}**|`${app-version}/${module-key}`|${module-description}|
}
|-|-|-|
and the same data in another form:
${module-rows
### ${module-name} (${module-key})
${module-description}
}
## Items
${formatted-items
* **${item-name}:** `${item-code}`
}
"#;

fn main() -> Result<()> {
    let skin = make_skin();
    let text_template = TextTemplate::from(TEMPLATE);
    let mut expander = text_template.expander();
    expander
        .set("app-name", "MyApp")
        .set("app-version", "42");
    expander.sub("module-rows")
        .set("module-name", "lazy-regex")
        .set("module-key", "lrex")
        .set("module-description", "eases regexes");
    expander.sub("module-rows")
        .set("module-name", "termimad")
        .set("module-key", "tmd")
        .set("module-description", "do things on terminal");
    expander.sub("formatted-items")
        .set("item-name", "3*5")
        .set("item-code", "187/12");
    expander.sub("formatted-items")
        .set("item-name", "π")
        .set("item-code", "22/7");
    let text = expander.expand();
    let (width, _) = terminal_size();
    let fmt_text = FmtText::from_text(&skin, text, Some(width as usize));
    println!("{}", &fmt_text);
    Ok(())
}

result

@zicklag
Copy link
Author

zicklag commented Nov 20, 2019

Ooh, that looks pretty neat. Nice work. That will be more than I need. :)

@Canop Canop closed this as completed in 46a2ffd Nov 24, 2019
@Canop
Copy link
Owner

Canop commented Nov 24, 2019

@zicklag I've published a new version with a description : https://github.com/Canop/termimad#templates

It should close this issue.

Please tell me how it works for you, though.

@zicklag
Copy link
Author

zicklag commented Nov 25, 2019

Awesome, I can't wait to try it out. I'll let you know how it goes.

@zicklag
Copy link
Author

zicklag commented Nov 27, 2019

It seems like there is no TextTemplate type that I can find in the repo or docs.rs. Did those changes somehow get left out of the Git commit?

@Canop
Copy link
Owner

Canop commented Nov 28, 2019

@zicklag I should make that clearer in the documentation: The TextTemplate is part of the Minimad library which is developed for Termimad and contains the Markdown making parts.

You should have a look at how templates are used in broot: https://github.com/Canop/broot/blob/master/src/help_content.rs

You'll need this in your dependencies:

minimad = "0.5.0"
termimad = "0.8.0"

@zicklag
Copy link
Author

zicklag commented Nov 28, 2019

Oh, perfect thanks.

@zicklag
Copy link
Author

zicklag commented Nov 28, 2019

I got it working! Thanks for the help!

image

The usage is substituted into the template from the clap long help message.

Some of the terminal control and rendering stuff took a little bit of experimentation for me to get right, but now it is working nicely.

@Canop
Copy link
Owner

Canop commented Nov 28, 2019

Oh that's pretty. I'll use it for a gallery if I can get a few other ones.

I'd be interested by suggestions regarding the documentation.

@zicklag
Copy link
Author

zicklag commented Nov 28, 2019

I'll take some more pictures when I get some more documentation written. 😉.

The biggest problem I had API-wise was that I couldn't use the MadView with the template because MadView takes a markdown string instead of a Text. Looking at your code from broot I did figure out how to reinitialize the Area, FmtText, and TextView ever frame and achieve the same effect.

@Canop
Copy link
Owner

Canop commented Nov 28, 2019

The current lifetime design of Minimad and Termimad minimizes memory and string copies but make a few things more complicated.
And when creating MadView, I had this in mind but not the templates.
There should probably be some new tool replacing MadView, or maybe some guidelines, to help deal with those problems.
But I don't want to clutter the lib with redundant structs so I'll have to think a little more before.

Side note: rebuilding everything at each render is reasonable: it's fast enough (normally less than a ms).

@zicklag
Copy link
Author

zicklag commented Nov 28, 2019

Yeah, the current design isn't bad or anything, it just isn't immediately apparent as a newbie. Also I'm new to terminal rendering so I had some confusion of when to flush the writer, etc.

There should probably be some new tool replacing MadView, or maybe some guidelines, to help deal with those problems.

That would be cool.

Side note: rebuilding everything at each render is reasonable: it's fast enough (normally less than a ms).

OK, thanks for the assurance of that. :) Also, I had some issue where, while scrolling, some of the text would get left over from previous lines in the command help. It only seems to happen in the command output.

Anyway, I just ended up clearing the whole screen at every update. Is that a decent solution? It caused more flickering, but I'm on a slow SSH connection at the moment, so I think it probably won't be a problem in general.

image

@Canop
Copy link
Owner

Canop commented Nov 28, 2019

No, you should not clean the whole screen at every render, the flickering isn't acceptable in my opinion.

There's a case of leftovers which happens when you resize the screen. That's why I usually do a screen cleaning at resize.

If your screenshot isn't related to terminal resizing, then an investigation is in order (and I can help if you build a minimal reproducible example). And if it's confirmed, this should be another issue.

@zicklag
Copy link
Author

zicklag commented Nov 28, 2019

OK, cool. I'll try to get a minimal example for you soonish.

@zicklag
Copy link
Author

zicklag commented Nov 28, 2019

Here is a minimal demonstration: https://github.com/katharostech/termimad/tree/termimad-test/examples/colored-template-scroll. Maybe not completely minimal, but it is simple ( tell me if you need me to trim it down furthur ).

The problem only happens when the text has to wrap a lot, and it only happens when color is enabled:

image

Edit: Also, I'm pretty sure this was happening without the template, too, when I was just using format! to get the help message in there.

@Canop
Copy link
Owner

Canop commented Nov 29, 2019

I just published Termimad 0.8.1 which should solve the problem.

Side note: crossterm has a function to get the size of the terminal, you don't need to import another crate for that.

@zicklag
Copy link
Author

zicklag commented Nov 29, 2019

That worked! Thanks for the fix. 😃

Thanks for the crossterm tip. 👍 I'm really liking crossterm. Very nice API.

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