Print embedded Pod as formatted text with termcap escapes - raku

I am trying to output embedded Pod as ANSI text to the terminal. In Perl 5 I can use Pod::Text::Termcap:
use strict;
use warnings;
use Pod::Text::Termcap;
my $str = do {local $/; <DATA>};
my $parser = Pod::Text::Termcap->new();
$parser->parse_string_document( $str, \*STDERR );
__DATA__
=head1 SYNOPSIS
my_test_command I<filename> [OPTIONS]
=head1 ARGUMENTS
=over 4
=item I<filename>
File name to test
=back
=head1 OPTIONS
=over 4
=item B<--help>
Prints help
=back
=head1 DESCRIPTION
A sample test command with embedded Pod
Output:
I tried to achieve the same in Perl 6:
use v6;
%*ENV<POD_TO_TEXT_ANSI> = 1;
my #lines;
for $=pod -> $pod-block {
for $pod-block.contents -> $pod-item {
use Pod::To::Text;
push #lines, pod2text($pod-item);
}
}
say #lines.join("\n\n");
=begin pod
=head1 SYNOPSIS
my_test_command I<filename> [OPTIONS]
=head1 ARGUMENTS
=item I<filename>
File name to test
=head1 OPTIONS
=item B<--help>
Prints help
=head1 DESCRIPTION
A sample test command with embedded Pod
=end pod
Output:
As seen the ANSI termcap escapes are missing in the Perl 6 output. How can I get ANSI features like bold face and underlined text in Perl 6?

Pod::To::Text accepts an environment variable POD_TO_TEXT_ANSI that turns this on. Setting that env var inside of a DOC phaser might be too late, though, if the selected Pod::To module is loaded before the perl 6 code is parsed however.

Regarding your question:
How can I get ANSI features like bold face and underlined text in Perl 6?
You might want to give Terminal::ANSIColor a try but you will need to add the ANSI escape codes yourself; it's not going to work automatically on PODs

Related

raku run('find .', :out); not working on MacOS

While testing around this issue, Can raku avoid this Malformed UTF-8 error? it was suggested that I try using the built in MacOS 'find .' command with the raku run function.
1 #!/usr/local/bin/raku
2
3 shell('find .'); #works
4
5 my $proc = run('find .', :out); #fails with
6 $proc.out.lines(:close).say; #() [ie. ().Seq]
Turns out that raku shell works fine, but raku run fails. I am not entirely sure if this is a bug with raku on MacOS (if so, I am happy to report it) ...?
[MacOS Catalina 10.15.17 ... Welcome to 𝐑𝐚𝐤𝐮𝐝𝐨™ v2020.10. Implementing the 𝐑𝐚𝐤𝐮™ programming language v6.d. Built on MoarVM version 2020.10.]
The issue you're running encountering isn't related to MacOS – it's caused by the difference in how &shell and &run work. Consulting the docs, we can see that shell's signature includes $cmd – the command as a Str, exactly as you provided.
In contrast, run's signature specifies that it takes *#args – that is, a list of zero or more arguments to execute.
To match this signature, you should change your code as shown below:
# my $proc = run('find .', :out); # doesn't work
my $proc = run('find', '.', :out); # works
my $p2 = run <find .>, :out; # also works (using word-splitting)
(Your version asked your computer to run the program find ., which doesn't exist in your $PATH, which explains why it produced no output.)

Don't show declarator blocks with p6doc

I've written a small example file to learn more about Perl 6 POD, and I'm using p6doc to render a small manual page from the POD document. However, p6doc also tries to parse the declarator blocks outside the POD document. This doesn't look particularly great in the output. Is there a way to ignore the declarator blocks when using p6doc?
The code sample I'm using is:
#! /usr/bin/env perl6
use v6.c;
#| Greet people on the command line.
sub MAIN (
#| A name to greet.
$names,
#| Optional. Additional names to greet.
*#names,
) {
*
}
=begin pod
=NAME greeter
=AUTHOR Patrick Spek
=VERSION 0.0.1
The greeter application greets someone via a terminal. At least 1 name is
required, but multiple names can be given to greet many people in one go.
=end pod
And the output given by p6doc is:
sub MAIN(
$names, # A name to greet.
*#names, # Optional. Additional names to greet.
)
Greet people on the command line.
class $names
A name to greet.
class *#names
Optional. Additional names to greet.
NAME
greeter
AUTHOR
Patrick Spek
VERSION
0.0.1
The greeter application greets someone via a terminal. At least 1 name is
required, but multiple names can be given to greet many people in one go.
Everything before the NAME part is what I want to remove from the p6doc output.
declarator blocks outside the POD document.
A couple minor things that still seem worth a quick mention first:
It's considered best practice to call it pod (or Pod or Pod6 or POD6) rather than POD to distinguish it from P5's POD because it's not backwards compatible, in the same way P6 isn't backwards compatible with P5;
The syntax =begin pod ... =end pod doesn't declare "the pod document". It declares a pod block that's one of many that comprise the overall pod document. You can have several of them. And the reason for mentioning this is because declarator blocks are also pod blocks. This is why they get included.
Is there a way to ignore the declarator blocks when using p6doc?
You could run the output through a filter at the shell command level.
But see my next comment for what's likely a better way.
I'm using p6doc
p6doc is a wrapper around perl6 --doc.
perl6 --doc provides exactly the same result as you've shown in your question, but has an output post-processing option (and isn't limited to installed modules only).
Assuming you can switch to using perl6 --doc instead:
perl6 -doc, without an argument to the --doc option, uses the default pod output filter.
Using perl6 --doc=MyFilter.pm6 you can run the pod through an installed custom filter module Pod::To::MyFilter.pm6.
See a search of modules.perl6.org for pod::to for a full list of filters that you can use as examples.

