Put all methods into .h file automatically - iphone

In implementation file (.m) I have 30.. methods. How can I put their description (all of them) into .h file automatically?

Seams hard to do properly with a regex, but you can do it with awk:
https://gist.github.com/1771131
#!/usr/bin/env awk -f
# print class and instance methods declarations from implementation
# Usage: ./printmethods.awk class.m or awk -f printmethods.awk class.m
/^[[:space:]]*#implementation/ {
implementation = 1;
}
/^[[:space:]]*#end/ {
implementation = 0;
}
/^[[:space:]]*[\-\+]/ {
if(implementation) {
method = 1;
collect = "";
}
}
/[^[:space:]]/ {
if(implementation && method) {
p = index($0, "{");
if(p == 0) {
if(collect == "")
collect = $0
else
collect = collect $0 "\n";
} else {
method = 0;
# trim white space and "{" from line end
gsub("[\{[:space:]]*$", "", $0);
collect = collect $0;
# trim white space from start
gsub("^[[:space:]]*", "", collect);
print collect ";"
}
}
}

Write a piece of code that will extract all the methods definitions (Use regular expressions to detect them) and then just added it to the h file and "\; \n".

The program Accessorizer (on the Mac App Store for $5) is specifically intended for these obnoxious grunt work issues in Xcode. It can generate prototypes as well as property synthesizes, accessors, inits, etc.
Caveat: it's been a bit touchy and rough around the edges in my experience. It might, for example, not realize that a function is inside a multi-line comment, and thus provide an unwanted prototype for it. But even with those quirks in mind, it's saved me way more than $5 worth of time.
Their website: http://www.kevincallahan.org/software/accessorizer.html

Related

Update scalar variable globally inside if statement in Perl?

I'm trying to update a variable declared and used outside of a series of if / elsif / else statements, and updating it within the series. Is there a functional way to make this sorting/updating variable work?
my $daterange = 'initial';
if ($in{from_date} & $in{to_date}) {
my $daterange=~"AND (date BETWEEN '$fromdate' and '$todate')";
}
elsif ($in{from_date}) {
my $daterange=~"AND (date > '$fromdate')";
}
elsif ($in{to_date}) {
my $daterange=~"AND (date < '$todate')";
}
else {
my $daterange=~"blank";
}
print $daterange;
my creates a new variable. That means that inside your "then` clauses, you create a new variable, then assign a string to it. You never use that variable again!
You want to assign to the existing variable, so stop creating new ones with the same name.
There are numerous other problems with your code:
Your code suffer from SQL injection bugs.
You used =~ to assign to a variable when the assignment operator is =.
You used & to check if two value are true when the logical-AND operator is &&.
You used "blank" to create an empty string when it doesn't.
You sometimes use $in{from_date} and sometimes $fromdate.
You sometimes use $in{to_date} and sometimes $todate.
You assign an initial value (initial) to $daterange that you never end up using.
You have some useless parentheses in your SQL.
Fixed:
my $daterange;
if ($in{from_date} && $in{to_date}) {
$daterange = " AND (date BETWEEN ".$dbh->quote($in{from_date})." AND ".$dbh->quote($in{to_date}).")";
} elsif ($in{from_date}) {
$daterange = " AND date > ".$dbh->quote($in{from_date});
} elsif ($in{to_date}) {
$daterange = " AND date < ".$dbh->quote($in{to_date});
} else {
$daterange = "";
}
Delete all my except the first one.
This prevents one local variable being introduced for each {}, which is then unknown outside.
That way, the accesses inside the {} will affect your global variable.
As c3st7n noted (thanks), you will also have to doublecheck what you actually do to your variable, it is likely that it is not what you intended. I.e. you probably want to use = instead of =~.

In Vim, how to avoid having "/*" be treated as comment

