A book about the command line for humans.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
2.4 KiB

  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use 5.10.0;
  5. use Cwd;
  6. use File::Basename;
  7. use Text::Markdown::Discount;
  8. use IPC::System::Simple qw(capturex);
  9. # Enable html5 block-level tags:
  10. Text::Markdown::Discount::with_html5_tags();
  11. my $flags = Text::Markdown::Discount::MKD_EXTRA_FOOTNOTE();
  12. my $markdown = Text::Markdown::Discount->new;
  13. my $cwd = Cwd::getcwd();
  14. my $full_source = '';
  15. while (my $source = get_input()) {
  16. # A simple preprocessor:
  17. my ($basename, $dir) = fileparse($ARGV); # get path of target file
  18. chdir $dir;
  19. $source =~ s{<!-- exec -->(.*?)<!-- end -->}{handle_block($1);}egs;
  20. chdir $cwd;
  21. $full_source .= "<!-- {{{ -->\n\n" . $source . "<!-- }}} -->";
  22. # $full_source .= "\n\n<div class=slide>\n\n" . $source . "\n\n</div>\n\n";
  23. }
  24. # actually spit out the contents of the slide
  25. print replace_some_stuff($markdown->markdown($full_source, $flags));
  26. sub get_input {
  27. local $/ = undef;
  28. my $source = <>;
  29. return $source;
  30. }
  31. sub handle_block {
  32. my ($block) = @_;
  33. my $cmd;
  34. if ($block =~ m/\$ (.*?)$/m) {
  35. $cmd = $1;
  36. my $result = `$cmd`;
  37. # indent 4 spaces so we get a code block:
  38. $result =~ s/^/ /gm;
  39. return "<!-- exec -->\n\n \$ " . $cmd . "\n" . $result . "\n<!-- end -->";
  40. } else {
  41. die "bogus cmd";
  42. }
  43. }
  44. # super cheeseball, man
  45. sub replace_some_stuff {
  46. my ($markup) = @_;
  47. # bold first "$ command" string in a code block
  48. # $markup =~ s{<code>(\$ .*?)$}{<code><b>$1</b>}gm;
  49. # my $content_link_marker = '#';
  50. my $content_link_marker = '';
  51. my @contents;
  52. # insert anchors in headers, accumulate a table of contents
  53. $markup =~ s{<(h[12])(.*?)>(.*?)</h[12]>}{
  54. my ($tag, $attributes, $text) = ($1, $2, $3);
  55. my $a_name = $text;
  56. $a_name =~ s/[^a-z]+/-/ig;
  57. $a_name =~ s/^-|-$//g;
  58. push @contents, make_contents_link($tag, $a_name, $text);
  59. "<$tag$attributes><a name=$a_name href=#$a_name>$content_link_marker</a> $text</$tag>";
  60. }iesg;
  61. my $contents_text = '<div class=contents>'
  62. . $markdown->markdown((join "\n", @contents), $flags)
  63. . '</div>';
  64. $markup =~ s/{{contents}}/$contents_text/g;
  65. $markup =~ s/<!-- {{{ -->/<section>/g;
  66. $markup =~ s/<!-- }}} -->/<\/section>/g;
  67. return $markup;
  68. }
  69. # make an individual element of a markdown list
  70. sub make_contents_link {
  71. my ($tag, $a_name, $text) = @_;
  72. if ($tag eq 'h2') {
  73. return " * [$text](#$a_name)";
  74. } elsif ($tag eq 'h1') {
  75. return "* [$text](#$a_name)";
  76. }
  77. }