Vim: sort al use statements inside a php file - php

I'll like to learn how to select all lines that starts with use, inside current php file, and then sort them. Until now: I've worked with :sort command. Also, ... I've remapped sort command:
map <Leader>s :sort<CR>
But I'll like to create a complex function that select all use statements inside a php file, and after that, that sort all that lines.
I know how to sort. But I have no idea of what is the way to select some arbitrary group of strings with VimL
function! SortUseStatements()
let g:select='/^use .*$<CR>V' !?!?!?!?!?!?!?!?!?
exec g:select
endfunction
map <F2> :call SortUseStatements()<CR>
I know that I want to execute commands like:
go to the beginning of current file
sarch first ^use .*;$ statement
start selection
go to the end of current file
sarch last ^use .*;$ statement
and finally, run :sort

This can be neatly done with :help cmdline-ranges.
You want the search to start at the beginning of the file, so your initial address is 0 (to start before the first line). Then, search for the first line beginning with use. When separated with ; the cursor position will be set to that line before interpreting the next line specifier. Then, you need to navigate to the last of the use statements (starting from the first use line, so again separated by ;). I first choose an easy way that searches for an empty line, and then takes the previous one. With :print, you can check that the range is fine before replacing the command with :sort:
:0;/^use /;/^$/-1 print
If there's no empty line after the use block, you have to use a more complex pattern for any line not starting with use:
:0;/^use /;/^\(use \)\#!/-1 print
Alternatives
For anything more complex, a single :range probably won't do. I would then determine the start and end line numbers separately, using let lnum = search(...) with appropriate patterns. Then you can insert the numbers into an Ex command via :execute startLnum . ',' . endLnum . 'sort'

Related

Read, sort and split text file into blocks

