Feeds:
Posts
Comments

Posts Tagged ‘perl’

So much for good intentions. I get myself all geared up to
the problem I need to solve today? Well, I want to find out about how emacs networking works.

So first, I need a simple server to play with. Now normally when I think server I automatically think Apache but this time I want something a bit more basic. And if I was thinking enterprise1 I might reach for C++/ACE. However, for something basic, Perl is ideal.

I’ve just upgraded to Ubuntu 9.04 on this box and Perl is unused so let’s see if it has what I need.

06.52 Ubuntu finishes booting

I waste a few minutes on the internet.

06.57 I start Emacs

and remind myself just how gorgeous emacs-23 looks.

06.59 I check for the Net::Server package
$ perldoc Net::Server
You need to install the perl-doc package to use this program.
$ sudo apt-get install perl-doc

$ perldoc Net::Server
No documentation found for "Net::Server".

It is not installed. I could install it using apt (it is called libnet-server-perl) but I’ve got in the habit of using Perl’s CPAN module which provides package management facilities too. The advantage is that it is somewhat consistent across platforms.

$ sudo perl -MCPAN -e shell

cpan[1]> install YAML
cpan[2]> install CPAN
cpan[3]> reload CPAN
cpan[4]> install Bundle::CPAN

The CPAN bundle installs quite a bit so I go for breakfast.

07.15 Back from breakfast
cpan[5]> install Net::Server

I took this code pretty much straight from perldoc Net::Server.

#!/usr/bin/perl

use strict;
use warnings;

package SimpleServer;

use base qw(Net::Server);

sub process_request
{
    while (<STDIN>) {
        s/\r?\n$//;
        print STDERR "Received [$_]\n";
        last if /quit/i;
    }
}

SimpleServer->run(port => 8080);

I tested it using telnet localhost 8080 to confirm it does what I need.

07.20 All done

Presumably Python and Ruby have similar incantations that will get a server up and running quickly.

And unfortunately at this point I have to go to work. But later on, I can begin experimenting with emacs networking.


1. i.e. some thing that grows humongous over a period of two years and then no-one wants to work with it anymore.

Read Full Post »

Pretty Printing XML

During the course of a typical workday, in order to track down a problem, I often need to look at logfiles containing xml. The xml is usually poorly formatted and sometimes it is all on one line, making it very difficult to read. What would be ideal would be if I could extract the xml I am interested in into a buffer and pretty-print it with very little effort. The steps would be something like:

  1. create a new buffer called *xml* in another window (C-x 4 b)
  2. delete anything that exists in that buffer already
  3. pretty print the xml into the new buffer

Did I gloss over step 3? That sounds pretty complicated right? Well, I can call a simple perl script from emacs. I’m pretty pragmatic and I don’t feel the need to code absolutely everything in emacs-lisp.

#!/usr/bin/perl

use XML::Twig;
use XML::Parser;

my $xml = XML::Twig->new(pretty_print => 'indented');

if ($ARGV[0]) {
    $xml->parse($ARGV[0]);
} else {
    $xml->parse(\*STDIN);
}

$xml->print();
(defun xml-pretty-print-region (start end)
  (interactive "r")
  (let ((b (get-buffer-create "*xml*")))
    (switch-to-buffer-other-window b)
    (xml-mode)
    (erase-buffer)
    (other-window -1)
    (goto-char end)
    (let ((e (point-marker)))
      (join-broken-lines start end)
      (call-process-region start e "xml_pretty_print.pl" nil b))))

Actually, sgml-mode (xml-mode is just an alias) has a method called sgml-pretty-print but firstly I prefer the output from XML::Twig and secondly it is nice to see how easy emacs makes it to call out to an external process and return the results. Anyone without perl installed might prefer to replace the external call with a call to (sgml-pretty-print ...).

(defun xml-pretty-print-region (start end)
  (interactive "r")
  (let ((cb (current-buffer))
        (buf (get-buffer-create "*xml*")))
    (set-buffer buf)
    (erase-buffer)
    (set-buffer cb)
    (copy-to-buffer buf start end)

    (switch-to-buffer-other-window buf)
    (xml-mode)
    (join-broken-lines (point-min) (point-max))
    (sgml-pretty-print (point-min) (point-max))
    (other-window -1)))

What is that call to (join-broken-lines ...)? When I cut and paste from putty it breaks lines at the width of my window.

<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0"><xsl:output
 method="html"/><xsl:template match="/"><H2>Customer Listing (in Alternating ro
w colors)</H2><table border="1"><xsl:for-each select="/customers/customer"><tr>
<xsl:choose><xsl:when test="position() mod 2 = 1"><xsl:attribute name="class">c
lsOdd</xsl:attribute></xsl:when><xsl:otherwise><xsl:attribute name="class">clsE
ven</xsl:attribute></xsl:otherwise></xsl:choose><xsl:for-each select="@*"><td><
xsl:value-of select="."/></td></xsl:for-each></tr></xsl:for-each></table><H3>To
tal Customers<xsl:value-of select="count(customers/customer)"/></H3></xsl:templ
ate></xsl:stylesheet>

This invalidates the xml so I need to fix this before passing the result to the xml parser.

(defconst cr (string ?\n))
(defconst *broken-line-regex* cr)

(defun join-broken-lines (start end)
  (interactive "r")
  (goto-char start)
  (while (re-search-forward *broken-line-regex* end t)
    (replace-match "" nil nil)))

This is the output from the version which calls (sgml-pretty-print ...)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0">
  <xsl:output method="html"/>
  <xsl:template match="/">
    <H2>Customer Listing (in Alternating row colors)
    </H2>
    <table border="1">
      <xsl:for-each select="/customers/customer">
        <tr>
          <xsl:choose>
            <xsl:when test="position() mod 2 = 1">
              <xsl:attribute name="class">clsOdd
              </xsl:attribute>
            </xsl:when>
            <xsl:otherwise>
              <xsl:attribute name="class">clsEven
              </xsl:attribute>
            </xsl:otherwise>
          </xsl:choose>
          <xsl:for-each select="@*">
            <td>
              <xsl:value-of select="."/>
            </td>
          </xsl:for-each>
        </tr>
      </xsl:for-each>
    </table>
    <H3>Total Customers
      <xsl:value-of select="count(customers/customer)"/>
    </H3>
  </xsl:template>
</xsl:stylesheet>

We probably want a function to handle the common case is where all the xml is on one line with some junk before the xml and some junk afterwards. E.g.

asdflkjnalkjnasdf <?xml version="1.0" encoding="UTF-8"?><a><b>c</b></a> xskldfgjnskldf
(defun xml-pretty-print-current ()
  (interactive)
  (save-excursion
    (end-of-line nil)
    (re-search-backward ">" 1)
    (let ((e (+ 1 (point))))
      (beginning-of-line nil)
      (re-search-forward "<?xml[^>]*>" e)
      (xml-pretty-print-region (point) e))))

And, er, I guess that’s all I’ve got to say about that.

Read Full Post »

« Newer Posts

Follow

Get every new post delivered to your Inbox.