SiteMap Search ElispArea HowTo Glossary RecentChanges News Problems Suggestions
Jordan, Independence Day, Argentina, National Day

ewb.el

Last edit

Summary: Preparing to coalesce some http-emacs ideas...

Changed: 2,4c2

< ;; Copyright (C) 2002 Free Software Foundation, Inc.
< ;; Author: Patrick Anderson <patware around freeshell.org>
< ;; Keywords: hypermedia, browser, web, net

to

> ;; Copyright (C) 2002 Personal Sovereignty Foundation

Added: 8a7,11

> ;; Author: Patrick Anderson (concat (nreverse (string-to-list "gro.scimococe@tunwo")))
> ;; Keywords: browser, web, net, XHTML/HTTP/TCP
> ;;; Installation:
> ;; Add this to your .emacs
> ;; (autoload 'ewb "ewb" "emacs web browser" t)

Changed: 10,11c13,16

< ;; Try M-x ewb or M-x ewb-local
< ;; type C-h m for keystroke help

to

> ;; For entertainment purposes only
> ;;; Usage:
> ;;
M-x ewb RET
> ;; C-h m for keystroke help

Changed: 13,21c18,27

< ;; Use interpreter-minor
< ;; Use xml.el to make state parser.
< ;; Display bold, italics, etc.
< ;; Turn <frame> into link
< ;; Handle encodings [gzip, deflate, compress, etc.]
< ;; Handle ssl. I don't know how to
use ssl yet. does tramp have ssl client code?
< ;; Handle form data (RFC 2616)
< ;; <style>.*?</style>, <script>.*?</script>

< ;;; Current:

to

> ;; use http-get.el, http-post.el, htmlr.el
> ;;
<script>Can we use font-lock and narrow these code regions?</script>
> ;; Text and image data
is incrementally (stealthily) downloaded.
> ;; Download queue is also background managed.
> ;;;
Version:
> ;; .001 -- Brewing a new mix...
> ;; Researching htmlr.el, http-get.el, xml.el, nxml, asynch.el
> ;; 0 -- end of life
> ;; ewb has overgrown design limitations.
> ;; The replacement for ewb will parse XHTML directly.

Removed: 25d30

< ;;; Changes:

Removed: 39,46d43

< ;; Installation:
< ;; Add these lines to your .emacs
< ;; (autoload 'ewb "ewb" "emacs web browser" t)
< ;; (autoload 'ewb-local "ewb" "emacs web browser" t)
< ;; type M-x make-directory ~/.ewb RET
< ;; type M-! touch ~/.ewb/history
< ;; type M-x eval-buffer RET then M-x ewb RET to try it now
< ;; M-x customize-variable RET browse-url-browser-function to make ewb your default browser.

Changed: 67c64

< (defcustom ewb-markup-font

to

> (defcustom ewb-markup-face

Changed: 69c66

< "Font for markup if `ewb-invisible-markup' is not set."

to

> "Face for markup if `ewb-invisible-markup' is not set."

Added: 71a69,72

> (defface ewb-note-face
> '((t (:height 0.5)))
> "Face for markup if `ewb-invisible-markup' is not set."
> :group 'ewb)

Changed: 77c78,80

< (ewb-parse-url url nil))

to

> (string-match "\\(http://\\)?\\(.*\\)" url)
> (setq url (concat "http://" (match-string 2 url)))
> (ewb-parse-url url))

Changed: 81c84,86

< (ewb-parse-url (concat "file://" "/" (file-relative-name file "/")) nil))

to

> (let ((file (file-relative-name file "/")))
> (cd (concat "/" (file-name-directory file)))
> (ewb-parse-url (concat "file://" "/" file))))

Added: 82a88,91

> (define-key ewb-mode-map [(n)] 'pan-up)
> (define-key ewb-mode-map [(down)] 'pan-up)
> (define-key ewb-mode-map [(p)] 'pan-down)
> (define-key ewb-mode-map [(up)] 'pan-down)

Changed: 123c132

< (ewb-parse-url (replace-regexp-in-string "%20" " " (match-string 1)) t))

to

> (ewb-parse-url (replace-regexp-in-string "%20" " " (match-string 1))))

Changed: 150c159,160

< (defvar ewb-href "<a.*?\\(?:href\\|name\\)=\"?\\([^\">]+\\).*?>")

to

> ;;(defvar ewb-href "<a\\(.\\|\n\\)*?\\(?:href\\|name\\)=\"?\\([^\">]+\\)\\(.\\|\n\\)*?>")
> (defvar ewb-href "<a\\(.\\|\n\\)*?\\(href\\|name\\)=\"?\\([^\">]+\\)[^>]*>")

Changed: 178,179c188,206

< `("<img .*?src=\"\\(.*?\\)\".*?>"
< (0

to

> `("<em>\\(.\\|\n\\)*?</em>" (0 (progn 'ewb-note-face)))
> `("<i>\\(.\\|\n\\)*?</i>\\|<cite>\\(.\\|\n\\)*?</cite>" (0 'italic))
> `("<b>\\(.\\|\n\\)*?</b>"
> (0
> (progn
> 'bold)))
> ;; `("<i>.*?</i>" (0 'italic))
> ;; `("<i>.*?</i>" (0 'italic))
> ;; `("<i>.*?</i>" (0 'italic))
> ;; `("<i>.*?</i>" (0 'italic))
> `("<\\(.\\|\n\\)*?>\\|&....;"
> (0 (progn
> (if ewb-invisible-markup
> (let ((overlay (make-overlay (match-beginning 0) (match-end 0))))
> (overlay-put overlay 'invisible 'ewb)
> (overlay-put overlay 'intangible 'ewb)))
> ewb-markup-face)))
> `("<img .*?src=\"\\([^\"]*?\\)\"[^>]*>[^Z]"
> (1

Added: 180a208,212

> ;; (edebug-br)
> (backward-char)
> (insert "Z")
> (if (= 0 (length ewb-host)) ;;if we're browsing locally
> (insert-image (create-image (match-string 1))))

Changed: 184,187c216,218

< ;; `(,(concat ewb-href "\\([^<]*?\\)" "</a>")
< `(,(concat ewb-href "\\(.*?\\)</a>")
< (2 (progn
< (let (( overlay (make-overlay (match-beginning 2) (match-end 2))))

to

> `(,(concat ewb-href "\\(\\(.\\|\n\\)*?\\)</a>")
> (4 (progn
> (let (( overlay (make-overlay (match-beginning 4) (match-end 4))))

Removed: 203,209d233

< `("<.*?>\\|&....;"
< (0 (progn
< (if ewb-invisible-markup
< (let ((overlay (make-overlay (match-beginning 0) (match-end 0))))
< (overlay-put overlay 'invisible 'ewb)
< (overlay-put overlay 'intangible 'ewb)))
< ewb-markup-font)))

Changed: 215,226c239,245

< (defun ewb-parse-url (url followed)
< " A 'followed' link has a looser file spec, tighter host spec:
< A host must begin with (http:)?//
< A link such as \"a.b\" specifies file
or directory.
< An 'interactive' url has a tighter 'file' spec, looser host spec:
< A host might not begin with (http:)?//
< A link such as \"a.b\" specifies a host."
< (if followed

< ;; 1=proto?, 2=//host? 3=/?, 4=dir/* 5=file?
< (string-match "\\(http:\\)?\\(//[^/\n]+\\)?\\(/\\)?\\(\\(?:[^/\n]+/\\)*\\)\\(.*\\)" url)
< ;; 1=proto//?, 2=host 3=/?, 4=dir/* 5=file?
< (string-match "\\(http://\\|file://\\)?\\([^/\n]+\\)?\\(/\\)?\\(\\(?:[^/\n]+/\\)*\\)\\(.*\\)" url))

to

> (defun ewb-parse-url (url)
> "An optional PROTO looks like http:
or file:
> An optional HOST looks like //(a.b.c)?
> An optional DIR looks like /?a.b/c.d/
> An optional FILE looks like a.b"

> ;; 1=proto:?, 2=//host? 3=/dir/* 5=file?
> (string-match "\\(http:\\|file:\\)?\\(//[^/\n]*\\)?\\(\\([^/\n]*/\\)*\\)\\(.*\\)" url)

Changed: 229c248

< (dir (match-string 4 url))

to

> (dir (match-string 3 url))

Removed: 231,232d249

< (local (or (string-equal "file://" proto)
< (and (not host) (not ewb-host))))

Changed: 234c251

< (if proto

to

> (if (> (length proto) 0)

Changed: 236,239c253

< (if local
< (setq ewb-host nil)
< (setq ewb-proto "http://"))
< (if host

to

> (if (> (length host) 0)

Changed: 243,249c257,274

< (setq ewb-host host)
< (setq ewb-dir dir))) ;force this (generally to clear)
< (if dir
< (if (not (= 0 (length dir)))
< (setq ewb-dir dir)))
< (setq ewb-url (concat ewb-proto ewb-host "/" ewb-dir file))
< (write-region (concat ewb-url "\n") nil ewb-history-file t)

to

> (setq ewb-host host))) ;;this will be nil for file:
> (if (> (length dir) 0) ;;if dir is full,
> (setq ewb-dir dir) ;;update cwd
> (if (= 0 (length file)) ;;else, if file is empty
> (setq ewb-dir "/"))) ;;make dir root
> ;; (if dir
> ;; (if root
> ;; (setq ewb-dir (concat "/" dir))
> ;; (progn
> ;; ;; (setq dir (file-relative-name dir ewb-dir))
> ;; (setq ewb-dir (concat ewb-dir dir))))
> ;; (if (not file)
> ;; (setq ewb-dir "/" )))
> ;; (cd ewb-dir)
> ;; (setq ewb-dir (file-relative-name ewb-dir "/"))
> (setq ewb-url (concat ewb-proto "//" ewb-host ewb-dir file))
> (if (file-exists-p ewb-history-file)
> (write-region (concat ewb-url "\n") nil ewb-history-file t))

Changed: 255,257c280,284

< (if local
< (insert-file-contents (concat "/" ewb-dir file))
< (ewb-get ewb-proto ewb-host ewb-dir file buf))

to

> (if (> (length ewb-host) 0)
> (ewb-get ewb-host ewb-dir file buf)
> (progn
> ;; (cd ewb-dir)
> (insert-file-contents (concat ewb-dir file))))

Changed: 259c286

< (defun ewb-get (proto host dir file buf)

to

> (defun ewb-get (host dir file buf)

Changed: 270c297

< "GET /"

to

> "GET "


Download

;;; ewb.el --- Emacs Web Browser

;; Copyright (C) 2002  Personal Sovereignty Foundation

;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; Author: Patrick Anderson (concat (nreverse (string-to-list "gro.scimococe@tunwo")))

;; Keywords: browser, web, net, XHTML/HTTP/TCP

;;; Installation:
;;   Add this to your .emacs
;; (autoload 'ewb "ewb" "emacs web browser" t)

;;; Commentary:
;; For entertainment purposes only

;;; Usage:
;; M-x ewb RET
;; C-h m for keystroke help

;;; Todo:
;; use http-get.el, http-post.el, htmlr.el
;; <script>Can we use font-lock and narrow these code regions?</script>
;; Text and image data is incrementally (stealthily) downloaded.
;; Download queue is also background managed.


;;; Version:
;;   .001 -- Brewing a new mix...
;;   Researching htmlr.el, http-get.el, xml.el, nxml, asynch.el

;;   0 -- end of life
;;   ewb has overgrown design limitations.
;;   The replacement for ewb will parse XHTML directly.

;;   -.05
;;   fixed font-lock errors
;;   local files should work (use `ewb-local')

;;   -.09 --
;;   Much more responsive because i'm using the idea from
;;   http://emacswiki.org/cgi-bin/wiki.pl?PrettyLambda to piggy-back
;;   onto font-lock.
;;   Can now view local files, but cannot follow local links
;;   killing stale ewb-connection when entering ewb-get.

;;   -.1a -- Fixed dangerous sentinel code (when ewb-connection finally exits, the formatting was being applied to whichever buffer had focus.)
;;   -.1 --- Sending a more complete request - sourceforge.net works, but replies with gzipped content.  patware.freeshell.org works but ewb-connection hangs.  now using HTTP/1.1
;;   -.2a -- Removed referer string.
;;   -.2 --- Sending referer. Changed version numbering. ewb-href now accepts <a name=>. need to move to state-machine parser.
;;   -.3 --- Prefix arg or file extensions suppress formatting. write bookmarks to file, customizeable
;;   -.4 --- added ewb-revert [(g)], minibuffer state messages, display ewb-url above header, mouse-face, help-echo
;;   -.5 --- first alpha.





;;; Customizations:
(defgroup ewb nil "Emacs Web Browser"
  :group 'hypermedia)

(defcustom ewb-suppressed-extensions 
  "\.el$\\|\.txt$"
  "Don't parse these extensions."
  :group 'ewb)

(defcustom ewb-bookmark-file
  "~/.ewb/bookmarks"
  "Bookmark file"
  :group 'ewb)

(defcustom ewb-history-file
  "~/.ewb/history"
  "History file"
  :group 'ewb)

(defcustom ewb-invisible-markup
  t
  "Make markup invisible?"
  :type 'boolean
  :group 'ewb)

(defcustom ewb-markup-face
  'file-name-shadow
  "Face for markup if `ewb-invisible-markup' is not set."
  :type 'face
  :group 'ewb)

(defface ewb-note-face
  '((t (:height 0.5)))
  "Face for markup if `ewb-invisible-markup' is not set."
  :group 'ewb)

;; Code:
(defun ewb (url &optional prefix)
  "Emacs Web Browser.
\\{ewb-mode-map}"
  (interactive "sURL: ")
  (string-match "\\(http://\\)?\\(.*\\)" url)
  (setq url (concat "http://" (match-string 2 url)))
  (ewb-parse-url url))

(defun ewb-local (file)
  "Start `ewb' on a local file."
  (interactive "fFile: ")
  (let ((file (file-relative-name file "/")))
	(cd (concat "/" (file-name-directory file)))
	(ewb-parse-url (concat "file://" "/" file))))

(defvar ewb-mode-map (make-sparse-keymap))

(define-key ewb-mode-map [(n)] 'pan-up)
(define-key ewb-mode-map [(down)] 'pan-up)
(define-key ewb-mode-map [(p)] 'pan-down)
(define-key ewb-mode-map [(up)] 'pan-down)

(define-key ewb-mode-map [(C)]
  (lambda (dir)
	(interactive "DDownload to: ")
	(cd dir)
	(start-process "wget" "*wget*" "wget" "-nv"
				   (message (progn
							  (re-search-backward ewb-href)
							  (match-string 1))))))

(define-key ewb-mode-map [(b)] 'ewb-bookmarks)
(defun ewb-bookmarks ()
  (interactive)
  (find-file ewb-bookmark-file))
(defun ewb-bookmark-add ()
  (interactive)
  (message (concat ewb-url "\nAdded to " ewb-bookmark-file))
  (write-region (concat ewb-url "\n") nil ewb-bookmark-file t))
(define-key ewb-mode-map [(B)] 'ewb-bookmark-add)

(define-key ewb-mode-map [(o)] 'ewb)
(define-key ewb-mode-map [(g)] 'ewb-revert)
(defun ewb-revert ()
  (interactive)
  (ewb ewb-url)
  (setq ewb-history (cdr ewb-history)))

(define-key ewb-mode-map [(9)] 'ewb-next)
(defun ewb-next ()
  "jump to next link"
  (interactive)
  (re-search-forward ewb-href)
  (message (match-string 1)))

(define-key ewb-mode-map [(shift 9)] 'ewb-prev)
(defun ewb-prev ()
  "jump to prev link"
  (interactive)
  (re-search-backward ewb-href)
  (message (match-string 1)))

(define-key ewb-mode-map [(13)] 'ewb-follow)
(defun ewb-follow ()
  "follow this link"
  (interactive)
  (re-search-backward ewb-href)
  (ewb-parse-url (replace-regexp-in-string "%20" " " (match-string 1))))

(define-key ewb-mode-map [(mouse-2)] 'ewb-follow-mouse)
(defun ewb-follow-mouse (event &optional univ)
  (interactive "e\nP")
  (goto-char (posn-point (event-end event)))
  (ewb-follow))

(define-key ewb-mode-map [(s)] 'ewb-search)
(defun ewb-search (str)
  "use google"
  (interactive "sFor: ")
  (ewb (concat "www.google.com/search?q=" (dired-replace-in-string " " "+" str))))

(define-key ewb-mode-map [(q)] 'bury-buffer)
(define-key ewb-mode-map " " 'scroll-up)
(define-key ewb-mode-map [(u)] 'scroll-down)
(define-key ewb-mode-map [(h)] (lambda () (interactive) (mapcar 'print ewb-history)))

(define-key ewb-mode-map [(meta left)] 'ewb-back)
(define-key ewb-mode-map [(backspace)] 'ewb-back)
(defun ewb-back ()
  "go back in history"
  (interactive)
  (if ewb-history
	  (progn
		(setq ewb-history (cdr ewb-history))
		(let ((cur (car ewb-history)))
		  (setq ewb-history (cdr ewb-history)) ;remove self, since ewb-get adds
		  (ewb cur)))))

;;(defvar ewb-href "<a[^>]*?\\(?:href\\|name\\)=\"?\\([^\">]+\\)[^>]*?>")
;;(defvar ewb-href "<a\\(.\\|\n\\)*?\\(?:href\\|name\\)=\"?\\([^\">]+\\)\\(.\\|\n\\)*?>")
(defvar ewb-href "<a\\(.\\|\n\\)*?\\(href\\|name\\)=\"?\\([^\">]+\\)[^>]*>")
(defvar ewb-history nil)
(defvar ewb-host nil)
(defvar ewb-proto nil)
(defvar ewb-dir nil)
(defvar ewb-url nil)
(defvar ewb-connection nil)

(defun ewb-mode ()
  "emacs web browser mode. \\{ewb-mode-map}"
  (interactive)
  (kill-all-local-variables)
										;  (setq buffer-read-only t)
  (use-local-map ewb-mode-map)
  (setq mode-name "ewb")
  (setq major-mode 'ewb-mode)
  (add-to-invisibility-spec 'ewb)
  (make-local-variable 'font-lock-defaults)
  (setq font-lock-defaults '(ewb-font-lock-keywords t t nil nil)) ; nil nil ((?_ . "w")))))
  (run-hooks 'ewb-mode-hook))

(defconst ewb-font-lock-keywords
  (eval-when-compile
    (list
  	 `("\\(<br/?>\\|<p/?>\\|<hr/?>\\|</h[1-9]>\\|</li>\\|</title>\\)[^\n]"
   	   (1
		(progn
		  (backward-char)
		  (insert "\n")
		  ewb-markup-font)))

 	 `("<em>\\(.\\|\n\\)*?</em>" (0 (progn 'ewb-note-face)))

 	 `("<i>\\(.\\|\n\\)*?</i>\\|<cite>\\(.\\|\n\\)*?</cite>" (0 'italic))

 	 `("<b>\\(.\\|\n\\)*?</b>"
  	   (0
		(progn
		  'bold)))

;;  	 `("<i>.*?</i>" (0 'italic))
;;  	 `("<i>.*?</i>" (0 'italic))
;;  	 `("<i>.*?</i>" (0 'italic))
;;  	 `("<i>.*?</i>" (0 'italic))

 	 `("<\\(.\\|\n\\)*?>\\|&....;"
  	   (0 (progn
			(if ewb-invisible-markup
				(let ((overlay (make-overlay (match-beginning 0) (match-end 0))))
				  (overlay-put overlay 'invisible 'ewb)
				  (overlay-put overlay 'intangible 'ewb)))
			ewb-markup-face)))

  	 `("<img .*?src=\"\\([^\"]*?\\)\"[^>]*>[^Z]"
   	   (1
		(progn
;;		  (edebug-br)
		  (backward-char)
		  (insert "Z")
		  (if (= 0 (length ewb-host)) ;;if we're browsing locally
			  (insert-image (create-image (match-string 1))))
;; 		  (if ewb-invisible-markup
;; 			  (insert (match-string 1)))
		  ewb-markup-font)))

 	 `(,(concat ewb-href "\\(\\(.\\|\n\\)*?\\)</a>")
  	   (4 (progn
  			(let (( overlay (make-overlay (match-beginning 4) (match-end 4))))
  			  (overlay-put overlay 'mouse-face 'highlight)
  			  (overlay-put overlay 'help-echo (match-string 1)))
			font-lock-keyword-face)))

 	 `(" [^ ]"
  	   (0
		(progn
		  (backward-char)
		  (insert " ")
		  font-lock-string-face)))

 	 `(""[^\"]"
  	   (0
		(progn
		  (backward-char)
		  (insert "\"")
		  font-lock-string-face)))

	 (cons (regexp-opt
			'("HTTP/1.1" "Date:" "Server:" "Keep-Alive:" "Connection:" "Transfer-Encoding:" "Content-Type:")
			'words)
		   'font-lock-builtin-face)
	 )))

(defun ewb-parse-url (url)
  "An optional PROTO looks like http: or file:
An optional HOST looks like //(a.b.c)?
An optional DIR looks like /?a.b/c.d/
An optional FILE looks like a.b"
  ;;             1=proto:?,          2=//host?       3=/dir/*               5=file?
  (string-match "\\(http:\\|file:\\)?\\(//[^/\n]*\\)?\\(\\([^/\n]*/\\)*\\)\\(.*\\)" url)

  (let* ((proto (match-string 1 url))
		 (host (match-string 2 url))
		 (dir (match-string 3 url))
		 (file (match-string 5 url))
		 (buf (get-buffer-create "*Emacs Web Browser*")))

	(if (> (length proto) 0)
		(setq ewb-proto proto))

	(if (> (length host) 0)
		(progn
		  (string-match "\\(//\\)?\\(.*\\)" host)
		  (setq host (match-string 2 host)) ;;strip leading // if present
		  (setq ewb-host host))) ;;this will be nil for file:

	(if (> (length dir) 0) ;;if dir is full,
		(setq ewb-dir dir) ;;update cwd
	  (if (= 0 (length file)) ;;else, if file is empty
		  (setq ewb-dir "/"))) ;;make dir root
;; 	(if dir
;; 		(if root
;; 			(setq ewb-dir (concat "/" dir))
;; 		  (progn 
;; ;;			(setq dir (file-relative-name dir ewb-dir))
;; 			(setq ewb-dir (concat ewb-dir dir))))
;; 	  (if (not file)
;; 		  (setq ewb-dir "/" )))

;; 	(cd ewb-dir)
;; 	(setq ewb-dir (file-relative-name ewb-dir "/"))

	(setq ewb-url (concat ewb-proto "//" ewb-host ewb-dir file))
	(if (file-exists-p ewb-history-file)
	  (write-region (concat ewb-url "\n") nil ewb-history-file t))
	(setq ewb-history (cons ewb-url ewb-history))
	(switch-to-buffer buf)
	(erase-buffer)
	(insert (concat ewb-url "\n"))
	(overlay-put (make-overlay 1 (+ (length ewb-url) 1)) 'face 'font-lock-constant-face)

	(if (> (length ewb-host) 0)
		(ewb-get ewb-host ewb-dir file buf)
	  (progn
;;		(cd ewb-dir)
		(insert-file-contents (concat ewb-dir file))))

	(ewb-mode)))

(defun ewb-get (host dir file buf)
  "get over http"
  (message (concat "downloading " ewb-url "..."))

  (if ewb-connection
	  (progn
		(delete-process ewb-connection)
		(setq ewb-connection nil)))

  (setq ewb-connection (open-network-stream "ewb-connection" buf host 80))
  (process-send-string
   ewb-connection
   (concat
	"GET "
	(replace-regexp-in-string " " "%20" (concat dir file))
	" HTTP/1.1\r\n"
	"Host: " host "\r\n"
	"User-Agent: Emacs Web Browser\r\n"
	"Accept: */*\r\n"
	"Accept-Language: *\r\n"
	"Accept-Encoding: gzip, deflate, compress\r\n"
	"Accept-Charset: ISO-8859-1, utf-8\r\n"
	"Keep-Alive: 300\r\n"
	"Connection: keep-alive\r\n"
	"\r\n")))


(provide 'ewb)
;;; ewb.el ends here