Perl I never write: snippets
Tags: perl, emacs, ide, snippets
Published: 2019-06-12 19:03:58

---
title: Perl I never write: snippets
published: true
description: Use snippets to avoid typing common, fiddly source code
tags: perl,emacs,ide,snippets
---

Emacs has this cool package `yasnippet`, which is a simple template expansion system.

So for instance when I'm declaring a method, I can type a simple trigger word: `argsm` (args for a method), hit `<Tab>` and the trigger word expands into the corresponding template (| is the cursor (or "point" in Emacs parlance)):

```perl
    my $self = shift;
    my (|) = @_;
```

This is obviously something that needs to be done *all. the. time*.

In this case I also use it when there are no method arguments, because it turns out it's way less hassle to type `argsm<Tab>` and delete the current line than to type `my $self = shift;`.

Snippets are a very useful mechanism for reducing the *friction* of doing common, slightly fiddly things. Reducing friction is important, because it allows you to keep your mind on what you *actually* want to accomplish, rather than the rote typing of syntax (and shifty characters like `()$@_`).

`yasnippet` is a good snippets package for Emacs; I'm sure your editor has a similar feature/plugin available.


# Yasnippets

Here's the actual snippet file `snippets/perl-mode/argsm`:

```perl
#name : methods args -- my $self = shift; my () = @_;
# --
my \$self = shift;
my ($0) = @_;
```

As part of the snippet expansion, you can hit `<tab>` to move between specific places (tab stops, like `$1`, `$2`, etc.) in the snippet, usually to type custom text there. `$0` is the final tab stop where the expansion process ends and you can continue editing.

The tab stop text can also have a default value which can be a string, or come from calling a function, or be mirrored from what you type elsewhere in the snippet.

This is all quite powerful, especially if you add in some simple elisp functions of your own. We'll see some of these things in action below.

There's a *lot* more to `yasnippet`, like different trigger mechanisms,  dropdown menus, completion support, etc. Start small and simple, and take it from there. 

You can find more `yasnippet` info and installation instructions at the end of this article.


# Perl snippets

`yasnippet` comes with a lot of existing little snippets for various languages and modes.

I don't use most of the canned Perl snippets however: they are mostly regular Perl keyword constructs that aren't a chore to type in the first place. Instead, here are some of the ones I've defined myself, in order of actual usage and utility:


## Argument unpacking

I use these right after having typed the method skeleton (with `autopair-mode` for the braces):

```perl
sub basket_total_price {
    |
}
```

### argsm

```perl
#name : methods args -- my $self = shift; my () = @_;
# --
my \$self = shift;
my ($0) = @_;
```

### args

```perl
#name : args my () = @_;
# --
my ($0) = @_;
```

But, wouldn't it be more convenient to include the whole sub skeleton in the snippet, curly braces and all?

Sure, you could do that. But I find that it pays off to try to hook the automated parts into the flow only where the friction starts to increase, and leave the low friction bits alone. So you type along, and just when it gets annoying, you switch over to inserting a snippet instead.

In addition, the shorter snippet can be added when editing an already existing sub. This makes the smaller, more targeted piece of text useful in more situations.


## Method/sub POD

Writing POD for *method signatures* (i.e. the sub name, arguments and return value) is a very good habit: spending more time thinking about what's going on is usually a good thing.

In some respects doing this is like a half-way house to TDD (ok, maybe fifth-way house), because writing things down makes you think through what the method does, what parameters it takes and what it returns, any special cases that may apply and how things can go wrong. Basically imagining how it should and could be called, while not going all the way to actually writing code to do that.


### podx

Invoke this just above a sub declaration to expand into boilerplate POD text:

```perl
#name : pod above sub -- =head2 name() :
# --
=head2 ${1:`(my-yas-perl-next-sub-name)`}($2) :$3

$0

=cut
```

This snippet is a good demonstration of the different tabstops `$1`, `$2`, `$3` and finally `$0`. The first stop is the pre-filled-in subroutine name, and when I hit `<tab>` the point jumps to the next place where I can continue to enter the parameters, etc.

The default value for the sub name is where things gets interesting. The sub name comes from calling the elisp function `my-yas-perl-next-sub-name`, which in this case is a simple regex match:

```common_lisp
(defun my-yas-perl-next-sub-name ()
  (interactive)
  (save-excursion
    (if (search-forward-regexp "sub +\\([a-z0-9_]+\\)" nil t)
        (match-string 1)
      "")))
```

So having this:

```perl
podx|
sub get_workflow_type_row {
```

turns into this:

```perl
=head2 |get_workflow_type_row() :



=cut

sub get_workflow_type_row {
```

and finally this, after documenting the method:

```perl
=head2 get_workflow_type_row($workflow_type) : $workflow_type_row | undef

Return a $workflow_type_row for the $workflow_type
(e.g. "multi_role"), or undef if it doesn't exist (either because
it's invalid or because the company has no Workflows with that
$workflow_type).

=cut
```


## Moo/Moose lazy attribute

These are basic Moo/Moose attributes with a lazy builder, easily the most common style of attribute in our code. And when it's not, the inserted snippet text is easy to adjust.

Using the trigger words `haslm` (Moo) and `hasls` (Moose) for this also has the benefit of getting the syntax right, since that is annoyingly different and I can never remember which is which.

### haslm

```perl
#name : has => () Moo attribute with lazy builder
# --
has ${1:name} => ( is => "lazy" );
sub _build_$1 {
    my $self = shift;
    $0
}
```


### hasls

```perl
#name : has => () Moose attribute with lazy builder
# --
has ${1:name} => ( is => "ro", lazy_build => 1 );
sub _build_$1 {
    my $self = shift;
    $0
}
```

If you look at the part where it says `${1:name}` you'll see another cool `yasnippet` feature: *mirroring*. While we type the attribute name, the builder sub name is updated in real time:

```perl
has csv_writer| => ( is => "lazy" );
sub _build_csv_writer {
    my $self = shift;

}
```



## Other Moo/Moose attributes

For completeness, here are some other less commonly used attribute declarations.


### hasr

```perl
#name : has => () Moose/Moo attribute with required => 1
# --
has ${1:name} => ( is => "ro", required => 1 );
```


### has

```perl
#name : has => () Simple Moose/Moo attribute
# --
has ${1:name} => ( is => "ro" );
```


### hasbm

```perl
#name : has => () Moo attribute with lazy "builder" subref
# --
has ${1:name} => ( is => "lazy", builder => sub { $0 } );
```


## POD fragments

Not as commonly used, but still somewhat useful: POD `=head1` sections.

### podn

```perl
#name : name with current package -- =head1 NAME
# --
=head1 NAME

${1:`(ps/current-package-name)`} -- $0

=head1 DESCRIPTION

=cut
```

This one is interesting in that it reuses the elisp function from [Devel::PerlySense -- Copy Package Name](https://metacpan.org/pod/Devel::PerlySense#Edit-Copy-Package-Name) to get the string with the current package name, which is what we want for the `=head1 NAME` POD section.

Let's stop typing things that are already known!


### poda

```perl
#name : pod =head1 ATTRIBUTES
# --
=head1 ATTRIBUTES
$0
=cut
```


### podm

```perl
#name : pod =head1 METHODS
# --
=head1 METHODS
$0
=cut
```


### podcm

```perl
#name : pod =head1 CLASS METHODS
# --
=head1 CLASS METHODS
$0
=cut
```


### pods

```perl
#name : pod =head1 SUBROUTINES
# --
=head1 SUBROUTINES
$0
=cut
```



# Start using `yasnippet`

Read more about `yasnippet` here:

* [Nice introduction](https://cupfullofcode.com/blog/2013/02/26/snippet-expansion-with-yasnippet/index.html)
* [Docs](http://joaotavora.github.io/yasnippet/)
* [GitHub repo](https://github.com/joaotavora/yasnippet)
* [EmacsWiki](https://www.emacswiki.org/emacs/Yasnippet)

Install it from [ELPA](https://elpa.gnu.org/packages/yasnippet.html).




# \_\_END\_\_

That's it!

After reading this I'm sure you've got some great ideas for snippets of your own, or maybe you already have an existing library of useful snippets?

Please share in the comments! <small>(or over at [reddit.com/r/perl](https://www.reddit.com/r/perl/comments/c045pj/perl_i_never_write_snippets/))</small>