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 )