Don't even remember.

This commit is contained in:
Jaidyn Lev 2018-12-02 02:26:38 -06:00
parent fe8bba1d3b
commit 722e2f8782
9 changed files with 364 additions and 25 deletions

51
src/date.lisp Normal file
View File

@ -0,0 +1,51 @@
(in-package :nih)
;; UNIVERSAL-TIME --> STRING
(defun iso-time (universal-time)
"Return `universal-time` in ISO 8601 format. :)"
(multiple-value-bind
(second minute hour date month year)
(decode-universal-time universal-time)
(format nil "~A-~A-~A"
year
(min-string-length month 2 :prefix "0")
(min-string-length date 2 :prefix "0"))))
;; NIL --> STRING
(defun get-iso-time ()
"Return the ISO 8601 time of immediately, right here, right now."
(iso-time (get-universal-time)))
;; STRING STRING --> INTEGER
(defun iso-date-distance (iso-date-a iso-date-b)
"Return the number of days between date-a and date-b."
(let* ((a (mapcar #'read-from-string (nih:char-split "-" iso-date-a)))
(year-a (car a)) (month-a (cadr a)) (day-a (caddr a))
(b (mapcar #'read-from-string (nih:char-split "-" iso-date-b)))
(year-b (car b)) (month-b (cadr b)) (day-b (caddr b)))
(+
(* 365 (- year-b year-a))
(- (day-number month-b day-b) (day-number month-a day-a)))))
(defvar month-length
'(31 28 31 30 31 30 31 31 30 31 30 30))
;; INTEGER [INTEGER] --> INTEGER
(defun day-number (month &optional (date 1))
"Return the day-number (of a year) of a month/day combo."
(let ((month-days (reduce #'+ (nih:up-to (- month 2) month-length)))
(date-days date))
(+ month-days date-days)))

35
src/file.lisp Normal file
View File

@ -0,0 +1,35 @@
(in-package :nih)
;; PATH --> STRING
(defun read-file-string (path)
"Read all lines from a file into a string."
(if (file-exists path)
(let ((encoding (asdf-encodings:detect-file-encoding path)))
(with-open-file (fstream path
:direction :input
:external-format encoding)
(line-string
(loop
:for line = (read-line fstream nil)
:while line
:collect line))))))
(defun write-file-string (path string &key
(if-exists :append)
(if-does-not-exist :create))
"Write a string to a file."
(let ((encoding :utf-8))
(if (file-exists path)
(setq encoding (asdf-encodings:detect-file-encoding path)))
(with-open-file (fstream path
:direction :output
:external-format encoding
:if-exists if-exists
:if-does-not-exist if-does-not-exist)
(format fstream "~A" string))))

View File

@ -1,19 +1,19 @@
(in-package :nih) (in-package :nih)
;; ITEM LIST --> DATA_AFTER_ITEM ;; ITEM LIST --> DATA_AFTER_ITEM
(defun following (item list) (defun following (item list &key (test #'eq))
"Return all items following the first instance of ITEM" "Return all items following the first instance of ITEM"
(cdr (up-from (position item list :test #'equal) list))) (cdr (up-from (position item list :test test) list)))
;; ITEM LIST --> DATA_UP_TO_ITEM ;; ITEM LIST --> DATA_UP_TO_ITEM
(defun preceding (item list) (defun preceding (item list &key (test #'eq))
"Return all items preceding the first instance of ITEM" "Return all items preceding the first instance of ITEM"
(reverse (reverse
(cdr (reverse (cdr (reverse
(up-to (position item list :test #'equal) list))))) (up-to (position item list :test test) list)))))
;; ---------------------------------------- ;; ----------------------------------------
@ -93,3 +93,71 @@
(setq i (+ 1 i))) (setq i (+ 1 i)))
stack)) stack))
;; ----------------------------------------
;; LIST --> LIST_OF_ODD-NUMBERED_ITEMS
(defun odds (list)
"Return a list only containing the odd-numbered items of a list."
(let ((stack '())
(i 0))
(loop
:while (< i (length list))
:do
(if (oddp i)
(setq stack (concatenate 'list stack (list (nth i list)))))
(setq i (+ 1 i)))
stack))
;; LIST --> LIST_OF_ODD-NUMBERED_ITEMS
(defun evens (list)
"Return a list only containing the even-numbered items of a list."
(let ((stack '())
(i 0))
(loop
:while (< i (length list))
:do
(if (evenp i)
(setq stack (concatenate 'list stack (list (nth i list)))))
(setq i (+ 1 i)))
stack))
;; ----------------------------------------
;; PLIST PLIST --> PLIST
(defun property-list-merge (plist-a plist-b)
"Merge two property-lists, with plist-a being the canonical one.
Useful for when you have defaults (in plist-a) and modifications to
them (in plist-b), especially for configs."
(let* ((keys (evens plist-a))
(pairs (length keys))
(stack '())
(i 0))
(loop
:while (< i pairs)
:do
(let* ((key (nth i keys))
(a-value (getf plist-a key))
(b-value (getf plist-b key)))
(setq stack
(append stack
(list key (value-or b-value a-value))))
(setq i (+ i 1))))
stack))

View File

@ -49,18 +49,38 @@
(defun random-item (list) (defun random-item (list)
"Return a random item from a list." "Return a random item from a list."
(nth (random (length list)) list)) (if (not list)
nil
(nth (random (length list)) list)))
;; INTEGER LIST --> LIST
(defun random-items (number list)
"Return an amount of random items from a list."
(if (not list)
nil
(let ((item (random-item list)))
(concatenate 'list
(list item)
(if (not (eq number 1))
(random-items (- number 1) (remove item list)))))))
;; FILE_PATH --> BOOLEAN
(defun file-exists (path)
"Return whether or not a file exists."
(if (ignore-errors (file-author path))
'T
nil))
;; UNIVERSAL-TIME --> ISO8601-FORMAT_TIME ;; STREAM --> STRING_OF_ENTIRE_STREAM
(defun iso-time (universal-time) (defun read-line-entire (stream)
"Return `universal-time` in ISO 8601 format. :)" (let* ((cur-line (ignore-errors (read-line stream))))
(multiple-value-bind (cond
(second minute hour date month year) (cur-line
(decode-universal-time universal-time) (string-combine cur-line
(read-line-entire stream)
(format nil "~A-~A-~A" :seperator (format nil "~%")) )
year ('T ""))))
(min-string-length month 2 "0")
(min-string-length date 2 "0"))))

View File

@ -16,17 +16,20 @@
:regex-get-all :regex-get-all
:regex-remove :regex-remove
:regex-remove-all :regex-remove-all
:regex-split
:nil-string :nil-string
:pad-string :pad-string
:min-string-length :min-string-length
:max-string-length
:getf-string :getf-string
:getf-strings :getf-strings
:get-colon-values :get-colon-values
:remove-colon-values :remove-colon-values
:replace-colon-value
;; STRING/WORD ;; STRING/WORD
@ -41,6 +44,8 @@
:word-remove-all :word-remove-all
:word-position :word-position
:word-positions :word-positions
:word-split
:word-length
:word-car :word-car
:word-caar :word-cadddrr :word-cadaar :word-cadr :word-caadr :word-caar :word-cadddrr :word-cadaar :word-cadr :word-caadr
@ -63,6 +68,8 @@
:line-remove-all :line-remove-all
:line-position :line-position
:line-positions :line-positions
:line-split
:line-length
:line-car :line-car
:line-caar :line-cadddrr :line-cadaar :line-cadr :line-caadr :line-caar :line-cadddrr :line-cadaar :line-cadr :line-caadr
@ -83,6 +90,8 @@
:char-remove-all :char-remove-all
:char-position :char-position
:char-positions :char-positions
:char-split
:char-length
:char-car :char-car
:char-caar :char-cadddrr :char-cadaar :char-cadr :char-caadr :char-caar :char-cadddrr :char-cadaar :char-cadr :char-caadr
@ -108,13 +117,37 @@
:replace-at :replace-at
:odds
:evens
:property-list-merge
;; DATE
;; =======================
:iso-time ;; see (local-time:format-timestring nil timestamp)
:get-iso-time
;; see (local-time:format-timestring nil (local-time:universal-to-timestamp)
:iso-date-distance ;; see #'local-time:timestamp-difference
:day-number ;; see #'local-time:format-timestring
:week-number ;; see #'local-time:format-timestring
;; FILE
;; =======================
:read-file-string ;; see #'alexandria:read-file-into-string
:write-file-string ;; see #'alexandria:write-string-into-file
;; MISC ;; MISC
;; ======================= ;; =======================
:random-item :random-item
:random-items
:iso-time :iso-time
:list-or-real :list-or-real
:value-or :value-or
:file-exists
:read-line-entire
:parse-keys)) :parse-keys))

View File

@ -37,6 +37,14 @@
(nth n (char-list string))) (nth n (char-list string)))
;; STRING --> INTEGER
(defun char-length (string)
"Return the length of a string by character."
(length (char-list string)))
;; ---------------------------------------- ;; ----------------------------------------
@ -75,6 +83,14 @@
(positions character (char-list string))) (positions character (char-list string)))
;; CHARACTER STRING --> LIST_OF_STRINGS
(defun char-split (character string)
"Split a string into a list of strings, at a set character."
(regex-split (string character)
(mapcar #'string (char-list string))))
;; ---------------------------------------- ;; ----------------------------------------

View File

@ -30,6 +30,14 @@
(nth n (line-list string))) (nth n (line-list string)))
;; STRING --> INTEGER
(defun line-length (string)
"Return the length of a string in lines."
(length (line-list string)))
;; ---------------------------------------- ;; ----------------------------------------
@ -72,6 +80,13 @@
(positions line (line-list string) :test #'equal)) (positions line (line-list string) :test #'equal))
;; QUERY STRING --> LIST_OF_LINES_SANS_MATCHES
(defun line-split (query string)
"Split a string into a list, seperated by a set line matching a regex query."
(regex-split query (line-list string) (string #\Newline)))
;; ---------------------------------------- ;; ----------------------------------------

View File

@ -87,6 +87,26 @@
(padding "" string suffix))))) (padding "" string suffix)))))
;; STRING INTEGER --> STRING
(defun max-string-length (string length)
"Return a string by splitting it into lines, each line being length long."
(let ((stack "")
(i 0))
(loop
:for char
:across string
:do
(if (eq length i)
(progn
(setq i 0)
(setq stack
(nih:string-combine stack (format nil "~%~A" char))))
(setq stack
(nih:string-combine stack (format nil "~A" char))))
(setq i (+ 1 i)))
stack))
;; STRING DESIRED_LENGTH [PREFIX] [SUFFIX] --> STRING_OF_DESIRED_LENGTH ;; STRING DESIRED_LENGTH [PREFIX] [SUFFIX] --> STRING_OF_DESIRED_LENGTH
(defun min-string-length (string target-length (defun min-string-length (string target-length
@ -188,6 +208,35 @@ Example:
stack)) stack))
;; QUERY LIST_OF_STRINGS --> LIST_SANS_QUERY_MATCHES
(defun regex-split (query list &optional (combiner ""))
"Split a string into a list, seperated by a set item matching a regex query."
(let ((stack '(""))
(i 0))
(loop
:while (< i (length list))
:do
(let ((string (nth i list))
(last-string (car (reverse stack)))
(stack-sans (reverse (cdr (reverse stack)))))
(cond
((ppcre:scan-to-strings query string)
(setq stack (concatenate 'list stack (list ""))))
('T
(setq stack (concatenate 'list stack-sans
(list (string-trim combiner
(string-combine
last-string string
:seperator combiner))))))))
(setq i (+ 1 i)))
(remove "" stack :test #'equal)))
;; ---------------------------------------- ;; ----------------------------------------
@ -268,3 +317,41 @@ Example:
"Remove the colon-variable declaration from a string." "Remove the colon-variable declaration from a string."
(line-remove-all "^:.*" string)) (line-remove-all "^:.*" string))
;; STRING SYMBOL STRING --> STRING
(defun replace-colon-value (string key-string value)
"Replace a colon variable's value."
(let ((existent
(getf (get-colon-values string) (read-from-string key-string))))
(if existent
(line-replace
(line-position
(line-get (string-combine "^" key-string " ") string)
string)
(string-combine key-string value :seperator " ")
string)
(string-combine :seperator (string #\Newline)
string (string-combine key-string " " value)))))
;; -------------------------------------
;; PRIVATE HELPER FUNCTIONS
;; INTEGER STRING STRING --> STRING
(defun line-replace (position new-line string)
"Replace nth line with a new one in a string."
(let* ((line-list (nih:line-split (nih:line-nth position string) string))
(modified-list
(list (car line-list)
new-line
(nih:value-or (cadr line-list) ""))))
(reduce (lambda (a b) (nih:string-combine a b :seperator (format nil "~%")))
modified-list)))

View File

@ -30,6 +30,14 @@
(word-string (nth n (word-list string)))) (word-string (nth n (word-list string))))
;; STRING --> INTEGER
(defun word-length (string)
"Return the length of a string by word."
(length (word-list string)))
;; ---------------------------------------- ;; ----------------------------------------
@ -37,7 +45,7 @@
(defun word-get (query string) (defun word-get (query string)
"Return a word in a string that matches a regex query." "Return a word in a string that matches a regex query."
(word-car (word-get-all query string))) (ignore-errors (word-car (word-get-all query string))))
;; REGEX STRING --> LIST_OF_MATCHING_WORDS ;; REGEX STRING --> LIST_OF_MATCHING_WORDS
(defun word-get-all (query string) (defun word-get-all (query string)
@ -72,6 +80,12 @@
(positions word (word-list string) :test #'equal)) (positions word (word-list string) :test #'equal))
(defun word-split (query string)
"Split a string into a list, seperated by a set word matching a regex query."
(regex-split query (word-list string) " "))
;; ---------------------------------------- ;; ----------------------------------------