NAME

Setup::Text::Snippet::WithID - Setup text snippet (with comment containing ID) in file

VERSION

version 0.04

SYNOPSIS

use Setup::Text::Snippet::WithID 'setup_snippet_with_id';

my $res = setup_snippet_with_id
    file    => '/etc/default/rsync',
    id      => 'enable',
    content => 'RSYNC_ENABLE=1',
    good_pattern    => qr/^RSYNC_ENABLE\s*=\s*1/m,
    replace_pattern => qr/^RSYNC_ENABLE\s*=.+/m;
die unless $res->[0] == 200;

Resulting /etc/default/rsync:

RSYNC_ENABLE=1 # SNIPPET id=enable

The above code's goal is to enable rsync daemon by default. If /etc/default/rsync already contains the "good pattern" (qr/^RSYNC_ENABLE\s*=\s*1/m), it will not be inserted with snippet. Snippet will replace text specified in replace_pattern (or if replace_pattern is not defined, snippet will be appended to the end of file [or beginning of file if top_style=>1]).

Example of multi-line snippet, in INI-style comment instead of shell-style:

; BEGIN SNIPPET id=default
register_globals=On
extension=mysql.so
extension=gd.so
memory_limit=256M
post_max_size=64M
upload_max_filesize=64M
browscap=/c/share/php/browscap.ini
allow_url_fopen=0
; END SNIPPET id=default

DESCRIPTION

This module provides one function: setup_snippet_with_id.

This module is part of the Setup modules family.

This module uses Log::Any logging framework.

This module's functions have Sub::Spec specs.

THE SETUP MODULES FAMILY

I use the Setup:: namespace for the Setup modules family. See Setup::File for more details on the goals, characteristics, and implementation of Setup modules family.

FUNCTIONS

None are exported by default, but they are exportable.

setup_snippet_with_id(%args) -> [STATUS_CODE, ERR_MSG, RESULT]

Setup text snippet (with comment containing ID) in file.

On do, will insert a snippet of text with specified ID to a file, if it doesn't already exist. Usually used for inserting tidbits of configuration into configuration files.

Snippets are enclosed with comment (shell-style by default, or alternatively C++/C-style) giving them ID. Example of one-line snippet:

some text # SNIPPET id=id1

Example of multi-line snippet (using C++-style comment instead of shell-style):

// BEGIN SNIPPET id=id2
some
lines
of
text
// END SNIPPET

On undo, will remove the snippet.

Returns a 3-element arrayref. STATUS_CODE is 200 on success, or an error code between 3xx-5xx (just like in HTTP). ERR_MSG is a string containing error message, RESULT is the actual result.

This function supports undo operation. See Sub::Spec::Clause::features for details on how to perform do/undo/redo.

This function supports dry-run (simulation) mode. To run in dry-run mode, add argument -dry_run => 1.

Arguments (* denotes required arguments):

  • comment_style => str (default "shell")

    Value must be one of:

    ["c", "cpp", "html", "shell", "ini"]

    Comment style.

    Snippet is inserted along with comment which contains meta information such as snippet ID (so it can be identified and updated/removed later when necessary).

    Example of shell-style (shell) comment:

    ... # SNIPPET id=...
    
    # BEGIN SNIPPET id=...
    ...
    # END SNIPPET

    Example of C-style (c) comment:

    .... /* SNIPPET id=... */
    
    /* BEGIN SNIPPET id=... */
    ...
    /* END SNIPPET id=... */

    Example of C++-style (cpp) comment:

    .... // SNIPPET id=...
    
    // BEGIN SNIPPET id=...
    ...
    // END SNIPPET id=...

    Example of SGML-style (html) comment:

    .... <!-- SNIPPET id=... -->
    
    <!-- BEGIN SNIPPET id=... -->
    ...
    <!-- END SNIPPET id=... -->

    Example of INI-style comment:

    .... // SNIPPET id=...
    
    ; BEGIN SNIPPET id=...
    ...
    ; END SNIPPET id=...
  • content* => str

    Snippet text.

    String containing text).

  • file* => str

    File name.

    File must already exist.

  • good_pattern => str

    Regex pattern which if found means snippet need not be inserted.

  • id* => str

    Snippet ID.

  • label => code|str (default "SNIPPET")

    Comment label.

    If label is string (e.g. 'Foo'), then one-line snippet comment will be:

    # Foo id=...

    and multi-line snippet comment:

    # BEGIN Foo id=...
    ...
    # END Foo id=...

    If label is coderef, it will be called with named arguments: id, comment_style. It must return a hash with these keys: one_line_comment, begin_comment, end_comment, one_line_pattern (regex to match snippet content and extract it in $1), and multi_line_pattern (regex to match snippet content and extract it in $1).

  • replace_pattern => str

    Regex pattern which if found will be used for placement of snippet.

    If snippet needs to be inserted into file, then if replace_pattern is defined then it will be searched. If found, snippet will be placed to replace the pattern. Otherwise, snippet will be inserted at the end (or beginning, see top_style) of file.

  • should_exist => bool (default 1)

    Whether snippet should exist.

    You can set this to false if you want to ensure snippet doesn't exist.

  • top_style => bool (default 0)

    Whether to append snippet at beginning of file instead of at the end.

    Default is false, which means to append at the end of file.

    Note that this only has effect if replace_pattern is not defined or replace pattern is not found in file. Otherwise, snippet will be inserted to replace the pattern.

BUGS/TODOS/LIMITATIONS

If a snippet is removed due to should_exist=>0, its position is not recorded. Thus the undo step will reinsert snippet according to replace_pattern/top_style instead of the original position.

The undo also currently doesn't record whether newline was autoappended on the file, so it doesn't restore that.

TODO: Restore attrs.

SEE ALSO

Other modules in Setup:: namespace.

AUTHOR

Steven Haryanto <stevenharyanto@gmail.com>

COPYRIGHT AND LICENSE

This software is copyright (c) 2011 by Steven Haryanto.

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