I am trying to re-activate my php knowledge for the following task:
I have a larger textfile containing unsorted lines of comma separated informations, each value enclosed by a '"'.
Each line can be understood as a single dataset, the first value of the line tells me in which table the row belongs.
Now I need to read the file, sort the lines (so that the lines belonging to the same table are together), detect the different blocks and save them in seperate text files. After that, I can do a fast import into a mysql database using load data from infile..
So, I can open the file and sort the lines via this:
<?php
$lines = file("importfile_unsorted.txt");
natsort($lines);
file_put_contents("importfile_sorted.txt", implode($lines));
?>
This works. But now I get stucked. importfile_sorted.txt looks like this:
"AV1","0","0","0","0","0","0","0","0","0","0","0:0","0:0","0:0"
"AV2","0","0","0","0","0","0","0","0","0","0","0:0","0:0","0:0"
.... [this would be the first block, all these lines should be saved in "av.txt"
In the next line the new block "F" begins with several lines:
"F1","D","D","Deutsch",,,"0","W"
"F4","E","E","Englisch",,,"0","W"
"F7","K","K","Kath.Religionslehre",,,"0","W"
"F8","Ev","Ev","Evang.Religionslehre",,,"0","W"
"F9","Eth","Eth","Ethik",,,"0","W"
... [save all these lines beginning with Fxx into file f.txt and go to the next blocks]
"G1","PhL","PÜG"
"G2","ChL","ChÜ"
..
"K1","5a","5a",,"304","Ma","Wei","0","16","16","5",,,,,"1","1","0",,"0","0","0","0"
"K2","5b","5b",,"303","Wo","Hm","0","32","16","5",,,,,"1","1","0",,"0","0","0","0"
"K3","5c","5c",,"302","Gr","Ro","0","32","16","5",,,,,"1","1","0",,"0","0","0","0"
... and so on. Later, there are blocks with a fixed first column like this:
"PL","Di 1","Ba","Q12","Inf1","CoR1"
"PL","Di 1","Bb","Q12","F","Ü2"
"PL","Di 1","Eg","Q12","L","M23"
...
and
"PLS","Di 1","Am"," frei "
"PLS","Di 1","Bad"," ----"
"PLS","Di 1","Bk"," frei "
...
followed by several other blocks (L1... L97, M, R1... R40, U1... U560).
I know all possible "identifiers" (AVx, Fx, Gx, .. PL, PLS..) of the blocks, but it is also possible that a block is omitted and the input file does not a single line of it at all.
The input file contains about 4000 lines all together, so performance should not be too low (although it's not time-critical, the import is done maybe 10 times a year..).
So, is there a way of getting this done in a "smart" and fast way or should I read the input file line by line, detect and remember the first value, add the current line to a result string and loop until a new first value occurs?
Thanks for your help!
Heiko
Use the built in CSV parser, don't split this manually
http://php.net/manual/en/function.str-getcsv.php

PHP order by length but ignore characters

I am changing a php plugin and having a hard time to get the sorting of the array it pulls from the database right. As of now I have it like:
order by LENGTH(name), name
Which gets me close but not right. It outputs like so:
8.2-11
8.2-12
8.2-13
8.2-14
8.2-13-A
Which I understand because 8.2-13-A is longer than 8.2-13 so it will be at the end. How can I ignore the -A or -B so the two 8.2-13's are right after each other?
You could try to find the last occurance of the - sign by using something like:
LENGTH(name) - LOCATE("-", REVERSE(name))
With this information it should be possible to only use a substring of the original string like:
ORDER BY LENGTH(SUBSTRING(name, (LENGTH(name) - LOCATE("-", REVERSE(name))))), SUBSTRING(name, (LENGTH(name) - LOCATE("-", REVERSE(name))))
BUT: I'm pretty sure this could have severe influence on the performance.
Maybe it's a better idea to implement a solution with a stored procedure or do this directly in php.

How to easily generate debugging statements for PHP code?

I need to be able to generate debugging statements for my code. For example, here is some code I have:
$this->R->radius_ft = $this->TC->diameter / 24;
$this->R->TBETA2_rad = $this->D->beta2 / $rad; //Outer angle
$this->R->TBETA1_rad = $this->R->inner_beta1 / $rad; //Inner angle
I need to be able display results of computations so that they can be read by a human.
So far I have been doing this (example showing first line from above only):
$this->R->radius_ft = $this->TC->diameter / 24;
if (self::DEBUG)
print("radius_ft({$this->R->radius_ft}) = diameter({$this->TC->diameter}) / 24");
The above print something like radius_ft(1.4583) = diameter(35) / 24 and a few of those lines looks like equations and are nicely traceable when I want to verify things on paper, or if I want to expose the intermediate work of the computations to someone else.
The problem is that it is a pain to construct those debugging statements. I craft them by hand, and usually it is not a problem, but in my current example, there are hundreds of lines of code where this needs to be done. Much pain.
I was wondering if there are facilities in PHP that will allow me to make print-outs of statements showing what each line of code does. Or methods to semi-automate creating the debug lines for me.
I have so far discovered this method to cut down on some of the work .... use Macro facilities of a text editor.
Paste line of code into TextPad (or similar editor that supports macros). Record macro and use Search, Mark and Copy facilities to carefully navigate between special symbols of the variable, such as $, >, and symbols that are not alphanumeric or $, >, etc. while copying and extracting and pasting parts of variable to craft my particular statement.
Exact steps may differ for one's needs. My macro operates on one variable like $this->R->radius_ft with cursor at the start and ends up with something like radius_ft({$this->R->radius_ft}), with cursor a few chars after the end, sometimes coinciding with the next variable to process.
Perhaps same could be done with regular expressions but I like the way Macro does it - I can process a variable and go to the next one and just repeat the macro with a hot key combination. This takes out the most tedious chunk of work for me.
Alternatively - hand the person the code and let them figure it out. Teach them how to read code.

PHP - Script to manipulate/replace function parameters in a PHP file?

I'm writing a script (in PHP) which will go through a PHP file, find all instances of a function, replace the function name with another name, and manipulate the parameters. I'm using get_file_contents() then strpos() to find the positions of the function, but I'm trying to find a good way to extract the parameters once I know the position of the start of the function. Right now I'm just using loop which walks through the next characters in the file string and counts the number of opening and closing parentheses. Once it closes the function parameters it quits and passes back the string of parameters. Unfortunately, runs into trouble with quotes enclosing parentheses (i.e. function_name(')', 3)). I could just count quotes too, but then I have to deal with escaped quotes, different types of quotes, etc.
Is there a good way to, knowing the start of the function, to grab the string of parameters reliably? Thank you much!
EDIT:
In case i didn't read the question carefully, if you want to only get function parameters,you can see these example :
$content_file = 'function func_name($param_1=\'\',$param_2=\'\'){';
preg_match('/function func_name\((.*)\{/',$content_file,$match_case);
print_r($match_case);
but if you want to manipulate the function, read below.
How about these :
read file using file_get_contents();
use preg_match_all(); to get all function inside that file.
please not that i write /*[new_function]*/ inside that file to identify EOF.
I use this to dynamically add/ delete function without have to open that php files.
Practically, it should be like this :
//I use codeigniter read_file(); function to read the file.
//$content_file = read_file('path_to/some_php_file.php');
//i dont know whether these line below will work.
$content_file = file_get_content('path_to/some_php_file.php');
//get all function inside php file.
preg_match_all('/function (.*)\(/',$content_file,$match_case);
//
//function name u want to get
$search_f_name = 'some_function_name';
//
for($i=0;$i<count($match_case[1]);$i++){
if(trim($match_case[1][$i]) == $search_f_name){
break;
}
}
//get end position by using next function start position
if($i!=count($match_case[1])-1){
$next_function= $match_case[1][$i+1];
$get_end_pos = strripos($content_file,'function '.$next_function);
} else {
//Please not that i write /*[new_function]*/ at the end of my php file
//before php closing tag ( ?> ) to identify EOF.
$get_end_pos = strripos($content_file,'/*[new_function]*/');
}
//get start position
$get_pos = strripos($content_file,'function '.$search_f_name);
//get function string
$func_string = substr($content_file,$get_pos,$get_end_pos-$get_pos);
you can do echo $func_string; to know whether these code is running well or not.
Use a real parser, like this one:
https://github.com/nikic/PHP-Parser
Using this library, you can manipulate the source code as a tree of "node" objects, rather than as a string, and write it back out.

VIM: Show PHP function / class in command line?

Is there any way to show the current PHP function or class name in the VIM command line? I found a plugin for showing C function names in the status line but it does not work for PHP and in any case I prefer the command line be used to save valuable vertical lines.
Thanks.
EDIT
While looking for something completely unrelated in TagList's help I've just found these two functions:
Tlist_Get_Tagname_By_Line()
Tlist_Get_Tag_Prototype_By_Line()
Adding this in my statusbar works beautifully:
%{Tlist_Get_Tagname_By_Line()}
Also, did you read the Vim Wiki? It has a bunch of tips trying to adress the same need. There is also this (untested) plugin.
ENDEDIT
If you are short on vertical space maybe you won't mind using a bit of horizontal space?
TagList and TagBar both show a vertical list of the tags used in the current buffer (and other opened documents in TagList's case) that you can use to navigate your code.
However, I'm not particularly a fan of having all sorts of informations (list of files, VCS status, list of tags, list of buffers/tabs…) displayed at all times: being able to read the name of the function you are in is only useful when you actually need to know it, otherwise it's clutter. Vim's own [{ followed by <C-o> are enough for me.
I don't know anything about PHP, and I'm not trying to step on anyone's toes, but having looked at some PHP code I came up with this function which I think takes a simpler approach than the plugins that have been mentioned.
My assumpmtion is that PHP functions are declared using the syntax function MyFunction(){} and classes declared using class MyClass{} (possibly preceded by public). The following function searches backwards from the cursor position to find the most recently declared class or function (and sets startline). Then we search forward for the first {, and find the matching }, setting endline. If the starting cursor line is inbetween startline and endline, we return the startline text. Otherwise we return an empty string.
function! PHP_Cursor_Position()
let pos = getpos(".")
let curline = pos[1]
let win = winsaveview()
let decl = ""
let startline = search('^\s*\(public\)\=\s*\(function\|class\)\s*\w\+','cbW')
call search('{','cW')
sil exe "normal %"
let endline = line(".")
if curline >= startline && curline <= endline
let decl = getline(startline)
endif
call cursor(pos)
call winrestview(win)
return decl
endfunction
set statusline=%{PHP_Cursor_Position()}
Because it returns nothing when it is outside a function/class, it does not display erroneous code on the statusline, as the suggested plugin does.
Of course, I may well be oversimplifying the problem, in which case ignore me, but this seems like a sensible approach.

Categories