diff --git a/bin/ghighlight b/bin/ghighlight new file mode 100755 index 0000000..d3903d7 --- /dev/null +++ b/bin/ghighlight @@ -0,0 +1,286 @@ +#! /usr/bin/env perl + +# ghighlight - A simple preprocessor for adding code highlighting in a groff file + +# Copyright (C) 2014-2018 Free Software Foundation, Inc. + +# Written by Bernd Warken . + +my $version = '0.9.0'; + +# This file is part of 'ghighlight', which is part of 'groff'. + +# 'groff' is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. + +# 'groff' is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. + +# You can find a copy of the GNU General Public License in the internet +# at . + +######################################################################## + +use strict; +use warnings; +#use diagnostics; + +# current working directory +use Cwd; + +# $Bin is the directory where this script is located +use FindBin; + +# open3 for a bidirectional communication with a child process +use IPC::Open3; + + +######################################################################## +# system variables and exported variables +######################################################################## + +$\ = "\n"; # final part for print command + +######################################################################## +# read-only variables with double-@ construct +######################################################################## + +our $File_split_env_sh; +our $File_version_sh; +our $Groff_Version; + +my $before_make; # script before run of 'make' +{ + my $at = '@'; + $before_make = 1 if '@VERSION@' eq "${at}VERSION${at}"; +} + +my %at_at; +my $file_perl_test_pl; +my $groffer_libdir; + +if ($before_make) { + my $highlight_source_dir = $FindBin::Bin; + $at_at{'BINDIR'} = $highlight_source_dir; + $at_at{'G'} = ''; +} else { + $at_at{'BINDIR'} = '@BINDIR@'; + $at_at{'G'} = '@g@'; +} + + +######################################################################## +# options +######################################################################## + +foreach (@ARGV) { + if ( /^(-h|--h|--he|--hel|--help)$/ ) { + print q(Usage for the 'ghighlight' program:); + print 'ghighlight [-] [--] [filespec...] normal file name arguments'; + print 'ghighlight [-h|--help] gives usage information'; + print 'ghighlight [-v|--version] displays the version number'; + print q(This program is a 'groff' preprocessor that handles highlighting source code ) . + q(parts in 'roff' files.); + exit; + } elsif ( /^(-v|--v|--ve|--ver|--vers|--versi|--versio|--version)$/ ) { + print q('ghighlight' version ) . $version; + exit; + } +} + +my $macros = "groff_mm"; +if ( $ENV{'GHLENABLECOLOR'} ) { + $macros = "groff_mm_color"; +} +######################################################################## +# input +######################################################################## + +my $source_mode = 0; + +my @lines = (); + + +sub getTroffLine { + my ($opt) = @_; + if ($opt =~ /^ps=([0-9]+)/) {".ps $1"} + elsif ($opt =~ /^vs=(\S+)/) {".vs $1"} + else { print STDERR "didn't recognised '$opt'"; ""} +} + +sub getTroffLineOpposite { + my ($opt) = @_; + if ($opt =~ /^ps=/) {".ps"} + elsif ($opt =~ /^vs=/) {".vs"} + else { print STDERR "didn't recognised '$opt'"; ""} +} + +# language for codeblocks +my $lang = ''; +my @options = (); +foreach (<>) { + chomp; + s/\s+$//; + my $line = $_; + my $is_dot_Source = $line =~ /^[.']\s*(``|SOURCE)(|\s+.*)$/; + + unless ( $is_dot_Source ) { # not a '.SOURCE' line + if ( $source_mode ) { # is running in SOURCE mode + push @lines, $line; + } else { # normal line, not SOURCE-related + print $line; + } + next; + } + + + ########## + # now the line is a '.SOURCE' line + + my $args = $line; + $args =~ s/\s+$//; # remove final spaces + $args =~ s/^[.']\s*(``|SOURCE)\s*//; # omit .source part, leave the arguments + + my @args = split /\s+/, $args; + + ########## + # start SOURCE mode + + $lang = $args[0] if ( @args > 0 && $args[0] ne 'stop' ); + + if ( @args > 0 && $args[0] ne 'stop' ) { + # For '.``' no args or first arg 'start' means opening 'SOURCE' mode. + # Everything else means an ending command. + + shift @args; + @options = @args; + + if ( $source_mode ) { + # '.SOURCE' was started twice, ignore + print STDERR q('.``' starter was run several times); + next; + } else { # new SOURCE start + $source_mode = 1; + @lines = (); + next; + } + } + + ########## + # now the line must be a SOURCE ending line (stop) + + unless ( $source_mode ) { + print STDERR 'ghighlight.pl: there was a SOURCE ending without being in ' . + 'SOURCE mode:'; + print STDERR ' ' . $line; + next; + } + + $source_mode = 0; # 'SOURCE' stop calling is correct + + my $shopts = $ENV{"SHOPTS"} || ""; + + ########## + # Run source-highlight on lines + # Check if language was specified + my $cmdline = "source-highlight -f $macros $shopts --output STDOUT"; + if ($lang ne '') { + $cmdline .= " -s $lang"; + } + + # Start `source-highlight` + my $pid = open3(my $child_in, my $child_out, my $child_err, $cmdline) + or die "open3() failed $!"; + + # Provide source code to `source-highlight` in its standard input + print $child_in $_ for @lines; + close $child_in; + + if (my $v = $ENV{"GH_INTRO"}) { + print for split /;/, $v; + } + + for (@options) { + my $l = getTroffLine $_; + print $l if ($l ne ""); + } + + # Print `source-highlight` output + while (<$child_out>) { + chomp; + print; + } + close $child_out; + + for (reverse @options) { + my $l = getTroffLineOpposite $_; + print $l if ($l ne ""); + } + + if (my $v = $ENV{"GH_OUTRO"}) { + print for split /;/, $v; + } + + my @print_res = (1); + + # Start argument processing + + # remove 'stop' arg if exists + # shift @args if ( $args[0] eq 'stop' ); + + # if ( @args == 0 ) { + # # no args for saving, so @print_res doesn't matter + # next; + # } + # my @var_names = (); + # my @mode_names = (); + + # my $mode = '.ds'; + # for ( @args ) { + # if ( /^\.?ds$/ ) { + # $mode = '.ds'; + # next; + # } + # if ( /^\.?nr$/ ) { + # $mode = '.nr'; + # next; + # } + # push @mode_names, $mode; + # push @var_names, $_; + # } + + # my $n_vars = @var_names; + + # if ( $n_vars < $n_res ) { + # print STDERR 'ghighlight: not enough variables for Python part: ' . + # $n_vars . ' variables for ' . $n_res . ' output lines.'; + # } elsif ( $n_vars > $n_res ) { + # print STDERR 'ghighlight: too many variablenames for Python part: ' . + # $n_vars . ' variables for ' . $n_res . ' output lines.'; + # } + # if ( $n_vars < $n_res ) { + # print STDERR 'ghighlight: not enough variables for Python part: ' . + # $n_vars . ' variables for ' . $n_res . ' output lines.'; + # } + + # my $n_min = $n_res; + # $n_min = $n_vars if ( $n_vars < $n_res ); + # exit unless ( $n_min ); + # $n_min -= 1; # for starting with 0 + + # for my $i ( 0..$n_min ) { + # my $value = $print_res[$i]; + # chomp $value; + # print $mode_names[$i] . ' ' . $var_names[$i] . ' ' . $value; + # } +} + + +1; +# Local Variables: +# mode: CPerl +# End: diff --git a/bin/utf8-to-ms.sh b/bin/utf8-to-ms.sh new file mode 100755 index 0000000..70337db --- /dev/null +++ b/bin/utf8-to-ms.sh @@ -0,0 +1,147 @@ +#!/bin/sh + +# This program isn't by any mean complete. +# Most of text markers, accents and ligatures are handled. +# However, nothing else currently is. +# Please, do provide more translations. + +# Convert input into hexadecimal and a single byte per line. +to_hex_one_column() xxd -p -c 1 + +# Reverse hexadecimal to original value. +from_hex() xxd -p -r + +regroup_lines() awk ' + BEGIN { + line_start=1 + } + + { + if (line_start == 1) + line = $1; + else + line = line " " $1; + + line_start = 0; + if ($1 == "0a") { + print line; + line_start = 1 + } + } + + END { + if (line_start == 0) + print line + } + ' + +accents() sed \ + -e "s/c3 81/5c 5b 27 41 5d/g"\ + -e "s/c3 89/5c 5b 27 45 5d/g"\ + -e "s/c3 8d/5c 5b 27 49 5d/g"\ + -e "s/c3 93/5c 5b 27 4f 5d/g"\ + -e "s/c3 9a/5c 5b 27 55 5d/g"\ + -e "s/c3 9d/5c 5b 27 59 5d/g"\ + -e "s/c3 a1/5c 5b 27 61 5d/g"\ + -e "s/c3 a9/5c 5b 27 65 5d/g"\ + -e "s/c3 ad/5c 5b 27 69 5d/g"\ + -e "s/c3 b3/5c 5b 27 6f 5d/g"\ + -e "s/c3 ba/5c 5b 27 75 5d/g"\ + -e "s/c3 bd/5c 5b 27 79 5d/g"\ + -e "s/c3 84/5c 5b 3a 41 5d/g"\ + -e "s/c3 8b/5c 5b 3a 45 5d/g"\ + -e "s/c3 8f/5c 5b 3a 49 5d/g"\ + -e "s/c3 96/5c 5b 3a 4f 5d/g"\ + -e "s/c3 9c/5c 5b 3a 55 5d/g"\ + -e "s/c3 a4/5c 5b 3a 61 5d/g"\ + -e "s/c3 ab/5c 5b 3a 65 5d/g"\ + -e "s/c3 af/5c 5b 3a 69 5d/g"\ + -e "s/c3 b6/5c 5b 3a 6f 5d/g"\ + -e "s/c3 bc/5c 5b 3a 75 5d/g"\ + -e "s/c3 bf/5c 5b 3a 79 5d/g"\ + -e "s/c3 82/5c 5b 5e 41 5d/g"\ + -e "s/c3 8a/5c 5b 5e 45 5d/g"\ + -e "s/c3 8e/5c 5b 5e 49 5d/g"\ + -e "s/c3 94/5c 5b 5e 4f 5d/g"\ + -e "s/c3 9b/5c 5b 5e 55 5d/g"\ + -e "s/c3 a2/5c 5b 5e 61 5d/g"\ + -e "s/c3 aa/5c 5b 5e 65 5d/g"\ + -e "s/c3 ae/5c 5b 5e 69 5d/g"\ + -e "s/c3 b4/5c 5b 5e 6f 5d/g"\ + -e "s/c3 bb/5c 5b 5e 75 5d/g"\ + -e "s/c3 80/5c 5b 60 41 5d/g"\ + -e "s/c3 88/5c 5b 60 45 5d/g"\ + -e "s/c3 8c/5c 5b 60 49 5d/g"\ + -e "s/c3 92/5c 5b 60 4f 5d/g"\ + -e "s/c3 99/5c 5b 60 55 5d/g"\ + -e "s/c3 a0/5c 5b 60 61 5d/g"\ + -e "s/c3 a8/5c 5b 60 65 5d/g"\ + -e "s/c3 ac/5c 5b 60 69 5d/g"\ + -e "s/c3 b2/5c 5b 60 6f 5d/g"\ + -e "s/c3 b9/5c 5b 60 75 5d/g"\ + -e "s/c3 83/5c 5b 7e 41 5d/g"\ + -e "s/c3 91/5c 5b 7e 4e 5d/g"\ + -e "s/c3 95/5c 5b 7e 4f 5d/g"\ + -e "s/c3 a3/5c 5b 7e 61 5d/g"\ + -e "s/c3 b1/5c 5b 7e 6e 5d/g"\ + -e "s/c3 b5/5c 5b 7e 6f 5d/g"\ + -e "s/c3 87/5c 5b 2c 43 5d/g"\ + -e "s/c3 a7/5c 5b 2c 63 5d/g"\ + -e "s/c3 85/5c 5b 6f 41 5d/g"\ + -e "s/c3 a5/5c 5b 6f 61 5d/g"\ + -e "s/c5 b8/5c 5b 3a 59 5d/g"\ + -e "s/c5 a0/5c 5b 76 53 5d/g"\ + -e "s/c5 a1/5c 5b 76 73 5d/g"\ + -e "s/c5 bd/5c 5b 76 5a 5d/g"\ + -e "s/c5 be/5c 5b 76 7a 5d/g" + +# Ligatures. +ligatures() sed \ + -e "s/ef ac 80/5c 5b 66 66 5d/g"\ + -e "s/ef ac 81/5c 5b 66 69 5d/g"\ + -e "s/ef ac 82/5c 5b 66 6c 5d/g"\ + -e "s/ef ac 83/5c 5b 46 69 5d/g"\ + -e "s/ef ac 84/5c 5b 46 6c 5d/g"\ + -e "s/c5 81/5c 5b 2f 4c 5d/g"\ + -e "s/c5 82/5c 5b 2f 6c 5d/g"\ + -e "s/c3 98/5c 5b 2f 4f 5d/g"\ + -e "s/c3 b8/5c 5b 2f 6f 5d/g"\ + -e "s/c3 86/5c 5b 41 45 5d/g"\ + -e "s/c3 a6/5c 5b 61 65 5d/g"\ + -e "s/c5 92/5c 5b 4f 45 5d/g"\ + -e "s/c5 93/5c 5b 6f 65 5d/g"\ + -e "s/c4 b2/5c 5b 49 4a 5d/g"\ + -e "s/c4 b3/5c 5b 69 6a 5d/g"\ + -e "s/c4 b1/5c 5b 2e 69 5d/g"\ + -e "s/c8 b7/5c 5b 2e 6a 5d/g" + +# Text markers. +text_markers() sed \ + -e "s/e2 97 8b/5c 5b 63 69 5d/g"\ + -e "s/e2 80 a2/5c 5b 62 75 5d/g"\ + -e "s/e2 80 a1/5c 5b 64 64 5d/g"\ + -e "s/e2 80 a0/5c 5b 64 67 5d/g"\ + -e "s/e2 97 8a/5c 5b 6c 7a 5d/g"\ + -e "s/e2 96 a1/5c 5b 73 71 5d/g"\ + -e "s/c2 b6/5c 5b 70 73 5d/g"\ + -e "s/c2 a7/5c 5b 73 63 5d/g"\ + -e "s/e2 98 9c/5c 5b 6c 68 5d/g"\ + -e "s/e2 98 9e/5c 5b 72 68 5d/g"\ + -e "s/e2 86 b5/5c 5b 43 52 5d/g"\ + -e "s/e2 9c 93/5c 5b 4f 4b 5d/g" + +# These markers shouldn't be automatically translated in ms macros. +# @ "s/40/5c 5b 61 74 5d/g" +# # "s/23/5c 5b 73 68 5d/g" + +# Legal symbols. +legal_symbols() sed \ + -e "s/c2 a9/5c 5b 63 6f 5d/g"\ + -e "s/c2 ae/5c 5b 72 67 5d/g"\ + -e "s/e2 84 a2/5c 5b 74 6d 5d/g" + +hexutf8_to_hexms() { + text_markers | accents | ligatures | legal_symbols +} + +to_hex_one_column | regroup_lines | hexutf8_to_hexms | from_hex