;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; util.lisp - a collection of useful functions ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Copyright (C) 2018 Pasquale Frega ; All rights reserved ; http://pasqualefrega.antiblog.com/ ; ; Released under the simplified BSD license ; ; last edit: 10-May-2020 ; ; begin ; (import io (append-all! read-all!)) (import lua/os (tmpname remove execute)) (define _rand_max :hidden 32767) (define _seed :hidden :mutable 1) (define _time :hidden :mutable 1) ; ; Check if the given file exists and is readable ; (defun file-exists? (path) "If the file at PATH exists and is readable returns true otherwise returns false. ### Example ```cl > (file-exists? \"tests/data/this_file_exists\") out = true > (file-exists? \"tests/data/this_file_does_not_exist\") out = false > (file-exists? \"tests/data/this_file_is_not_readable\") out = false ```" (with (_chid (io/open path)) (if (not _chid) false (progn (io/close _chid) true ) ) ) ) ; ; Check if the given file exists and is a directory ; (defun is-dir? (path) "If the file at PATH exists and is a directory returns true otherwise returns false. ### Example ```cl > (is-dir? \"tests/data/this_file_is_dir\") out = true > (is-dir? \"tests/data/this_file_does_not_exist\") out = false > (is-dir? \"tests/data/this_file_is_not_dir_or_is_not_readable\") out = false ```" (if (file-exists? path) (if (append-all! path "") false true ) false ) ) ; ; Attempt to know the hosting Operating System ; (defun OS? () "Attempts to know the Operating System which hosts Urn. ### Example ```cl > (OS?) out = \"Ms Windows\" ```" (let [(_temp_file (tmpname)) (_os nil)] (remove _temp_file) (cond ((string/starts-with? _temp_file "T:") (set! _os "AmigaOS") ) ((string/starts-with? _temp_file "/") (set! _os "UNIX") ) ((eq? (string/char-at _temp_file 2) ":") (set! _os "Ms Windows") ) (true (set! _os "Unknown") ) ) _os ) ) ; ; Execute given command and returns a list with its exit code and its output as string ; (defun execute! (command) "Execute COMMAND and returns a list with its exit code and its output as string. ### Example ```cl > (cadr (execute! \"dir tests/data/\")) out = \"Hello.c \\ Hello.lisp \\ Hello.lua\" > (string/split (cadr (execute! \"dir tests/data/\")) \"\\n\") out = (\"Hello.c \" \"Hello.lisp \" \"Hello.lua \") > (execute! \"echo -n Hello!\") out = (0 \"Hello!\") ```" (let [(_temp_file (tmpname)) (_output nil) (_exit_code nil)] (if (eq? (OS?) "AmigaOS") (set! _exit_code (execute (sprintf "%s >>%s" command _temp_file))) (set! _exit_code (execute (sprintf "%s >>%s 2>&1" command _temp_file))) ) (set! _output (read-all! _temp_file)) (remove _temp_file) (list _exit_code _output) ) ) ; ; Return the size of the given file if possible ; (defun file-size (path) "If the file at PATH exists and is readable returns its size in bytes otherwise returns nil. ### Example ```cl > (file-size \"tests/data/this_file_exists\") out = 1234567890 > (file-size \"tests/data/this_file_does_not_exist\") out = nil > (file-size \"tests/data/this_file_is_not_readable\") out = nil ```" (with (_size nil) (when (file-exists? path) (set! _size (string/len (read-all! path))) ) _size ) ) ; ; Check if the given number is float ; (defun float? (x) "Check whether X is a floating number. ### Example ```cl > (float? 1.1) out = true > (float? 1) out = false ```" (if (and (number? x) (string/match x "%.")) true false ) ) ; ; Check if the given number is integer ; (defun integer? (x) "Check whether X is an integer number. ### Example ```cl > (integer? 1.1) out = false > (integer? 1) out = true ```" (if (and (number? x) (not (string/match x "%."))) true false ) ) ; ; Change _seed value ; (defun rand-seed! (new-seed) "Changes seed value (default 1) used by rand function. ### Example ```cl > (rand-seed! 20180217) out = nil ```" (when (>= new-seed 0) (set! _seed (math/round new-seed)) (set! _time 1) ) ) ; ; Return a pseudo-random number ; (defun rand () "Returns a pseudo-random number (positive integer) from 0 to 32767; using mod operator changes the range and increases random. ### Example ```cl > (rand) ; From 0 to 32767 out = 28513 > (mod (rand) 32768) ; From 0 to 32767 out = 20635 > (mod (rand) 11) ; From 0 to 10 out = 0 > (+ (mod (rand) 6) 5) ; From 5 to 10 out = 8 > (- (mod (rand) 11) 5) ; From -5 to 5 out = -1 > (* (mod (rand) 11) 1.0) ; From 0.0 to 1.0 out = 0.4 ```" (set! _seed (+ _seed _time)) (when (/= _seed _rand_max) (while (< _seed _rand_max) (set! _seed (* _seed (+ _seed 1))) ) (while (>= _seed _rand_max) (set! _seed (- _seed _rand_max)) ) ) (inc! _time) _seed ) ; ; Call YAD (Yet Another Dialog) ; (defun yad (arguments) "Call YAD (Yet Another Dialog). YAD is a program that display GTK+ dialogs and returns (in the exit code and standard output) the user input. Here it gets arguments as string and returns a list with 1st element the exit code and 2nd the standard output. ### Example ```cl > (yad \"--form --field=Name:ro Pasquale --field=Surname:ro Frega\") out = (0 \"Pasquale|Frega|\") ``` See YAD manual for more informations." (let [(_temp_file (tmpname)) (_output nil)] (set! _output (list (execute (sprintf "yad %s >%s" arguments _temp_file)) (string/trim (read-all! _temp_file)))) (remove _temp_file) _output ) ) ; ; end