Readline completion tab extra space - php

I'm trying to set auto-complete for readline to enable a user to navigate through the filesystem directories when running a script through CLI.
I found out PHP has a function called readline_completion_function for this purpose but every time I hit tab to complete a word, it adds a space at the end.
readline_completion_function(function() {
return ['aaa', 'bbb', 'ccc'];
});
// Input a or b or c
readline('Add char and tab: ');
I've create fiddle for you to test this:
https://repl.it/#rmdev/Readline-Completion-Tab-Extra-Space
I saw on Python readline configs that there's a configuration called set_completer_delims to set a character to be apendend after tab is hit but in PHP there are only two configurations and none of them apply to the completer delims.
I also saw some posts referring to this as a known bug but it seems it has been fixed on most of the integrations although I don't see any reference to a fix for the PHP one.
Is there any way to remove this space?
I'm using PHP 7.2.12 on a Mac.

Related

Clear php-a line history

When i run php -a It brings up a handy shell for testing code quickly along with a history of every line I type. Is there any way to clear this history?
Using php 5.5.9 if this makes any difference
On my linux laptop, there's a ~/.php_history that contains the ... history.
For clear history you can use readline_clear_history()
readline_clear_history ( void );
This function clears the entire command line history.
Return Values
Returns TRUE on success or FALSE on failure.
For Windows users, you can find the .php_history file in your home directory as well. I found mine at C:\Users\{my_name}\.php_history

Using vim-quickrun for "PHP REPL style"

I'm trying to get some "repl-like" feature for PHP, inside vim.
Basically, what I want is to be able to visually select a part of my script, execute it, and see the result in a separate buffer.
But I don't want to execute the whole current file (so :!php % doesn't do the trick ...)
I found the vim-quickrun plugin, which seems to greatly fit that need, but can't make it work and when looking for more documentation, most of the result I get are in japanese (I don't speak japanese :( ... )
For now, I have installed the plugin via Vundle, but have not added any extra configuration to my .vimrc
From inside a file, I can type
...
echo 'hello quickrun sh test'
...
=> visual select the date line, and type
:QuickRun sh
I got my hello world printed, all fine
But if I do
...
echo 'hellow quickrun php'
...
=> visual select ...
:QuickRun php
I just get a buffer with just the same text that I typed, no execution ...
Does someone already achieved something like this ?
Thanks a lot !
EDIT :
PHP is correctly added to my PATH. Added the 2 config lines suggested below ... Sadly, it doesn't change anything :(
You need to put the php flags around your php code, like any php script (it always starts in plain text mode):
...
<?php
echo 'hellow quickrun php';
?>
....
Then you can select only one part with QuickRun, but don't forget to select the flags as well.
I don't use that plugin, but I think you need to configure something like this in your ~/.vimrc:
let g:quickrun_config = {}
let g:quickrun_config.php = {'command' : 'php'}
and have the php executable in your PATH.
The following solution does not use vim-quickrun but allows you to visually select, execute and see the result just as you like. You need vim-slime with phpsh :
First, install the vim-slime plugin. It allows to send lines and visually selected chunks of code from VIM to a screen or tmux session.
Now install screen: On Ubuntu, do sudo apt-get install screen.
Open a terminal and start screen with a session name: screen -S sessionname.
Open a second terminal and start vim. Write some code, visually select it and press <C-c><C-c>, that is two times CTRL+C. You will be asked for the session name, use sessionname as before. The selected lines will be sent to the first terminal just as if you had written them directly there.
To make use of this functionality, you need to start an interactive PHP shell in the first terminal, such as phpsh.

MongooseIM module not getting variables from Packet

