Has there been a change in raku 2022.04 which breaks qqx? The line my $out = qqx|ls -l|; in a script leaves $out empty while the same line on raku 2022.03 and earlier populates $out with the contents of the current directory.
I have checked the release notes of raku but could not find a related change.
In case this is important: I'm on macOS 12.
EDIT:
qqx, shell and run stop working when they are enclosed in a loop reading from STDIN. The example below works in raku 2022.03 and earlier. It stops working in raku 2022.04. I have tried every version up to 2022.07 which is the latest version at the moment.
#!/usr/bin/env raku
sub MAIN() {
for slurp().lines -> $line {
shell <<ls -l ~>>;
}
}
Related
While testing around this issue, Can raku avoid this Malformed UTF-8 error? it was suggested that I try using the built in MacOS 'find .' command with the raku run function.
1 #!/usr/local/bin/raku
2
3 shell('find .'); #works
4
5 my $proc = run('find .', :out); #fails with
6 $proc.out.lines(:close).say; #() [ie. ().Seq]
Turns out that raku shell works fine, but raku run fails. I am not entirely sure if this is a bug with raku on MacOS (if so, I am happy to report it) ...?
[MacOS Catalina 10.15.17 ... Welcome to ๐๐๐ค๐ฎ๐๐จโข v2020.10. Implementing the ๐๐๐ค๐ฎโข programming language v6.d. Built on MoarVM version 2020.10.]
The issue you're running encountering isn't related to MacOS โ it's caused by the difference in how &shell and &run work. Consulting the docs, we can see that shell's signature includes $cmd โ the command as a Str, exactly as you provided.
In contrast, run's signature specifies that it takes *#args โ that is, a list of zero or more arguments to execute.
To match this signature, you should change your code as shown below:
# my $proc = run('find .', :out); # doesn't work
my $proc = run('find', '.', :out); # works
my $p2 = run <find .>, :out; # also works (using word-splitting)
(Your version asked your computer to run the program find ., which doesn't exist in your $PATH, which explains why it produced no output.)
Perl 6 Plain-Old-Documentation (perhaps Fancy-New-Documentation) has some features that allow it to construct documentation for things it sees, and the documentation shows up in the $=pod variable at runtime.
However, I was surprised when I couldn't read the docs when I'd made an error in the program text. Here I've left out a statement separator between two statements:
use v6;
BEGIN { put "BEGIN" }
INIT { put "INIT" }
CHECK { put "CHECK" }
"foo" "bar";
DOC INIT { put "DOC INIT" }
DOC BEGIN { put "DOC BEGIN" }
DOC CHECK { put "DOC CHECK" }
=begin pod
=head1 This is a title
This is a bit of pod
=end pod
When I run it with the --doc switch, the program syntax matters (and BEGIN runs):
$ perl6 --doc doc.p6
BEGIN
===SORRY!=== Error while compiling ...
Two terms in a row
------> "foo"โ "bar";
expecting any of:
infix
infix stopper
statement end
statement modifier
statement modifier loop
When I fix it, I get some warnings (so, perl6 is compiling) and the compilation-time phasers run:
BEGIN
DOC BEGIN
DOC CHECK
CHECK
WARNINGS for /Users/brian/Desktop/doc.p6:
Useless use of constant string "bar" in sink context (line 9)
Useless use of constant string "foo" in sink context (line 9)
INIT
DOC INIT
This is a title
This is a bit of pod
We already know this is a bit dangerous in Perl 5. A perl -c and a BEGIN block can run code. See How to check if a Perl script doesn't have any compilation errors?. I don't think this is any more dangerous than something we already know, but now it's happening at a time when I'm not explicitly asking something to compile program statements.
I haven't delved into the details of Perl 6 pod and why this might be necessary outside of declarator blocks and .WHY (a cool feature), but it seems like this can lead to trouble. Is there perhaps an external program that might extract the Pod? Or a way to do without the declarators unless the program will run?
Yes, the whole file has to be parsed, which in turn requires running BEGIN and use statements and such.
The Perl 6 language is designed for one-pass parsing from top to bottom, so that at any given point the parser understands what it is parsing based on what it has parsed so far.
Consider code like the following:
say "
=begin pod
Not POD, just a string!
";
If you'd just grep the file for POD statements without parsing all of it, it would misinterpret this piece of code.
I.e. you can't parse only the POD parts without parsing the normal Perl 6 code parts, because without parsing it all from top to bottom you can't know which is which.
PS: In theory, the Perl 6 designers could have accommodated POD-only parsing, by making it illegal for normal Perl 6 code to contain lines that look like they start a POD block. In this scenario, the above code snippet would be a syntax error when the whole file is parsed, because starting a line inside a string literal with =begin pod would be disallowed, so the --pod switch could rely on all lines that begin with =begin foo actually starting a POD block.
Such a restriction probably wouldn't be a major burden for normal Perl 6 code (after all, who needs to write =begin pod at the start of a line in a multi-line string literal), but note that one of the reasons for the one-pass top-to-bottom parsing architecture is to facilitate language extensibility via slangs.
E.g. CPAN modules could add support for users writing a single subroutine (or other lexical scope) in another language or DSL. (Implementing such modules isn't actually possible yet without hacking into Rakudo internals via NQP, but once the macro/slang design is complete, it will be).
The burden for disallowing lines that look like they start a POD block, would then be passed on to all those slang parsers.
You could always submit a feature request for Larry and the other Perl 6 designers to consider this, though.
By default, IntelliJ Idea will insert (something like) the following as the header of a new source file:
/**
* Created by JohnDoe on 2016-04-27.
*/
The corresponding template is:
/**
* Created by ${USER} on ${DATE}.
*/
Is it possible to update this template so that it inserts the last date of modification when the file is changed? For example:
/**
* Created by JohnDoe on 2016-03-27.
* Last modified by JaneDoe on 2016-04-27
*/
It is not supported out of the box. I suggest you do not include information about author and last edit/create time in file at all.
The reason is that your version control system (Git, SVN) contains the same information automatically. So the manual labelling is just duplicate of already existing info, but is only more error prone and needs to be manually updated.
Here's a working solution similar to what I'm using. Tested on mac os.
Create a bash script which will replace first occurrence of Last modified by JaneDoe on $DATE only if the exact value is not contained in the file:
#!/bin/bash
FILE=src/java/test/Test.java
DATE=`date '+%Y-%m-%d'`
PREFIX="Last modified by JaneDoe on "
STRING="$PREFIX.*$"
SUBSTITUTE="$PREFIX$DATE"
if ! grep -q "$SUBSTITUTE" "$FILE"; then
sed -i '' "1,/$(echo "$STRING")/ s/$(echo "$STRING")/$(echo "$SUBSTITUTE")/" $FILE
fi
Install File Watchers plugin.
Create a file watcher with appropriate scope (it may be this single file or any other scope, so that any change in project's source code will update modified date or version etc.) and put a path to your bash script into Program field.
Now every time the file changes the date will update. If you want to update date for each file separately, an argument $FilePath$ should be passed to the script.
This might have been just a comment to #oleg-mikhailov excellent idea, but the code snippet won't fit. Basically, I just tweaked his solution.
I needed a slightly different syntax but that's not the issue. The issue was that when the script ran automatically upon file save using the File Watchers plugin, if ran on a file which doesn't include PREFIX it would run over and over for ever.
I presume the that the issue is with the plugin itself, as it didn't happen when run from the shell, but I'm not sure why it happened.
Anyway, I ended up running the following script (as I said only a slight change with respect to the original). The new script also raises an error if the the prefix doesn't exist. For me this is a feature as Pycharm prompts me with the error, and I can fix the file.
Tested with PyCharm 2021.2.3 on macOS 11.6.
#!/bin/bash
FILE=$1
DATE=`date '+%Y-%m-%d'`
PREFIX="last_modified_date: "
STRING="$PREFIX.*$"
SUBSTITUTE="$PREFIX$DATE"
if ! grep -q "$SUBSTITUTE" "$FILE"; then
if grep -q "$PREFIX" "$FILE"; then
sed -i '' "s/$(echo "$STRING")/$(echo "$SUBSTITUTE")/" $FILE
else
echo "Error!"
echo "'$PREFIX' doesn't appear in $FILE"
exit 1
fi
fi
PHPStorm has not a "hook" for launching task after detect a change in file (just for uploading in server yes). Code templating is based on the creation of file not change.
The behaviour you want (automatic change file after manual change file) can be useful for lot of things but it's circular headhache for editor. Because if you change a file it must change file (and if a file is change ? it change file ?).
However, You can, perhaps, "enable Live Templates" when you launch a "reformat code" which able to rewrite your begin template code that way rewrite date modification.
Other solution is that use a tools with as grunt but I don't know if manage php file.
Perlย 6 has great builtin command-line parsing via MAIN. However, I faced a problem which seems to be trivial, but I cannot figure it out.
A simple MAIN:
sub MAIN(Int :n(:$num)) {
say "You passed: " ~ $num;
}
Then I can call my script as:
$ ./test.p6 -n=1
or:
$ ./test.p6 --num=1
But can't with:
$ ./test.p6 -n 1 # or even -n1
or:
$ ./test.p6 --num 1
I went through the design document for MAIN with no luck. How can I make this work?
Some info:
That's a reported bug. If you discover more about this that isn't mentioned in that bug report, eg find a workaround, please consider adding a comment to the report.
For your convenience, here are the other two extant bug reports I found for MAIN: Usage does not print required type for positional params in MAIN and fail to handle numbers as option name for MAIN.
Some options:
Use an options module. Maybe Getopt::Tiny will do the trick.
Help fix #124664. Perl 6 is (mostly) written in Perl 6. I think the code that munges raw main command line args and binds them to MAIN signature variables is the 20 lines or so in process-cmd-args.
I have a few python scripts, and for various reasons, I have shell script wrapper around them:
#!/bin/sh
source env.sh
python $0.py $#
This works fine, unless the arguments needs to be quoted. In this case, of course, the wrapper, eats the quotes, and gives the un-quoted version to the python script. So, my first question is "How can I get sh to not eat the quotes?"
However, even if I back-slash the quotes, it doesn't work. I print out the entire command I'm about to call:
source env.sh
echo "python $0.py $#"
python $0.py $#
If I call it with foo \"a b c" it outputs
python foo.py "a b c"
However, when foo.py gets called, it still GETS foo.py a b c
If I just copy and paste the output, and run it, it runs fine.
Can anyone tell me why the actual execution would fail from the script, but succeed on the command line?
thanks.
you need quotes around the actual use of the $# parameter, i.e.
source env.sh
echo "python $0.py $#"
python $0.py "$#"
I hope this helps.