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

Add ManSection enum, own title line struct and other minor updates #14

Closed
wants to merge 14 commits into from

Conversation

sondr3
Copy link

@sondr3 sondr3 commented Dec 18, 2021

The title line, manpage section and compatibility settings come from clap-rs/clap#3174, where we decided on extracting out Roff-specific functionality to this crate. I also did a few minor changes, like removing the derive for PartialEq and Eq from the structs. The title line struct will make #7 obsolete, and is in my opinion a better solution as the order of the elements is important and is not just a list of strings.

cc @epage

@sondr3 sondr3 mentioned this pull request Dec 18, 2021
4 tasks
Comment on lines +1 to +16
### Created by https://www.gitignore.io
### Rust ###
# Generated by Cargo
# will have compiled files and executables
debug/
target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come you are changing the .gitignore?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Force of habit, it carried over from my previous work on roff-rs, I can revert this if you want to.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do so. imo person/machine specific ignores should be set in the personal ignores rather than checked into the shared ignores.

Comment on lines +41 to +65
/// Manpage sections.
///
/// The most common is [`ManSection::Executable`], and is the recommended default.
#[derive(Clone, Copy)]
pub enum ManSection {
/// Executable programs or shell commands
Executable,
/// System calls (functions provided by the kernel)
SystemCalls,
/// Library calls (functions within program libraries)
LibraryCalls,
/// Special files (usually found in /dev)
SpecialFiles,
/// File formats and conventions, e.g. /etc/passwd
FileFormats,
/// Games
Games,
/// Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7)
Miscellaneous,
/// System administration commands (usually only for root)
SystemAdministrationCommands,
/// Kernel routines [Non standard]
KernelRoutines,
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I'm missing something, this seems like man policy when this crate is focused on the underlying markup.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your two comments about whether things should go here or in a more manpage specific crate was one of the reasons I ended up trying to do everything in clap_man, the inclusion of a title line means we're already targeting manpages and not "pure" roff. It is a massive type-setting system (here is short reference of GNU variant of the format, you can see we're only really touching a tiny, tiny part of it), and has historically been used for lots of different things from books, articles and more.

Nowadays however I thing nobody uses it outside of manpages anymore, and while the man crate contains useful tools to build manpages for CLI tools this crate already targets a subset of roff specific to manpages, at least in my opinion. sweat_smile roffman that you mentioned in the PR in clap has sections in it, though the name implies that it is specific for manpages, but not a huge fan of its API.

Sorry, this is a lot of words for saying that in my head roff-rs is already a manpage specific crate slightly_smiling_face It's again one of the reasons I've attempted a few different approaches to this, I haven't found a good solution for it yet besides creating my own crate for this.

My thought is to prefer to keep this crate man agnostic unless its getting in the way of getting clap_man done.

It looks like we could have the Section enum and the title formatting external to this crate and lose nothing but I'm not as knee deep in both crates as you are, so I defer to your judgement.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Due to the current architecture this crate cannot be used to create anything besides manpages, so it is in a sense already specific to manpages and not agnostic. I'm starting to lean more towards having a more intermediate crate specifically for creating manpages, I have a prototype laying around that I could revive. Thoughts?

Comment on lines +95 to +100
/// Date of the last nontrivial change to the manpage. Should be formatted
/// in `YYYY-MM-DD`.
pub fn date(mut self, date: impl Into<String>) -> Self {
self.title.date = Some(date.into());
self
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we accept year, month, day arguments so we can enforce formatting or eventually add a date/time lib dependency (haven't looked to see where the community is at with time vs chrono)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's probably a better way of doing it, good point. Not sure I'd like to pull in a full library for date changes here, we might do it in clap_man instead to fill these in instead.

}
}

pub struct Roff {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Roff is the entry point for this crate. please keep it first in the file so its easier to jump in and see what this crate does

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix!

Comment on lines +4 to +10
pub struct Title {
title: String,
section: i8,
section: ManSection,
date: Option<String>,
source: Option<String>,
manual: Option<String>,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How much of this is roff vs man policy?

src/lib.rs Show resolved Hide resolved
#[derive(PartialEq, Eq)]
pub struct Roff {
/// Title line for a manpage.
pub struct Title {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should at least implement Debug and Clone on everything

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point!

@@ -48,7 +148,6 @@ impl Troffable for Roff {
}
}

#[derive(PartialEq, Eq)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come you've been dropping PartialEq, Eq from these items?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really know why it's derived, I can't imagine it was used for something besides testing (the first full commit has them derived but not used) because comparing manpages for equality sounds very niche.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I lean towards keeping them (slightly less important than Clone and Debug) though we should make sure we call this out as a breaking change.

Comment on lines +207 to 209
pub fn escape(input: &str) -> String {
input.replace("-", r"\-")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is escape public? It seems like the API should be enforcing whats escaped or not

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was an oversight on my part, I forgot that everything is escaped when rendered, I'll fix this.

@sondr3
Copy link
Author

sondr3 commented Dec 18, 2021

Your two comments about whether things should go here or in a more manpage specific crate was one of the reasons I ended up trying to do everything in clap_man, the inclusion of a title line means we're already targeting manpages and not "pure" roff. It is a massive type-setting system (here is short reference of GNU variant of the format, you can see we're only really touching a tiny, tiny part of it), and has historically been used for lots of different things from books, articles and more.

Nowadays however I thing nobody uses it outside of manpages anymore, and while the man crate contains useful tools to build manpages for CLI tools this crate already targets a subset of roff specific to manpages, at least in my opinion. 😅 roffman that you mentioned in the PR in clap has sections in it, though the name implies that it is specific for manpages, but not a huge fan of its API.

Sorry, this is a lot of words for saying that in my head roff-rs is already a manpage specific crate 🙂 It's again one of the reasons I've attempted a few different approaches to this, I haven't found a good solution for it yet besides creating my own crate for this.

@@ -109,7 +109,7 @@ impl Troffable for Section {
fn render(&self) -> String {
let mut res = String::new();

writeln!(&mut res, ".SH {}", self.title.to_uppercase()).unwrap();
writeln!(&mut res, ".SH \"{}\"", self.title.to_uppercase()).unwrap();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fail if the title contains quote characters. I'm not sure how to fix that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oddly, I'm not seeing any quote escaping in asciidoctor, only left/right quotes. I wonder if that is an artifact of them only using left/right quotes

https://github.com/asciidoctor/asciidoctor/blob/main/lib/asciidoctor/converter/manpage.rb#L716

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some more information on escaping, check out https://www.ibm.com/docs/en/aix/7.2?topic=t-troff-command (search for mm Strings)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been reading the groff(7), and I can't see any way to escape quotes in control lines or macro arguments.

@@ -130,6 +130,16 @@ impl Troffable for Roff {

writeln!(&mut res, "{}", self.title.render()).unwrap();

// Compatibility settings:
Copy link

@larswirzenius larswirzenius Dec 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed? What requires turning of justification and hyphenation?

I'm looking at this from a manual page generation point of view, and non-justified manual pages are unusual, and thus jarring to read. I could live with it, but I'd like the comment to explain what requires it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the topic of compat settings, asciidoctor does https://github.com/asciidoctor/asciidoctor/blob/main/lib/asciidoctor/converter/manpage.rb#L61 (with links out for information)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point about plain apostrophes is a good one, and I should add that to my roff crate version. However, I can't see any explanation of why hyphenation and justification should be turned off. The sentence space size I can live with: it removes the need to make sure sentences end with a newline after the terminating punctuation.

@larswirzenius
Copy link

I had a closer look at the manual page generation and the roff crate. I've pushed two branches that I think would be an improvement.

https://github.com/larswirzenius/roff-rs/tree/liw/roff-only changes roff to have an abstraction level of ROFF only, dropping manual page stuff. The commit message has some more detailed explanations. The branch isn't ready to be merged, and needs some cleanup first.

I then ported @sondr3's maual page generation to my roff version (https://github.com/larswirzenius/clap/tree/liw/generate-man). This, too, probably needs cleanup.

What do you think? Is my approach of any interest?

@epage
Copy link
Contributor

epage commented Dec 20, 2021

What do you think? Is my approach of any interest?

I really like this! By focusing on the roff structure, I feel like it makes clearer the intent of what is going on while giving the benefit of escaping and typing (compared to doing everything with raw strings).

@sondr3
Copy link
Author

sondr3 commented Dec 21, 2021

I too like your approach and from the comment over on the PR to clap you have far more experience working with manpages and the roff-format, so you can be the judge for this crate. Do you want to create a PR against my fork of clap so we can integrate your changes once you feel it's ready? 😄

@larswirzenius
Copy link

I will do that later today or tomorrow, as soon as I've dug myself out from this horde of elves I'm buried under.

@sondr3
Copy link
Author

sondr3 commented Dec 23, 2021

Superseded by #15.

@sondr3 sondr3 closed this Dec 23, 2021
@sondr3 sondr3 deleted the updates branch June 17, 2024 17:51
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

Successfully merging this pull request may close these issues.

3 participants