I wrote the following module for MongooseIM but nothing is posted to the PHP file.
start(_Host, _Opt) ->
inets:start(),
ejabberd_hooks:add(user_send_packet, _Host, ?MODULE, fetchPacketData, 50).
stop (_Host) ->
ejabberd_hooks:delete(user_send_packet, _Host, ?MODULE, fetchPacketData, 50).
fetchPacketData(_From, _To, Packet) ->
To = xml:get_tag_attr_s(<<"to">>, Packet),
httpc:request(post, {"http://example.com/receiver.php",[],
"application/x-www-form-urlencoded",
lists:concat(["To=",To,"&Type=1","&Body=ABC"])}, [], []).
I was able to successfully implement the module after following erszcz's suggestion(Please see below). Below is the code i used. Hope it helps someone else too :)
start(Host, _Opts)->
inets:start(),
ejabberd_hooks:add(user_send_packet, Host, ?MODULE, sendMessage, 50),
ok.
stop(Host)->
ejabberd_hooks:delete(user_send_packet, Host, ?MODULE, sendMessage, 50),
ok.
sendMessage(_From, _To, Packet) ->
case xml:get_tag_attr_s(<<"type">>, Packet) of
<<"chat">> ->
To = lists:flatten(io_lib:format("~s", [xml:get_tag_attr_s(<<"to">>, Packet)])),
** post variables to PHP file using httpc:request **
ok;
_ ->
ok
end.
offline_message_hook is only called when the server is routing a message to a user who is not online. user_send_packet is run every time the server receives a stanza from a client. This might explain why the handler is not run, though it depends on how you test. There's an article with one section describing some hooks in MongooseIM available on the official wiki.
As for problems with retrieving packet attributes, either logging the incoming packet for inspection or using dbg in the server Erlang shell to trace the actual calls done by your module might be the way to tell what's happening.
An example session with dbg debugging the problem might look like this:
(mongooseim#localhost)1> dbg:tracer().
{ok,<0.570.0>}
(mongooseim#localhost)2> dbg:p(all, call).
{ok,[{matched,mongooseim#localhost,279}]}
(mongooseim#localhost)3> dbg:tpl(mod_test, x).
{ok,[{matched,mongooseim#localhost,5},{saved,x}]}
(mongooseim#localhost)4> (<0.576.0>) call mod_test:fetchPacketData({jid,<<"alice">>,<<"localhost">>,<<"escalus-default-resource">>,<<"alice">>,
<<"localhost">>,<<"escalus-default-resource">>},{jid,<<"alice">>,<<"localhost">>,<<>>,<<"alice">>,<<"localhost">>,<<>>},{xmlel,<<"presence">>,[{<<"xml:lang">>,<<"en">>}],[]})
(<0.576.0>) exception_from {mod_test,fetchPacketData,3} {error,function_clause}
2015-03-15 11:46:03.028 [error] <0.576.0>#ejabberd_hooks:run1:240 {function_clause,[{lists,thing_to_list,[<<>>],[{file,"lists.erl"},{line,601}]},{lists,flatmap,2,[{file,"lists.erl"},{line,1248}]},{lists,flatmap,2,[{file,"lists.erl"},{line,1248}]},{mod_test,fetchPacketData,3,[{file,"src/mod_test.erl"},{line,15}]},{safely,apply,3,[{file,"src/safely.erl"},{line,19}]},{ejabberd_hooks,run1,3,[{file,"src/ejabberd_hooks.erl"},{line,236}]},{ejabberd_c2s,session_established2,2,[{file,"src/ejabberd_c2s.erl"},{line,1063}]},{p1_fsm_old,handle_msg,10,[{file,"src/p1_fsm_old.erl"},{line,542}]}]}
Running hook: {user_send_packet,[{jid,<<"alice">>,<<"localhost">>,<<"escalus-default-resource">>,<<"alice">>,<<"localhost">>,<<"escalus-default-resource">>},{jid,<<"alice">>,<<"localhost">>,<<>>,<<"alice">>,<<"localhost">>,<<>>},{xmlel,<<"presence">>,[{<<"xml:lang">>,<<"en">>}],[]}]}
Callback: mod_test:fetchPacketData
We see that the handler errors out with function_clause when calling lists:thing_to_list(<<>>). The empty binary is a result of xml:get_tag_attr_s/2 when the attribute asked for is not found. lists:thing_to_list/1 is called to convert each parameter of lists:concat/1 to a list, but it's not possible to convert an empty binary <<>> to a list, hence the crash.
Match on the result of xml:get_tag_attr_s/2 and craft your logic appropriately to each case: when the attribute is found and when it's not there.
I don't know how to start a module in dbg. I tried what you had shared above and I think you missed the 4th command which could be an example of how to initiate a module.
This is a raw dump of my console without any edits - I did not miss any part.
You don't "start a module in dbg." You simply start a module the usual way and then use dbg from the server shell.
What I did was I took your example code, put it into apps/ejabberd/src/mod_test.erl file and built a release. After that you can enable the module either in ejabberd.cfg of the release (look for the modules section and do it similarly as examples there show) or you can start the server in live mode with mongooseimctl live and start the module manually with gen_mod:start_module(<<"localhost">>, mod_test, []) (where <<"localhost">> is just an example XMPP domain - substitute your own suitable domain there).
When the module is running (can be checked with gen_mod:is_loaded(<<"your-xmpp-domain">>, mod_name_goes_here)) you have to enable dbg. This is shown in the listing I added previously. I won't delve into describing how to use dbg as a very good introduction is already available on StackOverflow.
an example of how to test if an attribute exists or not
case xml:get_tag_attr_s(<<"some-attribute">>, Packet) of
<<>> ->
%% attribute does not exist, as get_tag_attr_s returned the default value
ok;
<<"some-value">> ->
%% do something sensible with <<"some-value">>
ok
end
Alternatively, you can use exml which is also part of MongooseIM (but not original ejabberd) and is more explicit about not finding the attribute you ask for:
case exml_query:attr(Packet, <<"some-attribute">>) of
undefined ->
%% not found
ok;
<<"some-value">> ->
%% do something
...
end

Get windows title using php doesn't work on browser call

My problem is I need to fetch FOOBAR2000's title because that including information of playing file, so I create a execute file via Win32 API(GetWindowText(), EnumWindows()) and it's working good.
TCHAR SearchText[MAX_LOADSTRING] = _T("foobar2000");
BOOL CALLBACK WorkerProc(HWND hwnd, LPARAM lParam)
{
TCHAR buffer[MAX_TITLESTRING];
GetWindowText(hwnd, buffer, MAX_TITLESTRING);
if(_tcsstr(buffer, SearchText))
{
// find it output something
}
return TRUE;
}
EnumWindows(WorkerProc, NULL);
Output would look like "album artis title .... [foobar2000 v1.1.5]"
I created a php file like test.php, and use exec() to execute it.
exec("foobar.exe");
then in console(cmd) I use command to execute it
php test.php
It's working good too, same output like before.
Now I use browser(firefox) to call this php file(test.php), strange things happened.
The output only foobar2000 v1.1.5, others information gone ...
I think maybe is exec() problem? priority or some limitation, so I use C# to create a COM Object and register it, and rewrite php code
$mydll = new COM("FOOBAR_COMObject.FOOBAR_Class");
echo $mydll->GetFooBarTitle();
still same result, command line OK, but browser Fail.
My question is
Why have 2 different output between command line and browser. I can't figure it out.
How can I get correct output via browser.
or there is a easy way to fetch FOOBAR2000's title?
Does anyone have experience on this problem?
== 2012/11/28 edited ==
follow Enno's opinion, I modify http_control plug-in to add filename info, original json info is "track title".
modify as following
state.cpp line 380 add 1 line
+pb_helper1 = pfc::string_filename(pb_item_ptr->get_path());
pb_helper1x = xml_friendly_string(pb_helper1);
# 1: when firefox opens the php and it gets executed, it the context depends on the user which runs the php-container (apache), this is quite different from the commandline call which gets executed in your context
# 2 and 3: there seems to be more than one way for getting the title: use the foobar-sdk and create a module which simply reads the current title per api, then write your result in an static-html-document inside your http-root-folder OR use the http-client inside the sdk, with it, you do not need a wabserver, even better use a already implemented module: for instance foo_upnp or foo-httpcontrol
Good luck!
If your webserver runs as a service, in windows you need to enable "allow desktop interaction" for the service. Your php script runs as a child of the webserver process when requested via browser.

Count number of file requests triggered

Is it possible with PHP(5) or other Linux tools on an apache debian webserver to get the file requests a single http request made?
for performance reasons i would like to compare them with the cached "version" of my cake app.
non-cached that might be over 100 in some views.
cached only up to 10 (hopefully).
afaik there are 3 main file functions:
file_get_contents(), file() and the manual fopen() etc
but i cannot override them so i cannot place a logRequest() function in them.
is there any other way? attaching callbacks to functions? intercepting the file requests?
This suggestion does not seems intuitive, but you can take look on xdebug - function trace
Once you have xdebug installed and enabled, you can using all sort of configuration to save the profiling into a disk file and you can retrieve it later. Such as profiling results for different URL save into different disk file.
To monitoring file system related functions, you can do a parse of the text file(profiling results) and do a count of matchable functions (programmable or manually)
The way I would do it would be to create a custom function that wraps around the one you need.
function custom_file_get_contents($filename) {
$GLOBALS['file_get_contents_count']++;
return file_get_contents($filename);
}
And just replace all of your calls to file_get_contents with custom_file_get_contents. This is just a rudimentary example, but you get the idea.
Side note, if you want to count how many files your script has included (or required), see get_included_files()
You can use Xdebug to log all function calls
Those so-called "function traces" can be a help for when you are new to an application or when you are trying to figure out what exactly is going on when your application is running. The function traces can optionally also show the values of variables passed to the functions and methods, and also return values. In the default traces those two elements are not available.
http://www.xdebug.org/docs/execution_trace
Interesting question. I'd start with the stream_wrapper ... try to replace them with custom classes.
There is a pecl extention called ADB (Advanced PHP Debugger) that has tow functions that would be very useful for a cse like this - override_function() and rename_function(). You could do something like this:
rename_function('file_get_contents', 'file_get_contents_orig');
function file_get_contents($filename) {
logRequest();
return file_get_contents_orig($filename);
}
It looks like ADB is pretty easy to install, too.
See http://www.php.net/manual/en/book.apd.php

Categories