Modify PHP_Beautifier in Vim to not strip empty lines - php

Just finished incorporating PHP_Beautifier into Vim and the fact that it removes whitespace irks me. Apparently it's a bug since 2007. There is a hack to fix this problem, but it leads to other problems. Instead I decided to use a round about method.
First Convert multiple blank lines to a single blank line via the command as suggested here
:g/^\_$\n\_^$/d
Next Convert all blank lines to something unique like so (make sure it does not get changed during beautification)
:%s/^[\ \t]*\n/$x = 'It puts the lotion on the skin';\r/ge
Next Call PHP_Beautifier like so
:% ! php_beautifier --filters "ArrayNested() IndentStyles(style=k&r) NewLines(before=if:switch:foreach:else:T_CLASS,after=T_COMMENT:function)"<CR>
Finally Change all unique lines back to empty lines like so
:%s/$x='It puts the lotion on the skin';//ge
All four work when I tested them independently. I also have the third step mapped to my F8 key like so
map <F8> :% ! php_beautifier --filters "ArrayNested() IndentStyles(style=k&r) NewLines(before=if:switch:foreach:else:T_CLASS,after=T_COMMENT:function)"<CR>
But when I try to string the commands together via the pipe symbol, like so (I padded the pipes with whitespace to better show the different commands)
map <F8> :g/^\_$\n\_^$/d | %s/^[\ \t]*\n/$x = 'It puts the lotion on the skin';\r/ge | % ! php_beautifier --filters "ArrayNested() IndentStyles(style=k&r) NewLines(before=if:switch:foreach:else:T_CLASS,after=T_COMMENT:function)" | %s/$x = 'It puts the lotion on the skin';//ge<CR>
I get the following error
Error detected while processing /home/xxx/.vimrc:
line 105:
E749: empty buffer
E482: Can't create file /tmp/vZ6LPjd/0
Press ENTER or type command to continue
How do I bind these multiple commands to a key, in this case F8.
Thanks to ib's answer, I finally got this to work. If anyone is having this same problem, just copy this script into your .vimrc file
func! ParsePHP()
:exe 'g/^\_$\n\_^$/d'
:%s/^[\ \t]*\n/$x = 'It puts the lotion on the skin';\r/ge
:exe '%!php_beautifier --filters "ArrayNested() IndentStyles(style=k&r)"'
:%s/$x = 'It puts the lotion on the skin';//ge
endfunc
map <F8> :call ParsePHP()<CR>

For some Ex commands, including :global and :!, a bar symbol (|) is
interpreted as a part of a command's argument (see :help :bar for the full
list). To chain two commands, the first of which allows a bar symbol in its
arguments, use the :execute command.
:exe 'g/^\_$\n\_^$/d' |
\ %s/^[\ \t]*\n/$x = 'It puts the lotion on the skin';\r/ge |
\ exe '%!php_beautifier --filters "ArrayNested() IndentStyles(style=k&r) NewLines(before=if:switch:foreach:else:T_CLASS,after=T_COMMENT:function)"' |
\ %s/$x = 'It puts the lotion on the skin';//ge

Related

Laravel Route List (php artisan route:list) Displaying Middleware on New Lines