Vim keeps treating my perl code as comments and the auto indentation does not work.
$dump=`cp /local/*.txt .`;
if ($a == 0)
{
if ($b == 0)
{
print "HELLO";
}
}
was formatted as:
$dump=`cp /local/*.txt .`;
if ($a == 0)
{
if ($b == 0)
{
print "HELLO";
}
}
This is because the "/*" in the first line was treated as comment and hence Vim gives up indenting anything afterwards.
I could think of a workaround as:
$dump=`cp /local/*.txt .`; #*/;
To manually close the comment.
But is there a better way?
Thanks.
You're using cindent, which is meant specifically to autoindent C code (including C-style block comments). This has no awareness that you are actually writing perl. Try smartindent instead, it seems to work better with perl. To try this, run set cindent! and then set smartindent. If this works better, you can change it in your .vimrc file.
If you're talking about the = key to indent, rather than the ident-as-you-go indentation, this is uses a separate formatter. You can change the what is used by setting equalprg. For perl, you might use set equalprg=perltidy\ -quiet to run the selected lines through perltidy.

Extracting Single from huge Archive using Perl

I'm trying a single from a large ".tgz" file. I'm using Archive::Tar::Streamed module.
Here is the sample code.
my $tar2 = Archive::Tar::Streamed->new($filename);
$fil = $tar2->next;
while($fil) {
$_ = $fil->name;
if(m/abc\.txt/g) {
$fil->extract($outpath);
$fil = $tar2->next;
}
}
But the iterator is not working. It is looping the first file in the archive not moving to the next file.
Can someone tell me what mistake i've done here???
You put the call to next inside your if, so it's only executed if you extracted the file. There's nothing that modifies $fil inside the loop if the file is not extracted.
You can simplify your code quite a bit by just calling the iterator in the condition of the while loop. Also, you can use the =~ binding operator instead of storing the name in $_. And you do not want the /g regex modifier here. In scalar context, you use /g to loop through multiple matches in a string. Here, all you want is to know whether the string contains a match.
my $tar2 = Archive::Tar::Streamed->new($filename);
while(my $fil = $tar2->next) {
if($fil->name =~ m/abc\.txt/) {
$fil->extract($outpath);
}
}

Alternative to "last" in do loops

According to the perl manual for for last (http://perldoc.perl.org/functions/last.html), last can't be used to break out of do {} loops, but it doesn't mention an alternative. The script I'm maintaining has this structure:
do {
...
if (...)
{
...
last;
}
} while (...);
and I'm pretty sure he wants to go to the end of the loop, but its actually exiting the current subroutine, so I need to either change the last or refactor the whole loop if there is a better way that someone can recommend.
Wrap the do "loop" in a bare block (which is a loop):
{
do {
...
if (...)
{
...
last;
}
} while (...);
}
This works for last and redo, but not next; for that place the bare block inside the do block:
do {{
...
if (...)
{
...
next;
}
...
}} while (...);
do BLOCK while (EXPR) is funny in that do is not really a loop structure. So, last, next, and redo are not supposed to be used there. Get rid of the last and adjust the EXPR to evaluate false when that situation is found.
Also, turn on strict, which should give you at least a warning here.
Never a fan of do/while loops in Perl. the do isn't really a loop which is why last won't break out of it. In our old Pascal daze you couldn't exit a loop in the middle because that would be wrong according to the sage Niklaus "One entrance/one exit" Wirth. Therefore, we had to create an exit flag. In Perl it'd look something like this:
my $endFlag = 0;
do {
...
if (...)
{
...
$endFlag = 1;
}
} while ((...) and (not $endFlag));
Now, you can see while Pascal never caught on.
Why not just use a while loop?
while (...) {
...
if (...) {
last;
}
}
You might have to change your logic slightly to accommodate the fact that your test is at the beginning instead of end of your loop, but that should be trivial.
By the way, you actually CAN break out of a Pascal loop if you're using Delphi, and Delphi DID catch on for a little while until Microsoft wised up and came out with the .net languages.
# "http://perldoc.perl.org/functions/last.html":
last cannot be used to exit a block that returns a value such as eval {} , sub {} or do {} , and should not be used to exit a grep() or map() operation.
So, use a boolean in the 'while()' and set it where you have 'last'...
Late to the party - I've been messing with for(;;) recently. In my rudimentary testing, for conditional expressions A and B, what you want to do with:
do {
last if A;
} while(B);
can be accomplished as:
for(;; B || last) {
last if A;
}
A bit ugly, but perhaps not more so than the other workarounds :) . An example:
my $i=1;
for(;; $i<=3 || last) {
print "$i ";
++$i;
}
Outputs 1 2 3. And you can combine the increment if you want:
my $i=1;
for(;; ++$i, $i<=3 || last) {
print "$i ";
}
(using || because it has higher precedence than ,)

