summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPatrick Spek <p.spek@tyil.nl>2018-06-23 19:32:25 +0200
committerPatrick Spek <p.spek@tyil.nl>2018-06-23 19:32:25 +0200
commit4a2b457746736b8075f86145e0e3fed8473606a6 (patch)
tree41aa6b01a17e2197f3e19555faf6ffb187b0b416 /lib
downloadPod::To::Pager-4a2b457746736b8075f86145e0e3fed8473606a6.tar.gz
Pod::To::Pager-4a2b457746736b8075f86145e0e3fed8473606a6.tar.bz2
Commit the first version of the module
Diffstat (limited to 'lib')
-rw-r--r--lib/Pod/To/Pager.pm622
-rw-r--r--lib/Pod/To/Pager/BorderedBlock.pm6101
-rw-r--r--lib/Pod/To/Pager/Handlers.pm6371
3 files changed, 494 insertions, 0 deletions
diff --git a/lib/Pod/To/Pager.pm6 b/lib/Pod/To/Pager.pm6
new file mode 100644
index 0000000..8da16bf
--- /dev/null
+++ b/lib/Pod/To/Pager.pm6
@@ -0,0 +1,22 @@
+use v6.c;
+
+use Pod::To::Pager::Handlers;
+
+class Pod::To::Pager
+{
+ multi method render(@pod is copy)
+ {
+ @pod .= grep({ $_.WHAT ~~ Pod::Block::Named }) if (1 < @pod.elems);
+
+ self.render(@pod[0]);
+
+ return;
+ }
+
+ multi method render($pod)
+ {
+ print handle-pod($pod);
+ }
+}
+
+# vim: ft=perl6 noet
diff --git a/lib/Pod/To/Pager/BorderedBlock.pm6 b/lib/Pod/To/Pager/BorderedBlock.pm6
new file mode 100644
index 0000000..ac0b35e
--- /dev/null
+++ b/lib/Pod/To/Pager/BorderedBlock.pm6
@@ -0,0 +1,101 @@
+#! /usr/bin/env false
+
+use v6.c;
+
+use Terminal::ANSIColor;
+
+class Pod::To::Pager::BorderedBlock
+{
+ has Str %.box-characters =
+ outer-top-left => "┏",
+ outer-top-right => "┓",
+ outer-bottom-left => "┗",
+ outer-bottom-right => "┛",
+ outer-horizontal => "━",
+ outer-vertical => "┃",
+ seperator-left => "┠",
+ seperator-right => "┨",
+ seperator => "─",
+ ;
+
+ has Str $.content = "";
+ has Str $.header = "";
+ has Str $.footer = "";
+
+ multi method render (
+ --> Str
+ ) {
+ self.render(
+ $!content,
+ header => $!header,
+ footer => $!footer,
+ );
+ }
+
+ multi method render (
+ Str:D $content is copy,
+ :$header = "",
+ :$footer = "",
+ --> Str
+ ) {
+ # Trim content
+ $content .= trim;
+
+ # Calculate the maximum width of the content
+ my Int $longest-string = 0;
+
+ for $content.lines { $longest-string = colorstrip($_).chars if $longest-string < colorstrip($_).chars; }
+ for $header.lines { $longest-string = colorstrip($_).chars if $longest-string < colorstrip($_).chars; }
+ for $footer.lines { $longest-string = colorstrip($_).chars if $longest-string < colorstrip($_).chars; }
+
+ # Create the top bar
+ my Str $block = %!box-characters<outer-top-left>;
+ $block ~= %!box-characters<outer-horizontal> x $longest-string;
+ $block ~= %!box-characters<outer-top-right>;
+ $block ~= "\n";
+
+ # Add a header, if needed
+ if ($header ne "") {
+ for $header.lines {
+ $block ~= self!wrap-line($_, $longest-string);
+ }
+
+ $block ~= %!box-characters<seperator-left>;
+ $block ~= %!box-characters<seperator> x $longest-string;
+ $block ~= %!box-characters<seperator-right>;
+ $block ~= "\n";
+ }
+
+ # Add the main content
+ for $content.lines {
+ $block ~= self!wrap-line($_, $longest-string);
+ }
+
+ # Add a footer, if needed
+ if ($footer ne "") {
+ $block ~= %!box-characters<seperator-left>;
+ $block ~= %!box-characters<seperator> x $longest-string;
+ $block ~= %!box-characters<seperator-right>;
+ $block ~= "\n";
+
+ for $footer.lines {
+ $block ~= self!wrap-line($_, $longest-string);
+ }
+ }
+
+ # Create the bottom bar
+ $block ~= %!box-characters<outer-bottom-left>;
+ $block ~= %!box-characters<outer-horizontal> x $longest-string;
+ $block ~= %!box-characters<outer-bottom-right>;
+ }
+
+ method !wrap-line (
+ Str:D $line,
+ Int:D $length,
+ --> Str
+ ) {
+ %!box-characters<outer-vertical> ~ $line ~ " " x ($length - colorstrip($line).chars) ~ %!box-characters<outer-vertical> ~ "\n";
+ }
+}
+
+# vim: ft=perl6 noet
diff --git a/lib/Pod/To/Pager/Handlers.pm6 b/lib/Pod/To/Pager/Handlers.pm6
new file mode 100644
index 0000000..c7e54f5
--- /dev/null
+++ b/lib/Pod/To/Pager/Handlers.pm6
@@ -0,0 +1,371 @@
+#! /usr/bin/env false
+
+use v6.c;
+
+use Terminal::ANSIColor;
+use Pod::To::Pager::BorderedBlock;
+
+unit module Pod::To::Pager::Handlers;
+
+my @footnotes;
+
+multi sub handle-pod (
+ Pod::FormattingCode $pod,
+ Int :$indent-size = 8,
+ Int :$max-line-length = 80,
+ Str :$prefix is copy = "",
+ Str :$suffix is copy = "",
+ --> Str
+) {
+ $suffix = 0 < $suffix.chars
+ ?? RESET ~ $prefix
+ !! RESET
+ ;
+
+ given $pod.type {
+ when "B" { $prefix = BOLD; }
+ when "C" { $prefix = BOLD; }
+ when "E" {
+ return handle-pod(
+ $pod.contents,
+ :$max-line-length,
+ :$prefix,
+ :$suffix,
+ indent-size => 0,
+ );
+ }
+ when "I" { $prefix = ITALIC; }
+ when "K" { $prefix = color('yellow'); }
+ when "L" {
+ @footnotes.append(color('blue underline') ~ $pod.meta[0] ~ color('reset'));
+
+ return handle-pod(
+ $pod.contents[0] ~ "[" ~ @footnotes.elems ~ "]",
+ :$max-line-length,
+ indent-size => 0,
+ prefix => "",
+ suffix => "",
+ );
+ }
+ when "N" {
+ @footnotes.append($pod.contents[0]);
+
+ return "[" ~ @footnotes.elems ~ "]";
+ }
+ when "T" { $prefix = color('magenta') }
+ when "U" { $prefix = UNDERLINE; }
+ when "Z" { return ""; }
+ }
+
+ handle-pod(
+ $pod.contents,
+ :$max-line-length,
+ :$prefix,
+ indent-size => 0,
+ suffix => RESET,
+ );
+}
+
+multi sub handle-pod (
+ Pod::Block::Code $pod,
+ Int :$indent-size = 8,
+ Int :$max-line-length = 80,
+ Str :$prefix = "",
+ Str :$suffix = "",
+ --> Str
+) {
+ my Pod::To::Pager::BorderedBlock $block .= new;
+
+ my $code-block = $block.render(
+ handle-pod(
+ $pod.contents,
+ indent-size => 0,
+ max-line-length => 0,
+ prefix => BOLD,
+ suffix => color('reset'),
+ ),
+ header => $pod.config<name> // "",
+ );
+
+ $code-block.split("\n").map({ $_.indent($indent-size + 4) }).join("\n") ~ "\n\n";
+}
+
+#| Handle definition lists.
+multi sub handle-pod(
+ Pod::Block::Named $pod where { $pod.name eq "defn" },
+ Int :$indent-size = 8,
+ Int :$max-line-length = 80,
+ Str :$prefix = "",
+ Str :$suffix = "",
+ --> Str
+) {
+ my Str $first-line = $pod.contents[0].contents[0];
+ my ($word, @leftovers) = $first-line.split(/\s+/);
+
+ $pod.contents[0].contents[0] = @leftovers.join(" ");
+
+ my Str $text = "{color('cyan')}{$word}{color('reset')}\n".indent($indent-size);
+
+ $text ~= handle-pod(
+ $pod.contents,
+ indent-size => $indent-size + 2,
+ :$max-line-length,
+ :$prefix,
+ :$suffix
+ );
+
+ $text;
+}
+
+multi sub handle-pod (
+ Pod::Block::Named $pod where { $pod.name eq "input" },
+ Int :$indent-size = 8,
+ Int :$max-line-length = 80,
+ Str :$prefix = "",
+ Str :$suffix = "",
+ --> Str
+) {
+ my Pod::To::Pager::BorderedBlock $block .= new;
+
+ my $code-block = $block.render(
+ handle-pod(
+ $pod.contents,
+ indent-size => 0,
+ max-line-length => 0,
+ prefix => color('yellow'),
+ suffix => color('reset'),
+ ),
+ header => $pod.config<name> // "",
+ );
+
+ $code-block.split("\n").map({ $_.indent($indent-size + 4) }).join("\n") ~ "\n\n";
+}
+
+multi sub handle-pod (
+ Pod::Block::Named $pod where { $pod.name eq "output" },
+ Int :$indent-size = 8,
+ Int :$max-line-length = 80,
+ Str :$prefix = "",
+ Str :$suffix = "",
+ --> Str
+) {
+ my Pod::To::Pager::BorderedBlock $block .= new;
+
+ my $code-block = $block.render(
+ handle-pod(
+ $pod.contents,
+ indent-size => 0,
+ max-line-length => 0,
+ prefix => color('magenta'),
+ suffix => color('reset'),
+ ),
+ header => $pod.config<name> // "",
+ );
+
+ $code-block.split("\n").map({ $_.indent($indent-size + 4) }).join("\n") ~ "\n\n";
+}
+
+#| Handle the main pod block
+multi sub handle-pod(
+ Pod::Block::Named $pod where { $pod.name eq "pod" },
+ Int :$indent-size = 8,
+ Int :$max-line-length = 80,
+ Str :$prefix = "",
+ Str :$suffix = "",
+ --> Str
+) {
+ my Str $document;
+
+ for $pod.contents {
+ $document ~= handle-pod(
+ $_,
+ :$indent-size,
+ :$max-line-length,
+ :$prefix,
+ :$suffix
+ );
+ }
+
+ if (@footnotes) {
+ my $index-length = @footnotes.elems.Str.chars;
+
+ $document ~= handle-pod(
+ Pod::Block::Named.new(
+ name => "Footnotes and references",
+ )
+ );
+
+ $document ~= "\n";
+
+ loop (my $i = 0; $i < @footnotes.elems; $i++) {
+ my @lines;
+ my $line = [sprintf("%{$index-length}d: ", $i + 1)];
+ my @words = @footnotes[$i].split(/\s+/);
+
+ for @words -> $word {
+ if ($max-line-length < ($indent-size + $line.chars + $word.chars)) {
+ @lines.append(chomp($line).indent($indent-size));
+ $line = $word;
+ next;
+ }
+
+ $line ~= " $word";
+ }
+
+ @lines.append(chomp($line).indent($indent-size));
+
+ $document ~= @lines.join("\n") ~ "\n";
+ }
+ }
+
+ $document;
+}
+
+#| Handle all other non-specific named pod blocks.
+multi sub handle-pod (
+ Pod::Block::Named $pod,
+ Int :$indent-size = 8,
+ Int :$max-line-length = 80,
+ Str :$prefix = "",
+ Str :$suffix = "",
+ --> Str
+) {
+ my Str $text;
+
+ $text ~= "{color('bold blue')}{$pod.name}{color('reset')}\n";
+ $text ~= handle-pod(
+ $pod.contents,
+ :$indent-size,
+ :$max-line-length,
+ :$prefix,
+ :$suffix
+ ) // "";
+
+ $text;
+}
+
+multi sub handle-pod(
+ Pod::Block::Para $pod,
+ Int :$indent-size = 8,
+ Int :$max-line-length = 80,
+ Str :$prefix = "",
+ Str :$suffix = "",
+ --> Str
+) {
+ my Str $text = "";
+
+ for handle-pod(
+ $pod.contents,
+ indent-size => 0,
+ max-line-length => $max-line-length - $indent-size,
+ :$prefix,
+ :$suffix
+ ).lines {
+ $text ~= $_.indent($indent-size) ~ "\n";
+ }
+
+ $text ~ "\n";
+}
+
+multi sub handle-pod(
+ Pod::Item $pod,
+ Int :$indent-size = 8,
+ Int :$max-line-length = 80,
+ Str :$prefix = "",
+ Str :$suffix = "",
+ --> Str
+) {
+ my @contents = $pod.contents;
+ my Str $bullet = "• ";
+ my Int $width = ($pod.level - 1) × 2;
+ my Str $text = $bullet.indent($indent-size + $width);
+
+ $text ~= handle-pod(
+ $pod.contents,
+ indent-size => ($indent-size + $width + $bullet.chars),
+ max-line-length => ($max-line-length - $indent-size),
+ :$prefix,
+ :$suffix,
+ ).trim-leading;
+
+ $text;
+}
+
+multi sub handle-pod(
+ Pod::Heading $pod,
+ Int :$indent-size = 8,
+ Int :$max-line-length = 80,
+ Str :$prefix = "",
+ Str :$suffix = "",
+ --> Str
+) {
+ handle-pod(
+ $pod.contents,
+ :$max-line-length,
+ indent-size => 0,
+ prefix => color('bold blue'),
+ suffix => RESET,
+ );
+}
+
+multi sub handle-pod(
+ Str $text,
+ Int :$indent-size = 8,
+ Int :$max-line-length = 80,
+ Str :$prefix = "",
+ Str :$suffix = "",
+ --> Str
+) {
+ if ($max-line-length < 1) {
+ for $text.lines {
+ if ($_ eq "") {
+ return "\n";
+ }
+
+ return "{$prefix}{$_.indent($indent-size)}{$suffix}";
+ }
+ }
+
+ my @words = "{$prefix}{$text}{$suffix}".split(/\s+/);
+ my @lines;
+ my $line = @words.shift;
+
+ for @words -> $word {
+ if ($max-line-length < ($indent-size + $line.chars + $word.chars)) {
+ @lines.append(chomp($line).indent($indent-size));
+ $line = $word;
+ next;
+ }
+
+ $line ~= " $word";
+ }
+
+ @lines.append(chomp($line).indent($indent-size));
+
+ return @lines.join("\n");
+}
+
+multi sub handle-pod (
+ @nodes,
+ Int :$indent-size = 8,
+ Int :$max-line-length = 80,
+ Str :$prefix = "",
+ Str :$suffix = "",
+ --> Str
+) is export {
+ my Str $text;
+
+ for @nodes {
+ $text ~= handle-pod(
+ $_,
+ :$indent-size,
+ :$max-line-length,
+ :$prefix,
+ :$suffix,
+ );
+ }
+
+ $text;
+}
+
+# vim: ft=perl6 noet