I have noticed recently a change in the way that my Laravel project is rendering the route list in the terminal. It is no longer comma separating the middleware column, and if there is more than one middleware it will add it to a new blank row in the table underneath its parent route.
This may seem like a very trivial problem, however being relatively new to laravel and this being my first proper project I have been producing with it I am firstly concerned that there could be an issue with the laravel install somehow that may cause other issues elsewhere, and the more routes I add with various middleware, the table when displaying all routes is becoming rather difficult to interoperate, where this was not an issue before.
See below a screenshot of the route table filtered to show only a select number of the routes in my project in order to give you an idea of what I am seeing.
Would anyone know why this has changed, and if there is a way to get it back to displaying it as it was before, by keeping all the middleware on the row with all the other data, and comma separating them.
On a whim, I have tried the following in the console, and they have made no difference:
php artisan cache:clear
php artisan routes:clear
php artisan config:clear
To be clear, what I expect to see is something like this:
I have since been informed that Laravel updated this a few days ago in their framework:
https://github.com/laravel/framework/pull/32993
It was as a result of this issue being raised:
https://github.com/laravel/framework/issues/33041
If you want to add semicolon again
Go to your project file vendor\laravel\framework\src\Illuminate\Foundation\Console
then open file RouteListCommand.php
search for function getMiddleware
protected function getMiddleware($route)
{
return collect($this->router->gatherRouteMiddleware($route))->map(function ($middleware) {
return $middleware instanceof Closure ? 'Closure' : $middleware;
})->implode("\n");
}
just change \n to , in implode
I added a cross-platform one-liner workaround that prints one row per route to the GitHub issue (more details there):
php artisan route:list | perl -pe 's/\x1b\[[0-9;]*[mG]//g' | perl -0777 -pe 's/ +\|(\r\n?|\n)/\n/g' | perl -0777 -pe 's/(\r\n?|\n)(\| +){6}/, /g'
Breakdown:
# strip control characters: https://superuser.com/a/561105
# strip trailing whitespace and pipe character, substituting newline with \0 during processing via -0
# strip leading pipes and whitespace before middleware column, substituting newline with \0 during processing via -0
php artisan route:list | \
perl -pe 's/\x1b\[[0-9;]*[mG]//g' | \
perl -0pe 's/ +\|(\r\n?|\n)/\n/g' | \
perl -0pe 's/(\r\n?|\n)(\| +){6}/, /g'
Here is the fix, if you are still facing issues in Laravel 8 with Sanctum.
I have replacedon this line
return collect($this->router->gatherRouteMiddleware($route))->map
with this line on
return collect($route->gatherMiddleware())->map
in Laravel's core file. Usually, this is not recommended, but I need a solution. You can also try if needed.
For more details, please visit the below link and refer to my comment on this page.
https://github.com/laravel/framework/commit/7ebd21193df520d78269d7abd740537a2fae889e

Command Prompt Width Within PHP

I'm running PHP on a Windows Server and I have a script that uses PowerShell to perform some WMI queries. I'm taking the results of the query and exploding it by line break so that each property of the WMI class is its own line (and later will be used for other stuff).
The problem I'm having is that by default, the command prompt window width is limited to 80 characters so when the PHP script obtains the results of the WMI query, certain lines that exceed 80 characters are broken up into numerous lines and I'd really like each line to only be one line regardless of how long the string is.
I've tried logging into the server and changing the default width of the command prompt as well as both 32- and 64-bit PowerShell windows. When I run the commands directly in those applications, I can see it's no longer breaking on 80 characters. However, my PHP script still does.
Here's a snippet of my code:
exec("powershell.exe -Command \" & { Get-WmiObject -Query 'Select * From Win32OperatingSystem' | Format-List *} \" ", $Output, $ReturnValue);
foreach ($Output as $PSOutput) {
$ExplodePSOutput = explode("\r\n", $PSOutput);
foreach ($ExplodePSOutput as $WMIProperty) {
echo $WMIProperty."<br>";
}
}
Here's an example of what the output is like:
Status : OK
Name : Microsoft Windows 10 Enterprise|C:\
WINDOWS|\Device\Harddisk0\Partition
2
FreePhysicalMemory : 9224968
But I'm wanting it to look like this:
Status : OK
Name : Microsoft Windows 10 Enterprise|C:\WINDOWS|\Device\Harddisk0\Partition2
FreePhysicalMemory : 9224968
Update:
My ultimate goal was to extract each property name from the selected WMI class. Since each property named was followed with " : ", I was able to work around this problem by searching each exploded string for this pattern and returning the value to the left of that. If that pattern doesn't exist, it's presumably a line that was broken because it went over the 80 character limit.
$PatternPosition = strpos($WMIPropertyResult, " : ");
$WMIPropertyName = substr($WMIPropertyResult, 0, $PatternPosition);
PowerShell formats the output to align all of the property values but it formats it based on the longest property name and property names will obviously change based on what WMI class is being queried. So it makes more sense to search for the " : " pattern instead of hardcoding a value in the substr() function.
I'll leave this post around in case anyone has a suggestion on the original question but for my use case, I believe I have a sufficient workaround.

Simple Zpl printing not working?

