Working on new model.
[elpher.git] / elopher.el
index 30383ae..96cd641 100644 (file)
@@ -13,7 +13,6 @@
   "A simple gopher client."
   :group 'applications)
 
-
 (defcustom elopher-index-face '(foreground-color . "cyan")
   "Face used for index records.")
 (defcustom elopher-text-face '(foreground-color . "white")
   "Face used for image records.")
 (defcustom elopher-unknown-face '(foreground-color . "red")
   "Face used for unknown record types.")
-(defcustom elopher-margin-face '(foreground-color . "orange")
-  "Face used for record margin legend.")
+
+;;; Model
+;;
+
+(defun elopher-make-node (parent address &optional content)
+  (list parent address cache))
+
+(defun elopher-node-parent (node)
+  (car node))
+
+(defun elopher-node-address (node)
+  (cadr node))
+
+(defun elopher-node-content (node)
+  (caddr node))
+
+(defun elopher-reload-node (node after)
+  ())
 
 ;;; Global constants
 ;;
@@ -36,7 +51,7 @@
 (defconst elopher-margin-width 6
   "Width of left-hand margin used when rendering indicies.")
 
-(defvar elopher-start-page
+(defconst elopher-start-page
   (concat "i\tfake\tfake\t1\r\n"
           "i--------------------------------------------\tfake\tfake\t1\r\n"
           "i          Elopher Gopher Client             \tfake\tfake\t1\r\n"
           "iTest entries:\tfake\tfake\t1\r\n"
           "pXKCD comic image\t/fun/xkcd/comics/2130/2137/text_entry.png\tgopher.floodgap.com\t70\r\n"))
 
-
 ;;; Mode and keymap
 ;;
 
-(defvar elopher-mode-map
+(setq elopher-mode-map
   (let ((map (make-sparse-keymap)))
     (define-key map (kbd "<tab>") 'elopher-next-link)
     (define-key map (kbd "<S-tab>") 'elopher-prev-link)
-    (define-key map (kbd "u") 'elopher-history-back)
+    (define-key map (kbd "u") 'elopher-pop-history)
     (define-key map (kbd "g") 'elopher-go)
+    (define-key map (kbd "r") 'elopher-reload)
     (when (require 'evil nil t)
       (evil-define-key 'normal map
         (kbd "C-]") 'elopher-follow-closest-link
-        (kbd "C-t") 'elopher-history-back
-        (kbd "u") 'elopher-history-back
-        (kbd "g") 'elopher-go))
-    map)
-  "Keymap for gopher client.")
+        (kbd "C-t") 'elopher-pop-history
+        (kbd "u") 'elopher-pop-history
+        (kbd "g") 'elopher-go
+        (kbd "r") 'elopher-reload))
+    map))
+  ;; "Keymap for gopher client.")
 
 (define-derived-mode elopher-mode special-mode "elopher"
   "Major mode for elopher, an elisp gopher client.")
 ;;; Index rendering
 ;;
 
+(defun elopher-insert-index (string)
+  "Inserts the index corresponding to STRING into the current buffer."
+  (dolist (line (split-string string "\r\n"))
+    (elopher-insert-index-record line)))
+
 (defun elopher-insert-margin (&optional type-name)
   (if type-name
-      (insert (propertize
-               (format (concat "%" (number-to-string elopher-margin-width) "s")
-                       (concat "[" type-name "] "))
-               'face elopher-margin-face))
+      (insert (format (concat "%" (number-to-string elopher-margin-width) "s"
+                              (concat
+                               (propertize "[" 'face '(foreground-color . "blue"))
+                               (propertize type-name 'face '(foreground-color . "white"))
+                               (propertize "]" 'face '(foreground-color . "blue"))))))
     (insert (make-string elopher-margin-width ?\s))))
 
-(defun elopher-render-record (line)
+(defun elopher-insert-index-record (line)
+  "Inserts the index record corresponding to LINE into the current buffer."
   (let* ((type (elt line 0))
          (fields (split-string (substring line 1) "\t"))
          (display-string (elt fields 0))
                               'face elopher-unknown-face))))
     (insert "\n")))
 
-(defvar elopher-incomplete-record "")
-
-(defun elopher-render-complete-records (string)
-  (let* ((til-now (string-join (list elopher-incomplete-record string)))
-         (lines (split-string til-now "\r\n")))
-    (dotimes (idx (length lines))
-      (if (< idx (- (length lines) 1))
-          (let ((line (elt lines idx)))
-            (unless (string-empty-p line)
-              (elopher-render-record line)))
-        (setq elopher-incomplete-record (elt lines idx))))))
-
-
 ;;; History management
 ;;
 
 (defvar elopher-history nil
   "List of pages in elopher history.")
 
+(defvar elopher-place-history nil
+  "List of objects describing how to access pages in history.")
+
+(defvar elopher-current-place nil
+  "How to access current page.")
+
 (defun elopher-push-history ()
   "Add current contents of buffer, including point, to history."
   (unless (string-empty-p (buffer-string))
     (push
      (list (buffer-string)
            (point))
-     elopher-history)))
+     elopher-history)
+    (push
+     elopher-current-place
+     elopher-place-history)))
 
 (defun elopher-pop-history ()
   "Restore most recent page from history."
             (switch-to-buffer "*elopher*")
             (erase-buffer)
             (insert page-string)
-            (goto-char page-point))
+            (goto-char page-point)
+            (setq elopher-current-place (pop elopher-place-history)))
         (message "Already at start of history."))
     (message "No elopher buffer found.")))
 
 ;;; Selector retrieval (all kinds)
 ;;
 
-
 (defun elopher-get-selector (selector host port filter &optional sentinel)
   (switch-to-buffer "*elopher*")
   (elopher-mode)
                         #'elopher-image-filter
                         #'elopher-image-sentinel))
 
+;; Start page retrieval
+
+(defun elopher-get-start-page (&optional selector host port)
+  "Display start page.  SELECTOR, HOST and PORT are unused."
+  (let ((inhibit-read-only t))
+    (erase-buffer)
+    (save-excursion
+      (elopher-render-complete-records elopher-start-page))))
 
 ;;; Navigation methods
 ;;
   (backward-button 1))
 
 (defun elopher-click-link (button)
-  (apply (button-get button 'link-getter) (button-get button 'link-address)))
+  (apply (button-get button 'link-getter) (button-get button 'link-address))
+  (setq elopher-current-place (list link-getter link-address)))
 
 (defun elopher-follow-closest-link ()
   (interactive)
 (defun elopher-go ()
   "Go to a particular gopher site."
   (interactive)
-  (elopher-get-index "" (read-from-minibuffer "Gopher host: ") 70))
+  (let* ((selector "")
+         (hostname (read-from-minibuffer "Gopher host: "))
+         (port 70)
+         (address (list selector hostname port)))
+    (elopher-get-index "" (read-from-minibuffer "Gopher host: ") 70)i
+    (setq elopher-current-place (list #'elopher-get-index address))))
 
+(defun  elopher-reload ()
+  "Reload current page."
+  (interactive)
+  (if elopher-current-place
+      (let ((link-getter (car elopher-current-place))
+            (address (cadr elopher-current-place)))
+        (apply link-getter address))
+    (elopher-get-start-page)))
 
 ;;; Main start procedure
 ;;
   (switch-to-buffer "*elopher*")
   (elopher-mode)
   (setq elopher-history nil)
-  (let ((inhibit-read-only t))
-    (erase-buffer)
-    (save-excursion
-      (elopher-render-complete-records elopher-start-page))))
+  (setq elopher-place-history nil)
+  (setq elopher-current-place nil)
+  (elopher-get-start-page))
 
 
 ;;; elopher.el ends here