Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Meditations

( #480=superdoc: print w/replies, xml ) Need Help??

If you've discovered something amazing about Perl that you just need to share with everyone, this is the right place.

This section is also used for non-question discussions about Perl, and for any discussions that are not specifically programming related. For example, if you want to share or discuss opinions on hacker culture, the job market, or Perl 6 development, this is the place. (Note, however, that discussions about the PerlMonks web site belong in PerlMonks Discussion.)

Meditations is sometimes used as a sounding-board — a place to post initial drafts of perl tutorials, code modules, book reviews, articles, quizzes, etc. — so that the author can benefit from the collective insight of the monks before publishing the finished item to its proper place (be it Tutorials, Cool Uses for Perl, Reviews, or whatever). If you do this, it is generally considered appropriate to prefix your node title with "RFC:" (for "request for comments").

User Meditations
The state of Perl
2 direct replies — Read more / Contribute
by FreeBeerReekingMonk
on Nov 30, 2016 at 15:01
    Some other monks made comments about the quietness on this site... here are some visual clues and trends:

    As measured by github changes and stackoverflow tags....

    Programming Language Popularity Chart

    And also:

    job-trends for perl and similar

    If you add C++ to the latter, you will see nobody is looking for C++ jobs (but they search for C instead).

(Placeholder) Imagine!
5 direct replies — Read more / Contribute
by BrowserUk
on Nov 29, 2016 at 22:24

    This place excels in starting with a single, clearly defined, abstracted problem, and refining the set of proposed solutions down to a clear, concise, efficient solution. Many hands make light work!

    Now, imagine if each of the Perl(5) opcodes was proffered here -- say: one per weekend -- on a Friday night - say: US West Coast time -- in the form of a hack-a-thon task for that weekend.

    What might result from that exposure of a clearly defined task to the assembled (and usually quite bored on weekends), diverse populous?

    If those more enlightened tolorant members of p5p were enthused to cast a critical eye over the proceedings -- to catch the less obvious pitfalls in the evolution of solutions -- then the results might be usefully fed back into the p5p process and result in benefits for all.

    Thoughts on: Is the idea viable?

    Thoughts on: Are any members of p5p willing to participate?

    Caveats?


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". The enemy of (IT) success is complexity.
    In the absence of evidence, opinion is indistinguishable from prejudice.
Propose addition to use warnings?
6 direct replies — Read more / Contribute
by perldigious
on Nov 28, 2016 at 09:30

    I'm not sure what the official mechanism for making such a suggestion would be, but I recently had to go on a bug hunt in my code that left me surprised use warnings didn't give me some sort of, "are you SURE you aren't doing something silly here at line x?" message. Maybe it isn't practical to expect use warnings to save me from myself in this case, but I figured I'd throw it out here as a meditation for discussion and to get opinions from Monks far wiser than I am.

    I'm of course simplifying and paraphrasing, but essentially I had some code that did the following:

    open(my $first_fh, "<", "file1.txt") or die "Cannot open \"file1.txt\" +: $!."; open(my $second_fh, "<", "file2.txt") or die "Cannot open \"file2.txt\ +": $!."; my @file1_lines = <$first_fh>; close $first_fh; while (my $line = <$second_fh>) { my @data = my_sub($first_fh, $line); # copy/paste error, should ha +ve passed $second_fh here # and of course a bunch of non-relevant stuff here }

    So I accidentally passed the $first_fh that I had previously closed to my_sub, but as it turns out use warnings didn't make a peep about this. I did of course get warnings from inside my_sub when it attempted to make use of the filehandle, but the kicker was that any such use was wrapped inside of a conditional that actually made it very rare it would ever get used (maybe once every 100,000 lines or so of typical data).

    DISCLAIMER: The fact that I didn't have something in my standard test data that ensured the conditional that used the filehandle was exercised is entirely on me (forgive me, for I have sinned). I accept full responsibility for that mistake and the initial copy/paste laziness error that forced me to engage in my bug hunt. I'm only pointing out that usually use strict, use warnings, or perl itself is pretty good about preemptively saving me from myself, and in this case it didn't.

    Any thoughts from the Monastery?

    Just another Perl hooker - will code for food
storeBackup - A Gem of a Backup Solution
1 direct reply — Read more / Contribute
by wjw
on Nov 20, 2016 at 11:49

    I was recently in a position where I needed a backup solution that was flexible enough to handle my laptop as well as my home server. I back up to a couple of older USB drives; A 1.5T for my laptop, and a 750G for my home server. The plethora of options out there is daunting, and the most obvious like rsync (which I really like and use often) are very nice. But I wanted something that I could set up quickly and would meet a couple of other needs easily.

    • I wanted it to conform to a standard backup scheme where there are a couple backups each day, a daily backup for a week or so, a monthly backup, and a yearly.
    • I wanted it to delete outdated backups
    • I wanted it to be tolerant of the backup drive not being available, such as when I am out of town with my laptop, but don't have the USB drive to back up to.
    • and ... I also wanted it to do something like rsync in that it stores only the differences, not an entire copy of everything in each backup.

    What I found was a Perl application called storeBackup. It has been around for a while, claims to be production ready/stable, and it seems to me as if it is.

    I did a non-exhaustive search here on perlmonks and did not find a reference to this handy tool, so thought I would mention it here in meditations....as I was sitting here meditating about it. The darn thing works really well! It does exactly what I want it to do in that it meets all the requirements listed above, and has the added benefit that it is written in Perl.

    For anyone looking for a very sweet backup solution that is simple to set up, is tolerant of a dynamic environment, and provides efficient, accessible, and easily recoverable backup data, I would certainly recommend looking at this solution. From my perspective, it just plain rocks!

    ...the majority is always wrong, and always the last to know about it...

    A solution is nothing more than a clearly stated problem...

RFC: Potracheno - a technical debt issue tracking system
No replies — Read more | Post response
by Dallaylaen
on Nov 14, 2016 at 06:50

    Hello dear esteemed monks,

    Today I would like to present a tool of my own which I hope you'll find useful.

    Preamble

    Every once in a while I encounter a technical debt discussion on the internet. Each time there are generally two types of comments: (1) tech debt is bad, it leads to bugs, delays, downtime, top talent quitting and product rewrites, and (2) nobody pays for clean code, all you need is features here and now.

    Being a supporter of the first cause myself, I keep wondering if the damage can actually be measured. And it looks like there is a way.

    The tool

    Potracheno (a Russian adjective with a meaning close to "wasted" or "spent") is a specialized tech debt issue tracking system. Just like a normal bug tracker, it has tickets, ticket statuses and comments, search, and so on. It supports markdown and Stackoverflow-like tags. Nothing much to boast about.

    Also like a normal bug tracker it has time tracking facility. However, instead of recording time spent fixing a problem, it tracks time wasted on living with it. Copy-and-pasting, fighting bugs, doing manually what could be automated, waiting for long compilation/deployment, and generally being frustrated and posting about it on the net.

    Completely unlike a normal bug tracker, it has a special feature called solution proposals. A solution is a special comment with a time estimate to fix the issue. Multiple solutions can be proposed for the same issue.

    Finally, a report with numerous criteria can be generated. Including, but not limited to, the fix estimate / wasted time ratio.

    The project is written in Perl and SQLite with minimal dependencies (DBD::SQLite, Text::Markdown, and MVC::Neaf). It is designed to run from local directory on any network-enabled device, be it a dev's laptop, a test server, or a coffee machine in the office.

    Source: https://github.com/dallaylaen/potracheno.

    A little philosophy

    The supposed setting for this tool is a team sick of bad code and willing to refactor it - refactor in the broadest sense, including rewriting specific components, fixing architecture/preformance problems, writing missing tools etc - anything that improves the project on the inside.

    Also somewhere must be the project owner, who only wants features as soon as possible. Well, if they wanted something else, the team would be out in the street with a well written product that nobody uses.

    This tool is supposed to be installed alongside a normal ITS (if you don't have one, tech debt isn't your biggest problem for sure). As statistics and solutions accumulate, they either should be presented to the product owner and converted to usual tasks, or silently included with features touching the same component(s).

    I believe that, similar to performance profiling, 80% of the team's frustration are accounted for by a tiny subset of problems that can be numbered, weighted, and dealt with once and for all. Whether this holds, only practice can tell.

    And finally

    I would like to ask you, fellow monks, to try and follow the installation instructions of my project, and tell me (either here, or in the github bugtracker) what went wrong. I'm planning to release it onto non-Perl users (thus acting as a Perl-monger), so I would like the process to be as smooth as possible.

    Thanks for reading, and have a great day and a great week!

OT: Programming For Kids
6 direct replies — Read more / Contribute
by karlgoethebier
on Nov 13, 2016 at 13:41

    This is something i would like to share.

    The last two week i took care of a 14 year old trainee at the company i'm with.

    I needed to prepare something for him and by chance i stumbled over Scratch.

    IMHO this is real good stuff. We had a lot of fun. Highly recommended.

    Please see also Snap! It looks like Scheme is not dead ;-)

    Regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