I have this in test.txt
CT~~CD,~CC^~CT~^XA~TA000~JSN^LT0^MNW^MTT^PON^PMN^LH0,0^JMA^PR6,6~SD15^JUS^LRN^CI0^XZ^XA^MMT^PW508^LL0203^LS0^BY4,3,138^FT48,155^BCN,,Y,N^FD>;12^FS^PQ1,0,1,Y^XZ
and I use the Zpl printer Google chrome add-on
On my mac in terminal I tried (after some ls)
lp -d zpl test.txt
All i get is 26 labels with error messages
ERROR: requested label 0, but there are only 0 labels
I also tried
lp -d zpl test.txt -o position=top-left,ppi=203,landscape
still 26 labels
But I expected something like this (but I have different label dimensions)
Few things I can find in your code.
Firstly
CT~~CD,~CC^~CT~^XA~TA000~JSN^LT0^MNW^MTT^PON^PMN^LH0,0^JMA^PR6,6~SD15^JUS^LRN^CI0^XZ^
This is an invalid label and the XA and XZ are telling the printer that this is one label (you really have two labels above, 2 pairs XA to start and XZ to end). Put just that part in an online zpl viewer and you will see the invalid with the same error. Your data is actually in the second portion of your code. Take out the middle ^XZ and ^XA and leave the first ^XA and ending ^XZ. Your code should work then.
Also FYI you don't need CT~~CD,~CC^~CT~ along with much of other parts of your code. These commands are telling the printer to change the control characters, however you telling them to change them to the default. example CT = change tilde then you put to tilde, and CC = change carot to carot etc.....

PHP exec very slow processing simple 3-pipe grep

I've read here and cannot really understand how to speed up my simple exec() which basically looks like this:
zcat access_log.201312011745.gz | grep 'id=6' | grep 'id2=10' | head -n10
I've added ini_set('memory_limit', 256); to the top of the PHP document, but the script still takes about 1 minute to run (contrasted with about near instant completion in Penguinet). What can I do to improve it?
I would try some of the following:
Change your exec to just run somethig simple, like
echo Hello
and see if it still takes so long - if it does, the problem is in the process creation and exec()ing area.
If that runs quickly, try changing the exec to something like:
zcat access_log.201312011745.gz > /dev/null
to see if it is the "zcat" slowing you down
Think about replacing the greps with a "sed" that quits (using "q") as soon as it finds what you are looking for rather than continuing all the way to end of file - since it seems (by your "head") you are only interested in the first few, not all occurrences of your strings. For example, you seem to be looking for lines that contain "id=6" and also "id2=10", so if you used "sed" like below, it may be faster because "sed" will print it and stop immediately the moment it finds a line with "id=6" followed by "id2=10"
zcat access_log.201312011745.gz | sed -n '/id=2.*id2=10/p;q'
The "-n" says "don't print, in general" and then it looks for "id=2" followed by any characters then "id2=10". If it finds that, it prints the line and the "q" makes it quit immediately without looking through to end of file. Note that I am assuming "id=2" comes before "id2=10" on the line. If that is not true, the "sed" will need additional work.

Asterisk full log parser

I want to make a log parser for for an Asterisk PBX, but don't know where to start.
I figured it out what i need from the log. the lines that i need look like this:
[Apr 12 11:11:56] VERBOSE[3359] logger.c: -- Called 111
the number in VERBOSE[....] are the same for 1 call.
The first thing that i have to do is get the lines that contain that VERBOSE number so i can identify that call. the second thing is to read the text, there are some standard texts so it won't be hard to recognize.
The thing is that i would like to read it real time (the file is written real time), and display it in a webpage. PHP or Ajax.
The thing that i want to do is, show up rows in a webpage as users call. and the new call to be added under the current/answered call.
Any tips, examples would be great.
Thanks,
Sebastian
I would do it in 2 programs that can work as simple CGI programs.
First program parses log and show date and call identifier. Such identifier will be link to 2nd program. In Python you can use regexp:
# 1st group - date, 2nd - callid
RX_VERBOSE = re.compile(r'(.*) VERBOSE\[(\d+)\] ')
def make_link(call_id):
return(' <a href="show_call.cgi?call_id=%d>%d</a>' % (call_id, call_id))
def show_calls(logfn):
call_ids = []
f = open(logfn)
for line in f:
rx = RX_VERBOSE.search(line)
if rx:
call_id = int(rx.group(2))
if not call_id in call_ids:
print('%s %s' % (rx.group(1), make_link(call_id)))
call_ids.append(call_id)
f.close()
This program will show the lines that has call identifier:
def show_call_datails(logfn, call_id):
search_str = ' VERBOSE[%s] ' % call_id
f = open(logfn)
for line in f:
if search_str in line:
print(line.rstrip())
f.close()

Categories