286 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			286 lines
		
	
	
	
		
			7.1 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable file
		
	
	
	
	
#! /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 <groff-bernd.warken-72@web.de>.
 | 
						|
 | 
						|
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 <http://www.gnu.org/licenses/gpl-2.0.html>.
 | 
						|
 | 
						|
########################################################################
 | 
						|
 | 
						|
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:
 |