RFC: Shortening line length in HTML Emails
2 direct replies — Read more / Contribute
by LanX
on Oct 27, 2016 at 12:02
    Hi

    My team is using TinyMCE in a web-application to create templates for HTML emails. (not my idea)

    We've been confronted with strange errors where whitespaces occasionally where introduced in the middle of the emails after sending.

    This was particularly ugly b/c sometimes HTML tags where broken, like in </sp an>

    A closer investigation revealed that by RFC lines in Emails are not allowed to have more than 1000 characters (only fair) and that TinyMCE sometimes tended to glue HTML code into one "physical" line, especially when

    • "visual" lines where separated by <br> tags
    • or when the text was introduced by cut&paste from other applications.
    So I need a pragmatic solution to avoid such "monster" lines after editing an email text.

    I came up with the following idea, which should be as safe as possible without starting to parse HTML

    1. prepend a \n before every <br> tag
    2. if overlong unbroken text-chunks remain, replace the last blank with a \n
    3. return an error to the user if the later fails
    The idea is to change a minimal amount of HTML code in a transparent way.

    (I suppose that <pre> -tags are not used with monster lines and that the inner code of HTML and CSS doesn't distinguish if a whitespace is a blank or a line-break)

    That's the code I came up with, comments are welcome! :)

    use strict; use warnings; use Data::Dump qw/pp dd/; my $body = <<'__HTML__'; <br /><br/><br><break> asdfghjk rtz ertzuiop rtzuiopu rtzuiop tzuiopu rtghljh AaaaaaaaaaaaaaABbbbbbbbbbbbbbbB __HTML__ #pp $body; my $err = FC012_shorten_lines_mail_body(\$body); #pp $body; print $err,$body; sub FC012_shorten_lines_mail_body { my ($body_ref) = @_; my $err = undef; # callback with closure for error my $replace_last_whitespace = sub { my ($chunk) = @_; # dd "CHUNK: $chunk"; my $ok = $chunk =~ s/ ([^\s]*)$/\n$1/; unless ($ok) { my $snip_length = 4; # for testing, should be 40 my $start_chunk = substr ($chunk,0,$snip_length); my $end_chunk = substr ($chunk,-$snip_length,$snip_length); $err .= "Failed to shorten chunk >>$start_chunk...$end_chunk< +<\n"; } return $chunk; }; # --- prepend all <br>-tags with real linebreak $$body_ref =~ s#(<br[ />])#\n$1#g; # --- find all reamining chunks in one line and # replace last whitespace with \n my $length = 15; # for testing, should be 998 $$body_ref =~ s/([^\n]{$length})/ $replace_last_whitespace->($1) /g +e; # --- return potential error message return $err ; }

    --->

    Failed to shorten chunk >>Aaaa...aaaA<< Failed to shorten chunk >>Bbbb...bbbb<< <br /> <br/> <br><break> asdfghjk rtz ertzuiop rtzuiopu rtzuiop tzuiopu rtghljh AaaaaaaaaaaaaaABbbbbbbbbbbbbbbB

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

Testing Dancer applications with a custom database
No replies — Read more | Post response
by Corion
on Oct 24, 2016 at 13:10

    While developing a plugin for Dancer as a wrapper around one of my modules, I wanted to unit test my code using a mock database instead of the database I do interactive tests with. Surprisingly, I didn't find documentation on how to supply Dancer::Plugin::Database with your own test database.

    After some reading through the test suite of Dancer::Plugin::Database, it seems that the magic is in overwriting the configuration at the right time. To give this approach a broader exposure and to maybe invite some comments or better suggestions, let's look through the code:

    In the prelude, we load Dancer, Dancer::Test and the application I'm writing, tentatively named mychat. We plan for three tests:

    #!perl -w use strict; use warnings; use Test::More import => ['!pass']; use Data::Dumper; use Dancer ':syntax'; use DBIx::RunSQL; use Dancer::Plugin::Database; # the order is important use mychat; use Dancer::Test; plan tests => 3;

    Then, we set up our own in-memory database and create all tables and triggers from the SQL file stored in sql/create.sql. This gives us a pristine database that contains only initial data.

    # set up our own database instead of whatever is in the config my $conf = { Database => { dsn => 'dbi:SQLite:dbname=:memory:', connection_check_threshold => 0.1, sqlite_unicode => 1, dbi_params => { RaiseError => 0, PrintError => 0, PrintWarn => 0, }, }, }; set plugins => $conf; # Set up a fresh instance my $dbh = database; $dbh = DBIx::RunSQL->create( dbh => $dbh, sql => 'sql/create.sql', );

    Since what I really want to test is whether image upload and retrieval works, let's fake a PNG image and "upload" it into the application:

    my $payload = join '', "\x89", 'PNG', "\x0d\x0a", "\x1a", "\x0a", (map { chr($_) x (1024 * 256) } 1..3) ; # Insert image into database my $upload = Dancer::Request::Upload->new( filename => 'test.png', tempname => 'test2.png', size => length($payload), headers => { 'Content-Type' => 'image/png', }, ); # Insert into DB my $content = mychat::UserContent->store( config->{image_store}, $dbh, $upload, { extension => 'png', content_type => 'image/png', }, $payload );

    After all this setup, we can now run three tests as if we had a standard Dancer application and can check that URLs exist where we expect them and that we get the appropriate content from each URL:

    ok $content, "We successfully saved the user content"; route_exists(['GET', '/image_store/foo.bar'], "We find /image_store/fo +o.bar"); # Check that we can access it through /image_store/sha1.jpg my $name = $content->{digest} . ".png"; response_status_is ['GET',"/image_store/$name"], 200, "GET '/image_sto +re/$name' succeeds" or diag Dumper read_logs();
Why aren't you using Google::API::Client?
1 direct reply — Read more / Contribute
by mla12
on Oct 24, 2016 at 12:23

    I stumbled on this module a while ago. It has some rough edges and the docs aren't the greatest, but I've found it incredibly useful.

    It uses the Google Discovery API to interact with any of their services.

    So why isn't it more popular? Is there another module that serves this purpose better?

RFC: MVC::Neaf aka Not Even A Framework, part 2
No replies — Read more | Post response
by Dallaylaen
on Oct 18, 2016 at 16:10

    Hello dear fellow monks,

    After weeks of hesitation, I finally decided to share a piece of work called MVC::Neaf. Neaf [ni:f] stands for Not Even A Framework.

    It aims to keep things simple and straightforward, while maintaining some degree of separation between logic and presentation.

    Not to repeat myself, here's the original post.

    I know there's a lot to do, so I would appreciate any feedback. If you dare to try it out, please send bug reports and feature requests to github.

    Cheers!

RFC: Not Even A Framework
1 direct reply — Read more / Contribute
by Dallaylaen
on Oct 02, 2016 at 10:31

    Hello dear fellow monks,

    It's Sunday, and I would like to confess to an awful sin of writing my own web framework from scratch. Yes, it's 2016, there are Dancer, Catalyst, Mojo, Kepl, and a dozen less known examples. I mostly did it for my own education, as well as to look at possible ways of handling the nuisances that have been plaguing me throughout my two last jobs. Yet I see some not so bad ideas in there and would like to share and possibly get some critique.

    It's called Neaf [ni:f], which stands for Not Even A Framework.

    Much like Dancer, it splits an application into a set of handler subroutines associated with URI paths. Unlike Dancer, however, it doesn't export anything (except one tiny auxiliary sub) into the application namespace. Instead, a know-it-all Request object is fed to a handler when serving request, like in OO CGI.pm or Kelp.

    The response is expected in the form of unblessed hash reference which is in turn fed to the view object for rendering (Template Toolkit and JSON/JSONP currently supported, also Data::Dumper for debugging). Also the return value may contain some dash-prefixed switches altering the behavior of Neaf itself - awful looking, yet visible and simple way of doing it without going for a more complex structure.

    Unlike anything I've seen so far, and much like Perl's own -T switch*, it offers no (easy) way to get user inputs without validation, either through regexp, or through a form validator. (Regexp-based one is in stock, LIVR also supported).

    My not-so-impressive feature list so far:

    • GET, POST, and HEAD requests, query parameters (multivalues not done yet), uploads, cookies, and redirects;
    • Template::Toolkit, JSON::XS view out of the box;
    • Can serve raw generated content (e.g. images) and static files (like css/js);
    • CLI-based debugging (can simulate posts, uploads, cookies etc);
    • Can serve delayed or unspecified length replies, or do custom actions after the request is finished;
    • cookie-based sessions supported (no storage drivers available out of the box yet, though);
    • Form validation and resubmission;
    • Half-decent example directory and 79% overall test coverage.

    The following is a valid application and can run as a CGI script, a PSGI app, or under Apache as a mod_perl handler**:

    use strict; use warnings; use MVC::Neaf; MVC::Neaf->route( "/" => sub { my $req = shift; return { -template => \'Hello, [% name %]!', -type => 'text/plain', name => $req->param( name => qr/\w+/, "Stranger" ), }, }); MVC::Neaf->run;

    So here it is: https://github.com/dallaylaen/perl-mvc-neaf. Thanks for reading this, and hope you enjoy the rest of the weekend.

    *That said, I have not seen it often in production, certainly not in big apps with convoluted logic.

    **Setting up a handler requires a little extra work though - see apache.cgi file in the distribution.

    UPDATE Uploaded to CPAN.

Don't post bad code!
5 direct replies — Read more / Contribute
by afoken
on Sep 26, 2016 at 16:46

    The thread Declaring and checking content of variables with consecutive names and especially the answer Re: Declaring and checking content of variables with consecutive names triggered this meditation.

    There is nothing special about this thread or this answer, it's just one of those FAQs (in this case "How can I get variable variable names"). People explain how to do the job properly, and some other people can't resist showing that there is a way how to force perl into using the stupid variant. I vagely remember threads where people tried to find even more stupid ways to "solve" a cleanly solveable problem.

    Yes, we can force perl into doing the most stupid things. Yes, it's cool to know how to mess with the inner workings of perl. But no, we should not show beginners the most dirty ways first. Not even with warnings not to use the dirty ways in production code. "Just do as I say, don't do as I do" is no good motto, not for teaching beginners.

    Why? Because there are lots of beginners out there, who either don't have time to or are unwilling to learn how to use perl. They just want fast results, they don't care about maintainability or improving their skills. Imagine what happens when they get ten answers linking to FAQs, HOWTOs, documentation, or showing examples of the right way, but require a little bit of thinking; and one or two answers showing how to abuse perl into the way they are currently thinking.

    "There is nothing humans would not do to avoid thinking."
    -- Found on a pinboard in a computer laboratory in my univerity

    This way, bad practices propagate, resulting in crappy perl scripts.

    Let's make it hard for the unwilling and the people in a hurry to find bad code, bad examples. Posting sane examples is good, improving a code example posted is even better.


    But what about golf?

    Perl golf is fun, true. Replacing pages and pages of code with 20 characters of "line noise" with the same result is deeply impressive. But do we have to show our golf skills in beginner threads? I don't think so. Create a new thread, link to the beginner's thread, and name it "Golf Challenge". Or at least start a golf posting by explaining that this is not a real answer, but a golf challenge for the experts.


    Are one-liners bad?

    (A meditation in a meditation)

    It depends. Short one-liners for one-time use are ok. But for anything more complex than one or two, maybe three explicit instructions (not counting the implicit loops in perl -p and perl -n) should be in a script. And if the one-liner is to be reused, it should instead be a script, too.

    Why?

    • One-liners require that you remember quite complex "line noise". So you very likely store them in a file. What's the difference to using a real script? It's just harder to use, as you need to copy-and-paste.
    • Quoting rules differ with different shells (and different operating systems), so you need to adapt the one-liners, especially the arguments to perl -e and perl -E, to the shell currently in use. Scripts don't have this problem.
    • Scripts can have nice names. cleanup-foo is easier to remember, easier to type, and shows the intention more clearly than perl + 10 perl command line options + -e plus 80 characters of "line noise" in quotes differing from shell to shell.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Code "taste", coding guidelines, and revision control systems
3 direct replies — Read more / Contribute
by afoken
on Sep 16, 2016 at 17:24

    (Just thinking out lout a little bit more after writing Re: Starting a New Script ...)

    A long time ago, in a galaxy company far, far away ...

    Co-worker IH asks: "Who wrote this code?"

    Me: "Hmm, definitively not me. And far too structured to be written by HK."

    IH: "Yes, I agree. Looking at the names of the identifiers hints at DF, or maybe JF during his first months [when he learned from DF]. It's full of three letter acronyms."

    Me: "But JF would have added at least some comments. There is not a single comment, and not a single bit of code that's not absolutely required. Tight, but elegant. DF?"

    IH: "Yes, definitely DF. But what does it do?"

    Me: "Well, let's start analysing it ..."

    And of course, we were right. DF wrote the code, and nobody else touched it after that. Just for fun, we tried that with other pieces of code the team members wrote over the years, and we were often right. We could even guess who wrote the original code, and who changed it later.

    When we later explained our little game and its origin to non-IT people, we compared it to wine tasting, and to guessing an author from a piece of text.

    In the next episode, same galaxy company, but a different team:

    JF, a hardly ever swearing co-worker, asks: "What the *BEEP*? Which *BEEP* *BEEP* has written this *BEEP* *BEEP* *BEEP* piece of code?"

    Me: "Show me."

    JF: "Here you are."

    Me: "Argh! Get it off my screen. It hurts my eyes! It hurts my brain! Get it off! GET IT OFF!"

    Me, after wiping off some tears: "Well, it roughly looks like code generated by $StupidMouseClickingCodeGenerator. But why the heck did the author use that *BEEP* tool? It's completely useless here! We are on a completely different target system!"

    JF: "If your only tool is a hammer, every problem looks like a nail. Some clueless worker from the client?"

    Me: "Nope, the client does not access that part of the code. It's part of our setup routine. And the client would use tools for the right target."

    JF: "So AG?"

    Me: "Yes, definitely AG. Who else would use a hammer for a brain surgery?"

    JF: "AG definitively needs to learn $ComputerLanguage."

    Me: "And our system. It's three months, and still AG has absolutely no clue of what happens here. You will tell AG. I can't do that without insults and swearing."

    And of course, we were right again.


    Using revision control systems makes the guessing game a lot less interesting (svn log, svn blame), and using strict coding rules and code templates generates more uniform code across the team.

    But still then, without looking at the logs, you can see differences in the way team members write code. And you can often identify who wrote a piece of code: "Soft factors" like the length and complexity of subroutines, naming of identifiers, style of the embedded documentation (POD, doxygen), systematic spelling errors in identifiers and documentation, preferred algorithms, and so on.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Starting a New Script
8 direct replies — Read more / Contribute
by LloydRice
on Sep 16, 2016 at 09:48

    How do you start a new script? Do you just open a blank editor page and start typing?

    I have written a Perl Code Builder that may be of some interest to somebody. To run it, you specify any number of capabilities this script should include, out of a catalog of a couple of dozen areas. Available capabilities range from a few simple trig functions and file read/write loops to a fairly elaborate PostScript code writer. You then open this "outline" script and finish rounding out the half-written pieces of code to do the current job. Since writing this, I have never started a new script from a blank slate.

    Would this be of interest to anybody? If so, I will make it freely available.

    Do similar things already exist? If so, I have missed seeing them.

    Lloyd Rice

[emacs] RFC live formating / tidying while I type
1 direct reply — Read more / Contribute
by LanX
on Sep 08, 2016 at 15:32
    Hi

    I always wanted to have live formatting as I type Perl code.

    The usual advice to pipe a text selection through perltidy is just too slow, and furthermore you might want to have only a visible snippet formatted to keep control, and tidy can fail here (emacs is mostly very tolerant)

    The following code called with M-x my-indent-block is re-indenting the surrounding block you are in. The devadvice binds it to the cperls electric-semi feature which automatically does a return and and indentation of the following line (see M-x customize-group RET cperl-autoinsert-details for details)

    before

    for my$scalar(1..10){print"$scalar"."txt";}
    after
    for my $scalar (1..10) { print"$scalar"."txt"; }
    NB: this is work progress but it's by far faster than perltidy
    (defun my-indent-block () "reindent surroundig expression" (interactive) (save-excursion (backward-up-list) (cperl-indent-exp) ) ) (defadvice cperl-electric-semi (after my-electric-indent-context) "indent whole context surrounding block/context" (my-indent-block) ) (add-hook 'cperl-mode-hook (lambda () (local-set-key (kbd "M-C-q") 'my-indent-block ) ) )

    Problems:
    • Defadvice is a kind of wrapping, I tried to bind it to cperl-indent-line to always indent the whole block whenever and indentation is triggered (there are many ways to do so in cperl-mode) but this is causing an infinite recursion , since cperl-indent-exp calls cperl-indent-line. (this is for sure solvable with some kind of flag, but I'm tired now :)
    • Toplevel In filescope this doesn't work cause there is no up-list! Thats good, because I didn't want to reindent distant code, without visual control. But it's still pretty easy in elisp to catch the error and to react otherwise, one option is to just reindent one paragraph or the whole file if that option is set.
    Natural keybindings

    cperl-indent-exp is normally bound to M-C-q , but is only useful after you've put the cursor in front of the block to highlight (here the for ), that's why I remapped it to work from inside the block.

    M-q should be the far better choice ( I hate 3+ finger combinations). In cperl-mode it's bound to cperl-fill-paragraph which wraps text to 80 colums ONLY in POD, here-docs or comments, but isn't useful in code! ( well as long as you are not trying to obfuscate )

    But now I'm not sure how to combine the old cperl-heuristic to distinguish between code and text with this new features, without patching cperl.

    Nice to have for my-indent-block
  • repeated manual calls should format ever bigger surrounding blocks till reaching the file-scope. (It's pretty easy to check the last command for repetition)
  • automatic delete-trailing-whitespace inside the block would be nice too (easy)
  • deleting unnecessary trailing empty lines at the block end
  • the cperl's indentation doesn't reformat spaces inside brackets or around operators (see print) yet
  • the cperl's indentation doesn't align = and => yet *
  • any other formating feature from perltidy I forgot

    COMMENTS ?

    footnotes

    *) there is align-current for regions, but it's reg-ex based fails with nested structures

    my $a = { a => 1, b => { c => 3, } };

    but with the semantic information of cperl's parsing it's possible to distinguish between the different levels of =>.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!


Add your Meditation
Title:
Meditation:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":


  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others pondering the Monastery: (8)
    As of 2016-12-09 16:05 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?
      On a regular basis, I'm most likely to spy upon:













      Results (152 votes). Check out past polls.