How can I cleanly handle error checking in Perl?

I have a Perl routine that manages error checking. There are about 10 different checks and some are nested, based on prior success. These are typically not exceptional cases where I would need to croak/die. Also, once an error occurs, there's no point in running through the rest of the checks.
However, I can't seem to think of a neat way to solve this issue except by using something analogous to the following horrid hack:
sub lots_of_checks
{
if(failcond)
{
goto failstate:
}
elsif(failcond2)
{
goto failstate;
}
#This continues on and on until...
return 1; #O happy day!
failstate:
return 0; #Dead...
}
What I would prefer to be able to do would be something like so:
do
{
if(failcond)
{
last;
}
#...
};
An empty return statement is a better way of returning false from a Perl sub than returning 0. The latter value will actually be true in list context:
sub lots_of_checks {
return if fail_condition_1;
return if fail_condition_2;
# ...
return 1;
}
Perhaps you want to have a look at the following articles about exception handling in perl5:
perl.com: Object Oriented Exception Handling in Perl
perlfoundation.com: Exception Handling in Perl
You absolutely can do what you prefer.
Check: {
last Check
if failcond1;
last Check
if failcond2;
success();
}
Why would you not use exceptions? Any case where the normal flow of the code should not be followed is an exception. Using "return" or "goto" is really the same thing, just more "not what you want".
(What you really want are continuations, which "return", "goto", "last", and "throw" are all special cases of. While Perl does not have full continuations, we do have escape continuations; see http://metacpan.org/pod/Continuation::Escape)
In your code example, you write:
do
{
if(failcond)
{
last;
}
#...
};
This is probably the same as:
eval {
if(failcond){
die 'failcond';
}
}
If you want to be tricky and ignore other exceptions:
my $magic = [];
eval {
if(failcond){
die $magic;
}
}
if ($# != $magic) {
die; # rethrow
}
Or, you can use the Continuation::Escape module mentioned above. But
there is no reason to ignore exceptions; it is perfectly acceptable
to use them this way.
Given your example, I'd write it this way:
sub lots_of_checks {
local $_ = shift; # You can use 'my' here in 5.10+
return if /condition1/;
return if /condition2/;
# etc.
return 1;
}
Note the bare return instead of return 0. This is usually better because it respects context; the value will be undef in scalar context and () (the empty list) in list context.
If you want to hold to a single-exit point (which is slightly un-Perlish), you can do it without resorting to goto. As the documentation for last states:
... a block by itself is semantically identical to a loop that executes once.
Thus "last" can be used to effect an early exit out of such a block.
sub lots_of_checks {
local $_ = shift;
my $all_clear;
{
last if /condition1/;
last if /condition2/;
# ...
$all_clear = 1; # only set if all checks pass
}
return unless $all_clear;
return 1;
}
If you want to keep your single in/single out structure, you can modify the other suggestions slightly to get:
sub lots_of_checks
{
goto failstate if failcond1;
goto failstate if failcond2;
# This continues on and on until...
return 1; # O happy day!
failstate:
# Any clean up code here.
return; # Dead...
}
IMO, Perl's use of the statement modifier form "return if EXPR" makes guard clauses more readable than they are in C. When you first see the line, you know that you have a guard clause. This feature is often denigrated, but in this case I am quite fond of it.
Using the goto with the statement modifier retains the clarity, and reduces clutter, while it preserves your single exit code style. I've used this form when I had complex clean up to do after failing validation for a routine.