Do Perl 6 programs have to compile to read embedded docs?

Perl 6 Plain-Old-Documentation (perhaps Fancy-New-Documentation) has some features that allow it to construct documentation for things it sees, and the documentation shows up in the $=pod variable at runtime.
However, I was surprised when I couldn't read the docs when I'd made an error in the program text. Here I've left out a statement separator between two statements:
use v6;
BEGIN { put "BEGIN" }
INIT { put "INIT" }
CHECK { put "CHECK" }
"foo" "bar";
DOC INIT { put "DOC INIT" }
DOC BEGIN { put "DOC BEGIN" }
DOC CHECK { put "DOC CHECK" }
=begin pod
=head1 This is a title
This is a bit of pod
=end pod
When I run it with the --doc switch, the program syntax matters (and BEGIN runs):
$ perl6 --doc doc.p6
BEGIN
===SORRY!=== Error while compiling ...
Two terms in a row
------> "foo"⏏ "bar";
expecting any of:
infix
infix stopper
statement end
statement modifier
statement modifier loop
When I fix it, I get some warnings (so, perl6 is compiling) and the compilation-time phasers run:
BEGIN
DOC BEGIN
DOC CHECK
CHECK
WARNINGS for /Users/brian/Desktop/doc.p6:
Useless use of constant string "bar" in sink context (line 9)
Useless use of constant string "foo" in sink context (line 9)
INIT
DOC INIT
This is a title
This is a bit of pod
We already know this is a bit dangerous in Perl 5. A perl -c and a BEGIN block can run code. See How to check if a Perl script doesn't have any compilation errors?. I don't think this is any more dangerous than something we already know, but now it's happening at a time when I'm not explicitly asking something to compile program statements.
I haven't delved into the details of Perl 6 pod and why this might be necessary outside of declarator blocks and .WHY (a cool feature), but it seems like this can lead to trouble. Is there perhaps an external program that might extract the Pod? Or a way to do without the declarators unless the program will run?
Yes, the whole file has to be parsed, which in turn requires running BEGIN and use statements and such.
The Perl 6 language is designed for one-pass parsing from top to bottom, so that at any given point the parser understands what it is parsing based on what it has parsed so far.
Consider code like the following:
say "
=begin pod
Not POD, just a string!
";
If you'd just grep the file for POD statements without parsing all of it, it would misinterpret this piece of code.
I.e. you can't parse only the POD parts without parsing the normal Perl 6 code parts, because without parsing it all from top to bottom you can't know which is which.
PS: In theory, the Perl 6 designers could have accommodated POD-only parsing, by making it illegal for normal Perl 6 code to contain lines that look like they start a POD block. In this scenario, the above code snippet would be a syntax error when the whole file is parsed, because starting a line inside a string literal with =begin pod would be disallowed, so the --pod switch could rely on all lines that begin with =begin foo actually starting a POD block.
Such a restriction probably wouldn't be a major burden for normal Perl 6 code (after all, who needs to write =begin pod at the start of a line in a multi-line string literal), but note that one of the reasons for the one-pass top-to-bottom parsing architecture is to facilitate language extensibility via slangs.
E.g. CPAN modules could add support for users writing a single subroutine (or other lexical scope) in another language or DSL. (Implementing such modules isn't actually possible yet without hacking into Rakudo internals via NQP, but once the macro/slang design is complete, it will be).
The burden for disallowing lines that look like they start a POD block, would then be passed on to all those slang parsers.
You could always submit a feature request for Larry and the other Perl 6 designers to consider this, though.

Lua syntax highlighting latex for arXiv

I have a latex file which needed to include snippets of Lua code (for display, not execution), so I used the minted package. It requires latex to be run with the latex -shell-escape flag.
I am trying to upload a PDF submission to arXiv. The site requires these to be submitted as .tex, .sty and .bbl, which they will automatically compile to PDF from latex. When I tried to submit to arXiv, I learned that there was no way for them to activate the -shell-escape flag.
So I was wondering if any of you knew a way to highlight Lua code in latex without the -shell-escape flag. I tried the listings package, but I can't get it to work for Lua on my Ubuntu computer.
You can set whichever style you want inline using listings. It's predefined Lua language has all the keywords and associated styles identified, so you can just change it to suit your needs:
\documentclass{article}
\usepackage{listings,xcolor}
\lstdefinestyle{lua}{
language=[5.1]Lua,
basicstyle=\ttfamily,
keywordstyle=\color{magenta},
stringstyle=\color{blue},
commentstyle=\color{black!50}
}
\begin{document}
\begin{lstlisting}[style=lua]
-- defines a factorial function
function fact (n)
if n == 0 then
return 1
else
return n * fact(n-1)
end
end
print("enter a number:")
a = io.read("*number") -- read a number
print(fact(a))
\end{lstlisting}
\end{document}
Okay so lhf found a good solution by suggesting the GNU source-hightlight package. I basically took out each snippet of lua code from the latex file, put it into an appropriately named [snippet].lua file and ran the following on it to generate a [snippet]-lua.tex :
source-highlight -s lua -f latex -i [snippet].lua -o [snippet]-lua.tex
And then I included each such file into the main latex file using :
\input{[snippet]-lua}
The result really isn't as nice as that of the minted package, but I am tired of trying to convince the arXiv admin to support minted...

colorizing golang test run output

I like it when terminal/console test runs actually show their output in either red or green text. It seems like a lot of the testing libraries available for Go have this. However, I'd like to just use the default testing package that comes with Go. Is there a way to colorize it's output with red and green?
You can use grc, a generic colourizer, to colourize anything.
On Debian/Ubuntu, install with apt-get install grc. On a Mac with , brew install grc.
Create a config directory in your home directory:
mkdir ~/.grc
Then create your personal grc config in ~/.grc/grc.conf:
# Go
\bgo.* test\b
conf.gotest
Then create a Go test colourization config in ~/.grc/conf.gotest, such as:
regexp==== RUN .*
colour=blue
-
regexp=--- PASS: .*
colour=green
-
regexp=^PASS$
colour=green
-
regexp=^(ok|\?) .*
colour=magenta
-
regexp=--- FAIL: .*
colour=red
-
regexp=[^\s]+\.go(:\d+)?
colour=cyan
Now you can run Go tests with:
grc go test -v ./..
Sample output:
To avoid typing grc all the time, add an alias to your shell (if using Bash, either ~/.bashrc or ~/.bash_profile or both, depending on your OS):
alias go=grc go
Now you get colourization simply by running:
go test -v ./..
You can create a wrapper shell script for this and color it using color escape sequence. Here's a simple example on Linux (I'm not sure how this would look on windows, but I guess there is a way.. :) )
go test -v . | sed ''/PASS/s//$(printf "\033[32mPASS\033[0m")/'' | sed ''/FAIL/s//$(printf "\033[31mFAIL\033[0m")/''
There's also a tool called richgo that does exactly this, in a user-friendly way.
You would still need a library to add color escape code like:
for Windows: mattn/go-colorable or shiena/ansicolor
for Unix or Windows: fatih/color or kortschak/ct
for Unix or Windows: logrusorgru/aurora (mentioned by Ivan Black in the comments)
From there, you specify what you want to color (StdOut or StdErr, like in this example)
rakyll/gotest (screenshot) is a binary that does this.
Example:
$ gotest -v github.com/rakyll/hey
Emoji
You can use colors for text as others mentioned in their answers to have colorful text with a color code or using a third-party library.
But you can use emojis instead! for example, you can use⚠️ for warning messages and 🛑 for error messages.
Or simply use these notebooks as a color:
📕: error message
📙: warning message
📗: ok status message
📘: action message
📓: canceled status message
📔: Or anything you like and want to recognize immediately by color
🎁 Bonus:
This method also helps you to quickly scan and find logs directly in the source code.
But some distributions of Linux default emoji font are not colorful by default and you may want to make them colorful, first.
BoltDB has some test methods that look like this:
func assert(tb testing.TB, condition bool, msg string, v ...interface{}) {
if !condition {
_, file, line, _ := runtime.Caller(1)
fmt.Printf("\033[31m%s:%d: "+msg+"\033[39m\n\n", append([]interface{}{filepath.Base(file), line}, v...)...)
tb.FailNow()
}
}
Here are the rest. I added the green dots here.