Page 3 of 7
Re: User Functions Exchange
Posted: 03 May 2015 16:14
by binocular222
nerdweed wrote:Is there any default include file which is always loaded? If not, how can we call UDF's from outside (like AHK) as the include wouldn't work in a one liner and without the include statement, the function definition is unknown.
See my wish here
http://www.xyplorer.com/xyfc/viewtopic. ... 90#p122589, seems everyone ignored it
Re: User Functions Exchange
Posted: 03 May 2015 17:30
by bdeshi
The include command still requires a complete line for itself.
But wait, the function cmd also had this requirement, but it was lifted last ver. Good things come to those who wait... ... good things, including inline include.
Re: User Functions Exchange
Posted: 07 May 2015 08:30
by highend
Code: Select all
// Convert a roman literal into an arabic number
// Derived from http://rosettacode.org/wiki/Roman_numerals/Decode#AutoHotkey
function romanToArabic($roman) {
if (!$roman || !regexmatches(trim($roman, " <tab>"), "^(M{0,4})(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$")) { return 0; }
$result = 0;
while ($i++ < strlen($roman)) {
$curChar = recase(substr($roman, $i - 1, 1));
$curNum = replacelist($curChar, "i,v,x,l,c,d,m", "1,5,10,50,100,500,1000", ",");
if ($curNum > $oldNum && $oldNum) {
$result = $result - 2 * $oldNum;
}
$result = $result + $curNum;
$oldNum = $curNum;
}
return $result;
}
// Convert an arabic number into a roman literal
// Returns an empty string if the number is not in range (1-3999)
// Derived from http://rosettacode.org/wiki/Roman_numerals/Encode#AutoHotkey
function arabicToRoman($number) {
$romans = "M,CM,D,CD,C,XC,L,XL,X,IX,V,IV,I";
$decimals = "1000,900,500,400,100,90,50,40,10,9,5,4,1";
$number = trim($number, " <tab>");
if (!$number || $number > 3999 || !regexmatches($number, "^\d+$")) { return; }
$result = "";
$i = 1;
foreach($roman, $romans, ",") {
$decimal = gettoken($decimals, $i, ",");
while ($number >= $decimal) {
$result = $result . $roman;
$number = $number - $decimal;
}
$i++;
}
return $result;
}
Re: User Functions Exchange
Posted: 07 May 2015 20:35
by highend
A minor (but in my daily workflow an important) one...
regexescape(): Escape a string for a regexmatch / -replace
Code: Select all
function regexEscape($string) {
return regexreplace($string, "([\\^$.+*|?(){\[])", "\$1");
}
Code: Select all
text regexEscape("C:\Temp\Mix.Song (One $) + [OLD] {delete it}.mp3");
// Output: C:\\Temp\\Mix\.Song \(One \$\) \+ \[OLD] \{delete it}\.mp3
Re: User Functions Exchange
Posted: 08 May 2015 11:01
by bdeshi
And here's a similar one I have to use often.
Escapes special html characters in a string, so the string can be faithfully displayed in a html page.
Code: Select all
FUNCTION htmlescape($str, $crlf = 0) {
/* Escape special html [markup] characeters in a string,
* to display it correctly in an html page.
* $str the string to Escape
* $crlf escape linebreaks (with <br>) */
// & has to be the 1st replacement
$str = replace($str, '&', '&');
$str = replace($str, '<', '<');
$str = replace($str, '>', '>');
$str = replace($str, '"', '"');
// escape consecutive spaces. This can be "freezy", so disabled
// $str = regexreplace($str, ' (?= )', ' ');
if ($crlf == 1) { $str = replace($str, <crlf>, '<br>'); }
return $str;
}
The original, slower version is below.
replacelist() is far slower than separate replace() calls.
Code: Select all
FUNCTION htmlescape($str, $crlf = 0) {
/* Escape special html [markup] characeters in a string,
* to display it correctly in an html page.
* $str the string to Escape
* $crlf escape linebreaks (with <br>) */
// & has to be the 1st replacement
$str = replacelist($str,'&|<|>|"', '&|<|>|"', '|');
// escape consecutive spaces. This can be "freezy", so disabled
// $str = regexreplace($str, ' (?= )', ' ');
if ($crlf == 1) { $str = replace($str, <crlf>, '<br>'); }
return $str;
}
[/size]
Re: User Functions Exchange
Posted: 16 May 2015 07:13
by bdeshi
allstrpos(haystack, needle, start, matchcase, rel) : Returns all positions of a substring, separated by pipe.
The Return is similar to regular strpos(), but for negative start position. Details in function comment.
function
Code: Select all
function allstrpos($haystack, $needle, $start = 0, $matchcase = 0, $rel = 0){
/* Return |-separated positions of all occurrences of $needle in $haystack.
** $haystack string to search in
** $needle string to search for
** [$start=0] 0-based start position to start search
** if negative, search is started from end, omitting abs($start) chars
** **NOTE**: $start = '-' starts searching from end, without omission
** 0 : start from lefmost char, - : start from rightmost char
** [$matchcase=0] case-sensitivity of search. Any value other than 0 is accepted as 1.
** [$rel=0] return position relative to $start. Any value other than 0 is 1.
** if $start is negative, positions are returned from end
** Returns -1 on no match, or '' on errors -- errors returned in global $G_UDF_lasterr
*/
//vErrodication -- this section can be removed safely if input validity is ensured.
global $G_UDF_lasterr;
if($haystack=='')||($needle=='')||(($start!='-')&&(($start!=0))&&($start*1==0))
{$r=='';$G_UDF_lasterr=$G_UDF_lasterr.'allstrpos()::BADPARAM;';}if($r==''){return $r;}
//^Errodication
if ($start > strlen($haystack)) { return '-1' ; } //ends function
$return = ''; $inv = 0; $len = 0; $start = ($start == '-') ? $start : round($start) ;
if ($start<0||$start=='-') { $haystack = substr($haystack,, ($start=='-')?'':$start);
$inv = 1; $start = 0; $len = strlen($haystack); }
$matchcase = (round($matchcase) != 0) ? 1 : 0 ;
$rel = (round($rel) == 1) ? ($start + $len - $inv) : 0 ;
$pos = strpos($haystack, $needle, $start, $matchcase) ;
if ($pos != -1) {
$ndlen = strlen($needle) ;
while ($pos != -1) {
$return = $return . abs(($pos - $rel)) . '|' ;
$pos = strpos($haystack, $needle, ($pos + $ndlen), $matchcase) ;
}
} else { $return = -1 ; }
if ($inv == 1) { $fmt = 've'; } else { $fmt = 'e'; }
$return = formatlist($return, $fmt);
return $return ;
}
call (assuming allstrpos() is saved in <xyscripts>\inc\allstrpos.xyi)
Code: Select all
INCLUDE "inc\allstrpos.xyi"
"allstrpos test"
text allstrpos('3.1415', '1'); //2|4
text allstrpos('3.1415', '1','-',,1); //1|3
text allstrpos('abcdef','def',2,,1); //1
Re: User Functions Exchange
Posted: 04 Jun 2015 19:35
by highend
Code: Select all
/* *****************************************************************
* Returns the index of one / multiple tab(s)
* Returns "0" if no index is found
* Parameter(s):
* $mode: c (caption = default), p (path), n (name), d (data)
* $side: l (left = default), r (right) -> Count from left / right side on
* $ret : f (first only = default), a (all) -> Which index to return
* $sep : "|" (default) -> Separator for multiple indexes
* Example(s):
* list of tab captions = "D:\|C:\|F:\|C:\"
* text getTabIndex("C:\", "c", "r", "a");
* Output: 4|2
* text getTabIndex("C:\");
* Output: 2
***************************************************************** */
function getTabIndex($str, $mode="c", $side="l", $ret="f", $sep="|") {
if !($str) { return 0; }
$mode = replacelist($mode, "c|d|p|n", "caption|data|path|name", "|");
$tabCount = tab("get", "count");
if ($side == "l") { $i = 1; $op = "+"; $cmp = ">"; $cmpVal = $tabCount; }
elseif ($side == "r") { $i = $tabCount; $op = "-"; $cmp = "<="; $cmpVal = 0; }
$retVal = "";
while (true) {
if (eval($i $cmp $cmpVal)) { break; }
if ($str LikeI tab("get", $mode, $i)) {
if ($ret == "f") { return $i; }
elseif ($ret == "a") { $retVal = $retVal . $i . $sep; }
}
$i = eval($i $op 1);
}
return ($retVal) ? trim($retVal, $sep, "R") : 0;
}
Re: User Functions Exchange
Posted: 06 Jun 2015 19:47
by bdeshi
a simple one:
swap($a, $b). Swaps the values of $a and $b. This has no return data but modifies the passed variables. Think of it as a command when using.
Code: Select all
FUNCTION swap(&$a, &$b) { $c = $a; $a = $b; $b = $c; unset $c; }
call
Code: Select all
$a=1;$b=2; swap($a,$b); echo '$a is now: '.$a.<crlf>.'$b is now: '.$b ;
Why? hide those menial steps.
Re: User Functions Exchange
Posted: 10 Jun 2015 12:00
by highend
Sometimes I want to get a range of tokens (e.g. 2-5) from a string...
Code: Select all
/* *****************************************************************
* Returns a range of tokens
* Returns an empty string if your values are out of bounds
* Parameter(s) are the same as in the original gettoken() function
* Two exceptions:
* There is no $flag parameter. It's autoset to 2 internally
* $count: 1 = default -> This defines how many tokens you want to return
* Example(s):
* $tokens = "C:\|D:\|E:\|F:\|G:\";
* text getTokenRange($tokens, 2, 3, "|");
* Output: D:\|E:\|F:\
* text getTokenRange($tokens, 3, , "|"); // Equals original function
* Output: E:\
***************************************************************** */
function GetTokenRange($str, $index=1, $count=1, $sep=" ", $format="") {
if ($count > 1) {
$str = gettoken($str, $index, $sep, $format, 2);
$str = gettoken($str, $count, $sep, , 1);
return $str;
}
return gettoken($str, $index, $sep, $format);
}
Re: User Functions Exchange
Posted: 11 Jun 2015 08:02
by waqu
Convert milliseconds to hh:mm:ss.fff
Code: Select all
function mstime ($ms) {
$fff = $ms % 1000;
$ms = $ms \ 1000;
$ss = $ms % 60;
$ms = ($ms - $ss) / 60;
$mm = $ms % 60;
$hh = ($ms - $mm) / 60;
$hh = format ("$hh", "00");
$mm = format ("$mm", "00");
$ss = format ("$ss", "00");
$fff = format ("$fff", "000");
return "$hh:$mm:$ss.$fff";
}
Re: User Functions Exchange
Posted: 11 Jun 2015 11:05
by PeterH
I think instead of $in=($in - $ms) / 1000; it would be shorter to say $in=$in \ 1000;
(Integer division, cuts fractions, no rounding.)
I think
Code: Select all
$ms = $in % 1000;
$in = $in \ 1000;
even looks better
Re: User Functions Exchange
Posted: 14 Jun 2015 18:37
by bdeshi
in() : checks whether a token (or tokens) exists in a tokenlist. Returns either 1 or 0. (Intended for conditionals)
function codeCode: Select all
FUNCTION in($token, $tokenlist, $separator='|', $matchcase=0) {
/*Returns 1 if $token exists in $tokenlist, else returns 0
** PARAMTERS
** token token to search. Can itself be a list
** of tokens, separated by $separator.
** tokenlist the list of tokens to search in
** separator separator between tokens in tokenlist
** matchcase 0=case-insensitive, 1=case-sensitive
**
** RETURN
** 1 if $token if found, 0 otherwise
**
** NOTE
** if $token itself is a token list, then each of it's
** "subtokens" are searched, and if all is found, then
** return is 1; if even one is not found, return is 0.
*/
if (strpos($token, $separator)==-1){
$return = gettokenindex($token, $tokenlist, $separator,
(($matchcase==1) ? '' : 'i') .'');
}
else {
foreach ($atoken, $token, $separator) {
$return = gettokenindex($atoken, $tokenlist, $separator,
(($matchcase==1) ?'' :'i') . '');
if ($return == 0){ break; } //no match, stop, return 0
}
}
return ($return>0)?1:0;
}
call
assuming the function is saved in <xyscripts>\inc\in.xyiCode: Select all
INCLUDE 'inc\in.xyi';
"in() test"
$token = 'bat'; $tokens = 'cmd|bat|sh|vbs|wsh';
if (in($token, $tokens)==1) {echo "it's all in tokens!"; }
$token = 'bat|cpp'; $tokens = 'cmd|bat|sh|vbs|wsh';
if (in($token, $tokens)==0) {echo "it's not all in tokens!"; }
here's an alternative lightweight in() that does not try to match multiple tokens in $token
Code: Select all
//lightweight in(), no mulittoken
FUNCTION in($token, $tokenlist, $separator='|', $matchcase=0){
/*Returns 1 if $token exists in $tokenlist, else returns 0*/
$return = gettokenindex($token, $tokenlist, $separator,
(($matchcase==1) ? '' : 'i') .'');
return ($return>0)?1:0;
}
Re: User Functions Exchange
Posted: 02 Jul 2015 00:01
by Marco
Code: Select all
function sqrt($num) {
// Returns the square root of a positive number in base 10.
// Any other argument causes the function to throw an error.
// The result has machine precision.
// Based on the Babylonian algorithm (see https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method).
//
// $num the positive number in base 10 to calculate the square root of
assert regexmatches("$num", "[^0-9.,]") == "", "Argument is not a positive number";
$num = eval($num);
if ($num >= 100) {
$root = $num/20;
} elseif ($num >= 2) {
$root = $num/2;
} elseif ($num >= 2/100) {
$root = $num;
} else {
$root = $num*10;
};
while ($root != $root_prev) {
$root_prev = $root;
$root = ($root + $num/$root)/2;
};
return $root;
}
Re: User Functions Exchange
Posted: 02 Jul 2015 00:53
by highend
Don't get me wrong Marco but imho this can be solved in a (probably) more elegant way.
I left out your assert & regexmatches command (because I hope a user is intelligent enough to feed it with a correct value):
Or, did I miss anything (which should be obvious)?
Code: Select all
function sqrt($num) { return eval($num) ^ (1/2); }
Re: User Functions Exchange
Posted: 02 Jul 2015 00:59
by Marco