Display unknown types. Replace tab with spaces - clic - Clic is an command line interactive client for gopher written in Common LISP
HTML git clone git://bitreich.org/clic/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/clic/
DIR Log
DIR Files
DIR Refs
DIR Tags
DIR README
DIR LICENSE
---
DIR commit 25487c3c561873fda304042df02ed8c68575ce20
DIR parent 165bb9a2db7f522d83e612c35b24a19d5b673517
HTML Author: Solene Rapenne <solene@perso.pw>
Date: Thu, 28 Dec 2017 11:45:34 +0100
Display unknown types. Replace tab with spaces
Diffstat:
M clic.lisp | 314 ++++++++++++++++---------------
1 file changed, 160 insertions(+), 154 deletions(-)
---
DIR diff --git a/clic.lisp b/clic.lisp
@@ -62,7 +62,7 @@
;;; List of allowed item types
(defparameter *allowed-selectors*
(list "0" "1" "2" "3" "4" "5" "6" "i"
- "h" "7" "8" "9" "+" "T" "g" "I"))
+ "h" "7" "8" "9" "+" "T" "g" "I"))
;;;; BEGIN CUSTOMIZABLE
;;; keep files visited on disk when t
@@ -78,7 +78,7 @@
(defun add-color(name type hue)
"Storing a ANSI color string into *colors*"
(setf (gethash name *colors*)
- (format nil "~a[~a;~am" #\Escape type hue)))
+ (format nil "~a[~a;~am" #\Escape type hue)))
(defun get-color(name) (gethash name *colors*))
(add-color 'red 1 31)
@@ -112,118 +112,124 @@
"this function split a string with separator and return a list"
(let ((text (concatenate 'string text (string separator))))
(loop for char across text
- counting char into count
- when (char= char separator)
- collect
- ;; we look at the position of the left separator from right to left
- (let ((left-separator-position (position separator text :from-end t :end (- count 1))))
- (subseq text
- ;; if we can't find a separator at the left of the current, then it's the start of
- ;; the string
- (if left-separator-position (+ 1 left-separator-position) 0)
- (- count 1))))))
+ counting char into count
+ when (char= char separator)
+ collect
+ ;; we look at the position of the left separator from right to left
+ (let ((left-separator-position (position separator text :from-end t :end (- count 1))))
+ (subseq text
+ ;; if we can't find a separator at the left of the current, then it's the start of
+ ;; the string
+ (if left-separator-position (+ 1 left-separator-position) 0)
+ (- count 1))))))
(defun formatted-output(line)
"Used to display gopher response with color one line at a time"
(let ((line-type (subseq line 0 1))
- (infos (split (subseq line 1) #\Tab)))
+ (infos (split (subseq line 1) #\Tab)))
- ;; see RFC 1436
- ;; section 3.8
- (when (and
- (= (length infos) 4)
- (member line-type *allowed-selectors* :test #'equal))
+ ;; if split worked
+ (when (= (length infos) 4)
(let ((line-number (+ 1 (hash-table-count *links*)))
- (text (car infos))
- (uri (cadr infos))
- (host (caddr infos))
- (port (parse-integer (cadddr infos))))
-
- ;; RFC, page 4
- (check "i"
- (print-with-color text))
-
- ;; 0 text file
- (check "0"
- (setf (gethash line-number *links*)
- (make-location :host host :port port :uri uri :type line-type ))
- (print-with-color text 'file line-number))
-
- ;; 1 directory
- (check "1"
- (setf (gethash line-number *links*)
- (make-location :host host :port port :uri uri :type line-type ))
- (print-with-color text 'folder line-number))
-
- ;; 2 CSO phone-book
- ;; WE SKIP
- (check "2")
-
- ;; 3 Error
- (check "3"
- (print-with-color "error" 'red line-number))
-
- ;; 4 BinHexed Mac file
- (check "4"
- (print-with-color text))
-
- ;; 5 DOS Binary archive
- (check "5"
- (print-with-color "selector 5 not implemented" 'red))
-
- ;; 6 Unix uuencoded file
- (check "6"
- (print-with-color "selector 6 not implemented" 'red))
-
- ;; 7 Index search server
- (check "7"
- (print-with-color "selector 7 not implemented" 'red))
-
- ;; 8 Telnet session
- (check "8"
- (print-with-color "selector 8 not implemented" 'red))
-
- ;; 9 Binary
- (check "9"
- (print-with-color "selector 9 not implemented" 'red))
-
- ;; + redundant server
- (check "+"
- (print-with-color "selector + not implemented" 'red))
-
- ;; T text based tn3270 session
- (check "T"
- (print-with-color "selector T not implemented" 'red))
-
- ;; g GIF file
- (check "g"
- (print-with-color "selector g not implemented" 'red))
-
- ;; I image
- (check "I"
- (print-with-color "selector I not implemented" 'red))
-
- ;; h http link
- (check "h"
- (print-with-color (concatenate 'string
- text " " uri)
- 'http "url"))))))
+ (text (car infos))
+ (uri (cadr infos))
+ (host (caddr infos))
+ (port (parse-integer (cadddr infos))))
+
+ ;; see RFC 1436
+ ;; section 3.8
+ (if (member line-type *allowed-selectors* :test #'equal)
+ (progn
+
+ ;; RFC, page 4
+ (check "i"
+ (print-with-color text))
+
+ ;; 0 text file
+ (check "0"
+ (setf (gethash line-number *links*)
+ (make-location :host host :port port :uri uri :type line-type ))
+ (print-with-color text 'file line-number))
+
+ ;; 1 directory
+ (check "1"
+ (setf (gethash line-number *links*)
+ (make-location :host host :port port :uri uri :type line-type ))
+ (print-with-color text 'folder line-number))
+
+ ;; 2 CSO phone-book
+ ;; WE SKIP
+ (check "2")
+
+ ;; 3 Error
+ (check "3"
+ (print-with-color "error" 'red line-number))
+
+ ;; 4 BinHexed Mac file
+ (check "4"
+ (print-with-color text))
+
+ ;; 5 DOS Binary archive
+ (check "5"
+ (print-with-color "selector 5 not implemented" 'red))
+
+ ;; 6 Unix uuencoded file
+ (check "6"
+ (print-with-color "selector 6 not implemented" 'red))
+
+ ;; 7 Index search server
+ (check "7"
+ (print-with-color "selector 7 not implemented" 'red))
+
+ ;; 8 Telnet session
+ (check "8"
+ (print-with-color "selector 8 not implemented" 'red))
+
+ ;; 9 Binary
+ (check "9"
+ (print-with-color "selector 9 not implemented" 'red))
+
+ ;; + redundant server
+ (check "+"
+ (print-with-color "selector + not implemented" 'red))
+
+ ;; T text based tn3270 session
+ (check "T"
+ (print-with-color "selector T not implemented" 'red))
+
+ ;; g GIF file
+ (check "g"
+ (print-with-color "selector g not implemented" 'red))
+
+ ;; I image
+ (check "I"
+ (print-with-color "selector I not implemented" 'red))
+
+ ;; h http link
+ (check "h"
+ (print-with-color (concatenate 'string
+ text " " uri)
+ 'http "url")))
+ ;; unknown type
+ (print-with-color (format nil
+ "invalid type ~a : ~a" line-type text)
+ 'red))))))
(defun getpage(host port uri)
"connect and display"
;; we reset the buffer
(setf *buffer*
- (make-array 200
- :fill-pointer 0
- :initial-element nil
- :adjustable t))
+ (make-array 200
+ :fill-pointer 0
+ :initial-element nil
+ :adjustable t))
;; we prepare informations about the connection
(let* ((address (sb-bsd-sockets:get-host-by-name host))
- (host (car (sb-bsd-sockets:host-ent-addresses address)))
- (socket (make-instance 'sb-bsd-sockets:inet-socket :type :stream :protocol :tcp)))
+ (host (car (sb-bsd-sockets:host-ent-addresses address)))
+ (socket (make-instance 'sb-bsd-sockets:inet-socket :type :stream :protocol :tcp)))
(sb-bsd-sockets:socket-connect socket host port)
@@ -237,9 +243,9 @@
;; for each line we receive we display it
(loop for line = (read-line stream nil nil)
- while line
- do
- (vector-push line *buffer*)))))
+ while line
+ do
+ (vector-push line *buffer*)))))
(defun g(key)
"browse to the N-th link"
@@ -263,14 +269,14 @@
"Restore the bookmark from file"
(when (probe-file *bookmark-file*)
(with-open-file (x *bookmark-file* :direction :input)
- (setf *bookmarks* (read x)))))
+ (setf *bookmarks* (read x)))))
(defun save-bookmark()
"Dump the bookmark to file"
(with-open-file (x *bookmark-file*
- :direction :output
- :if-does-not-exist :create
- :if-exists :supersede)
+ :direction :output
+ :if-does-not-exist :create
+ :if-exists :supersede)
(print *bookmarks* x)))
(defun add-bookmark()
@@ -289,13 +295,13 @@
while bookmark
do
(progn
- (setf (gethash line-number *links*) bookmark)
- (print-with-color (concatenate 'string
- (location-host bookmark)
- " "
- (location-type bookmark)
- (location-uri bookmark))
- 'file line-number))))
+ (setf (gethash line-number *links*) bookmark)
+ (print-with-color (concatenate 'string
+ (location-host bookmark)
+ " "
+ (location-type bookmark)
+ (location-uri bookmark))
+ 'file line-number))))
(defun help-shell()
"show help for the shell"
(format t "number : go to link n~%")
@@ -310,13 +316,13 @@
(defun parse-url(url)
"parse a gopher url and return a location"
(let ((url (if (and
- ;; if it contains more chars than gopher://
- (<= (length "gopher://") (length url))
- ;; if it starts with gopher// with return without it
- (string= "gopher://" (subseq url 0 9)))
- ;; we keep the url as is
- (subseq url 9)
- url)))
+ ;; if it contains more chars than gopher://
+ (<= (length "gopher://") (length url))
+ ;; if it starts with gopher// with return without it
+ (string= "gopher://" (subseq url 0 9)))
+ ;; we keep the url as is
+ (subseq url 9)
+ url)))
;; splitting by / to get host:port and uri
(let ((infos (split url #\/)))
@@ -324,20 +330,20 @@
;; splitting host and port to get them
(let ((host-port (split (pop infos) #\:)))
- ;; create the location to visit
- (make-location :host (pop host-port)
+ ;; create the location to visit
+ (make-location :host (pop host-port)
- ;; default to port 70 if not supplied
- :port (if host-port
- (parse-integer (car host-port))
- 70)
+ ;; default to port 70 if not supplied
+ :port (if host-port
+ (parse-integer (car host-port))
+ 70)
- ;; if type is empty we use "1"
- :type (let ((type (pop infos)))
- (if (< 0 (length type)) type "1"))
+ ;; if type is empty we use "1"
+ :type (let ((type (pop infos)))
+ (if (< 0 (length type)) type "1"))
- ;; glue remaining args between them
- :uri (format nil "~{/~a~}" infos))))))
+ ;; glue remaining args between them
+ :uri (format nil "~{/~a~}" infos))))))
(defun get-argv()
@@ -450,8 +456,8 @@
"visit a location"
(getpage (location-host destination)
- (location-port destination)
- (location-uri destination))
+ (location-port destination)
+ (location-uri destination))
;; we reset the links table ONLY if we have a new folder
(when (string= "1" (location-type destination))
@@ -462,21 +468,21 @@
(when *offline*
(let ((path (concatenate 'string
- "history/" (location-host destination)
- "/" (location-uri destination) "/")))
+ "history/" (location-host destination)
+ "/" (location-uri destination) "/")))
(ensure-directories-exist path)
(with-open-file
- (save-offline (concatenate
- 'string path (location-type destination))
- :direction :output
- :if-does-not-exist :create
- :if-exists :supersede)
+ (save-offline (concatenate
+ 'string path (location-type destination))
+ :direction :output
+ :if-does-not-exist :create
+ :if-exists :supersede)
- (loop for line across *buffer*
- while line
- do
- (format save-offline "~a~%" line)))))
+ (loop for line across *buffer*
+ while line
+ do
+ (format save-offline "~a~%" line)))))
(display-buffer (location-type destination)))
@@ -489,24 +495,24 @@
;; we loop until X or Q is typed
(loop for input = (format nil "~a" (read-line nil nil))
while (not (or
- (string= "exit" input)
- (string= "x" input)
- (string= "q" input)))
+ (string= "exit" input)
+ (string= "x" input)
+ (string= "q" input)))
do
(when (eq 'end (user-input input))
- (loop-finish))
+ (loop-finish))
(format t "clic => ")
(force-output)))
(defun main()
"fetch argument, display page and go to shell if type is 1"
(let ((destination
- (let ((argv (get-argv)))
- (if argv
- ;; url as argument
- (parse-url argv)
- ;; default url
- (make-location :host "gopherproject.org" :port 70 :uri "/" :type "1")))))
+ (let ((argv (get-argv)))
+ (if argv
+ ;; url as argument
+ (parse-url argv)
+ ;; default url
+ (make-location :host "gopherproject.org" :port 70 :uri "/" :type "1")))))
;; if user want to drop from first page we need
;; to look it here
@@ -514,7 +520,7 @@
;; we continue to the shell if the type was 1 and we are in a terminal
(when (and (ttyp)
(string= "1" (location-type destination)))
- (shell)))))
+ (shell)))))
;; we allow ecl to use a new kind of argument
;; not sure how it works but that works