Syntax-Highlight-WithEmacs

 view release on metacpan or  search on metacpan

lib/Syntax/Highlight/WithEmacs.pm  view on Meta::CPAN


whether to use the emacs client. Defaults to true

=item server_name

the name of the emacs server to which the client will
connect. Defaults to "EmacsHtmlize(pid)_(counter)". You might want to
set this to the empty string to make it connect to your default
server. See also I<kill_server> below.

=item start_server

whether to start the emacs server on object creation time. Defaults to true

=item kill_server

whether to kill the emacs server during object destroy. Defaults to
true. You should definitely disable this if you have it connect to
your default server

=item ansi_opts

a hashref of additional options for the ansifier. see the
C<ansify_string> method.

=back

=cut

    my $servercnt = 0;
    has mode	     => (is => 'rw', default => 'font');
    has htmlize_generate_hyperlinks
	             => (is => 'rw', default => 0);
    has use_client   => (is => 'ro', default => 1);
    has server_name  => (is => 'ro', default => sub { ++$servercnt; "EmacsHtmlize$$\_$servercnt" });
    has start_server => (is => 'ro', default => 1, reader => '_start_server');
    has kill_server  => (is => 'ro', default => 1, reader => '_kill_server');
    has term_spec    => (is => 'ro', default => 'xterm-256color');
    has emacs_args   => (is => 'rw', default => sub{[]});
    has emacs_cmd    => (is => 'ro', default => 'emacs');
    has client_cmd   => (is => 'ro', default => 'emacsclient');
    has ansi_opts    => (is => 'rw', default => sub{+{}});

    method BUILD {
	$self->{lx} = XML::LibXML->new;
	$self->{lx}->recover(2);
	lock_ref_keys_plus($self,
			   # client module:
			   'made_server',
			   # ansify module:
			   'ansify_css', 'ansify_ccss', 'ansify_opts', '_ansify_italic'
			  );
	$self->start_server if $self->_start_server && $self->use_client;
    }

    method start_server {
	return if $self->{made_server};
	my ($cout, $cin, $cerr);
	my @cmd = ($self->emacs_cmd, @{$self->emacs_args},
		   '--daemon' . ($self->server_name ? '='.$self->server_name : ''));
	local $ENV{HOME} = (getpwuid $<)[7] unless $ENV{HOME};
	local $ENV{TERM} = $self->term_spec;
	run \@cmd, \$cin, \$cout, \$cerr;
	$self->{made_server} = 1;
    }

    method _client_cmd_args {
	($self->client_cmd, -a => '', ($self->server_name ? (-s => $self->server_name) : ()))
    }

    method run_htmlize($in, $out) {
	my $mode = $self->mode;
	for ($in, $out) {
	    unless (defined) { $_ = ''; next; }
	    s/(["\\])/\\$1/g;
	    $_ = qq{"$_"};
	}
	my $kill_command = $self->use_client ? '(delete-frame (selected-frame) t)' : '(kill-emacs)';
	my @cmd = $self->use_client ? $self->_client_cmd_args : $self->emacs_cmd;
	my @cmd_args = @{$self->emacs_args};
	@cmd_args = grep { !/^-q$/i } @cmd_args if $self->use_client;
	my $hyper = $self->htmlize_generate_hyperlinks ? 't' : 'nil';
	my @args = (@cmd, '-nw', @cmd_args,
		    -eval => qq((ignore-errors (require 'htmlize) (setq htmlize-generate-hyperlinks $hyper) (setq htmlize-output-type "$mode") (htmlize-file $in $out))),
		    -eval => $kill_command);
	local $ENV{HOME} = (getpwuid $<)[7] unless $ENV{HOME};
	local $ENV{TERM} = $self->term_spec;
	my ($tin, $tout, $err);
	run \@args, '<pty<', \$tin, '>pty>', \$tout, '2>', \$err;
	$self->{made_server} = $self->use_client;
    }

=head2 htmlize_file

run htmlize on a given filename. The major-mode emacs uses to highlight
it will be chosen by your own emacs configuration file, which is
usually by the file extension.

The following parameters are expected:

=over

=item I<$file>

input file to run htmlize on

=item I<$out>

output file to save html in. Can be omitted, in which case the output
file will be the input file with C<.html> appended

=back

this method does not return anything. You can process the generated
HTML file with any tool you like.

=cut

    method htmlize_file($file, $out = undef) {
	$self->run_htmlize($file, $out);
    }

=head2 htmlize_string

run htmlize on the given string. The following parameters are expected:

=over

=item I<$string>

a string with code to highlight.

=item I<$mode>

extension of the temporary file created. As most emacs configurations
choose major mode by extension, this will directly influence the file
mode used for highlighting.

=back

Note: the file name passed to htmlize matches
C<^EmacsHtmlize.*\.$mode$>. You can use this to configure mode rules
based on filename in your .gnu-emacs file.

This method B<returns> the highlighted code as a L<XML::LibXML::Node> and
the accompanying stylesheet as a L<CSS::Tiny> object. In scalar

lib/Syntax/Highlight/WithEmacs.pm  view on Meta::CPAN

    $hl->marked_string(q{my $x = 42;}, 'pl');
    # ==> result is like follows
    [ [ 'keyword',       'my'     ],
      [ '',              ' '      ],
      [ 'variable-name', '$x'     ],
      [ '',              ' = 42;' ] ];

note, it is B<not> compatible to Text::VimColor!

=cut

    method _dump_node_marked($node) {
	my @ret;
	while ($node) {
	    my (@class, $text);
	    my $tnode = $node;
	    while ($tnode->nodeType == XML_ELEMENT_NODE) {
		push @class, $tnode->getAttribute('class');
		$tnode = $tnode->firstChild;
	    }

	    if ($node->nodeType == XML_TEXT_NODE) {
		$text = $node->data;
		next unless length $text;
	    }
	    else {
		$text = $node->textContent;
	    }

	    push @ret, [(join ' ', grep { length } @class) => $text];
	}
	continue {
	    $node = $node->nextSibling;
	}
	\@ret
    }
    method marked_string($string, $mode) {
	local $self->{htmlize_generate_hyperlinks} = 0;
	local $self->{mode} = 'css';

	my $html_node = $self->htmlize_string($string, $mode);
	return unless $html_node;

    	$self->_dump_node_marked($html_node->firstChild);
    }

=head2 start_server

manually start the emacs server

=head2 kill_server

manually send the kill command to the emacs server.

=cut

    method kill_server {
	my @cmd = ($self->_client_cmd_args,
		   -eval => '(kill-emacs)');
	my ($cout, $cin, $cerr);
	local $ENV{HOME} = (getpwuid $<)[7] unless $ENV{HOME};
	local $ENV{TERM} = $self->term_spec;
	run \@cmd, \$cin, \$cout, \$cerr;
	$self->{made_server} = 0;
    }

    method DEMOLISH {
	$self->kill_server if $self->_kill_server && $self->{made_server}
    }
};

package Convert::Color::XTerm8 {
    my $base = 'Convert::Color::XTerm';
    if ($base->can('register_color_space')) {
	our @ISA = $base;
	__PACKAGE__->register_color_space('xterm_8');
	__PACKAGE__->register_palette(
	    enumerate_once => sub {
		map { __PACKAGE__->new($_) } 0..7
	    });
    }
};

package Convert::Color::XTerm16 {
    my $base = 'Convert::Color::XTerm';
    if ($base->can('register_color_space')) {
	our @ISA = $base;
	__PACKAGE__->register_color_space('xterm_16');
	__PACKAGE__->register_palette(
	    enumerate_once => sub {
		map { __PACKAGE__->new($_) } 0..15
	    });
    }
};

=head1 SEE ALSO

L<Text::EmacsColor>

This module wants to do the same but it does not work properly when
not using emacsclient, and it fails to include the colour definitions
because Emacs does not load those in batch mode.

Other Syntax::Highlight::* modules on CPAN.

L<Text::VimColor> which does the same using VIM.

=head1 AUTHOR

Ailin Nemui E<lt>ailin at devio dot usE<gt>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2013 by Ailin Nemui.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut

    1



( run in 2.112 seconds using v1.01-cache-2.11-cpan-df04353d9ac )