User Functions Exchange

Discuss and share scripts and script files...
binocular222
Posts: 1416
Joined: 04 Nov 2008 05:35
Location: Hanoi, Vietnam

Re: User Functions Exchange

Post 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
I'm a casual coder using AHK language. All of my xys scripts:
http://www.xyplorer.com/xyfc/viewtopic. ... 243#p82488

bdeshi
Posts: 4249
Joined: 12 Mar 2014 17:27
Location: Asteroid B-612 / Dhaka
Contact:

Re: User Functions Exchange

Post 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.
Icon Names | Onyx | Undocumented Commands | xypcre
[ this user is asleep ]

highend
Posts: 13260
Joined: 06 Feb 2011 00:33

Re: User Functions Exchange

Post 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;
}
One of my scripts helped you out? Please donate via Paypal or paypal_donate (at) stdmail (dot) de

highend
Posts: 13260
Joined: 06 Feb 2011 00:33

Re: User Functions Exchange

Post 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
One of my scripts helped you out? Please donate via Paypal or paypal_donate (at) stdmail (dot) de

bdeshi
Posts: 4249
Joined: 12 Mar 2014 17:27
Location: Asteroid B-612 / Dhaka
Contact:

Re: User Functions Exchange

Post 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, ' (?= )', '&nbsp;');
  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, ' (?= )', '&nbsp;');
  if ($crlf == 1) { $str = replace($str, <crlf>, '<br>'); }
  return $str;
}
[/size]
Icon Names | Onyx | Undocumented Commands | xypcre
[ this user is asleep ]

bdeshi
Posts: 4249
Joined: 12 Mar 2014 17:27
Location: Asteroid B-612 / Dhaka
Contact:

Re: User Functions Exchange

Post 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
Icon Names | Onyx | Undocumented Commands | xypcre
[ this user is asleep ]

highend
Posts: 13260
Joined: 06 Feb 2011 00:33

Re: User Functions Exchange

Post 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;
}
One of my scripts helped you out? Please donate via Paypal or paypal_donate (at) stdmail (dot) de

bdeshi
Posts: 4249
Joined: 12 Mar 2014 17:27
Location: Asteroid B-612 / Dhaka
Contact:

Re: User Functions Exchange

Post 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. :whistle:
Icon Names | Onyx | Undocumented Commands | xypcre
[ this user is asleep ]

highend
Posts: 13260
Joined: 06 Feb 2011 00:33

Re: User Functions Exchange

Post 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);
}
One of my scripts helped you out? Please donate via Paypal or paypal_donate (at) stdmail (dot) de

waqu
Posts: 15
Joined: 04 Jan 2015 05:58
Location: Russia/Saint-Petersburg
Contact:

Re: User Functions Exchange

Post 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";
 }
Last edited by waqu on 17 Aug 2015 17:46, edited 7 times in total.

PeterH
Posts: 2776
Joined: 21 Nov 2005 20:39
Location: Germany

Re: User Functions Exchange

Post 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 :D
W7(x64) SP1 German
( +WXP SP3 )

bdeshi
Posts: 4249
Joined: 12 Mar 2014 17:27
Location: Asteroid B-612 / Dhaka
Contact:

Re: User Functions Exchange

Post by bdeshi »

in() : checks whether a token (or tokens) exists in a tokenlist. Returns either 1 or 0. (Intended for conditionals)

function code

Code: 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.xyi

Code: 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;
}
Icon Names | Onyx | Undocumented Commands | xypcre
[ this user is asleep ]

Marco
Posts: 2347
Joined: 27 Jun 2011 15:20

Re: User Functions Exchange

Post 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;
}
Tag Backup - SimpleUpdater - XYplorer Messenger - The Unofficial XYplorer Archive - Everything in XYplorer
Don sees all [cit. from viewtopic.php?p=124094#p124094]

highend
Posts: 13260
Joined: 06 Feb 2011 00:33

Re: User Functions Exchange

Post 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); }
One of my scripts helped you out? Please donate via Paypal or paypal_donate (at) stdmail (dot) de

Marco
Posts: 2347
Joined: 27 Jun 2011 15:20

Re: User Functions Exchange

Post by Marco »

Oh. My. God. I never thought of that :oops: :oops: :oops: Shame on me, time for some corner time... :oops: :oops: :oops:
(But the eval was necessary because feeding a decimal number with a dot or a comma made a difference)
Tag Backup - SimpleUpdater - XYplorer Messenger - The Unofficial XYplorer Archive - Everything in XYplorer
Don sees all [cit. from viewtopic.php?p=124094#p124094]

Post Reply