diff options
| author | Lars Magne Ingebrigtsen | 2013-06-10 22:12:47 +0000 |
|---|---|---|
| committer | Katsumi Yamaoka | 2013-06-10 22:12:47 +0000 |
| commit | f22255bdbd0dd71d87f810f2ede419e6ec35370f (patch) | |
| tree | c2500107626636bb65440369f5cd372ca1d79525 | |
| parent | 08c0a604a289168bec624cb96c09adf357491890 (diff) | |
| download | emacs-f22255bdbd0dd71d87f810f2ede419e6ec35370f.tar.gz emacs-f22255bdbd0dd71d87f810f2ede419e6ec35370f.zip | |
lisp/gnus/eww.el (eww-tag-input): Implement submit buttons
(eww-click-radio): Implement radio and checkboxes
(eww-submit): Handle hidden elements
(eww-submit): Get submit button logic right
lisp/gnus/shr.el (shr-expand-url): Expand URLs that start with a slash correctly
| -rw-r--r-- | lisp/gnus/ChangeLog | 12 | ||||
| -rw-r--r-- | lisp/gnus/eww.el | 144 | ||||
| -rw-r--r-- | lisp/gnus/shr.el | 8 |
3 files changed, 135 insertions, 29 deletions
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog index 69137ff7358..f4d45e9fd0b 100644 --- a/lisp/gnus/ChangeLog +++ b/lisp/gnus/ChangeLog | |||
| @@ -1,6 +1,18 @@ | |||
| 1 | 2013-06-10 Lars Magne Ingebrigtsen <larsi@gnus.org> | 1 | 2013-06-10 Lars Magne Ingebrigtsen <larsi@gnus.org> |
| 2 | 2 | ||
| 3 | * shr.el (shr-expand-url): Expand URLs that start with a slash | ||
| 4 | correctly. | ||
| 5 | |||
| 6 | * eww.el (eww-submit): Get submit button logic right. | ||
| 7 | |||
| 8 | * shr.el (shr-final-table-render): New variable to signal when we're | ||
| 9 | doing the final table rendering so that we can collect more data at | ||
| 10 | that point. | ||
| 11 | |||
| 3 | * eww.el (eww-submit): Make form submission work. | 12 | * eww.el (eww-submit): Make form submission work. |
| 13 | (eww-tag-input): Implement submit buttons. | ||
| 14 | (eww-click-radio): Implement radio and checkboxes. | ||
| 15 | (eww-submit): Handle hidden elements. | ||
| 4 | 16 | ||
| 5 | * shr.el (shr-descend): Allow other packages to override (or provide) | 17 | * shr.el (shr-descend): Allow other packages to override (or provide) |
| 6 | rendering of elements. | 18 | rendering of elements. |
diff --git a/lisp/gnus/eww.el b/lisp/gnus/eww.el index 63ad6fd4f8a..1a072244fb4 100644 --- a/lisp/gnus/eww.el +++ b/lisp/gnus/eww.el | |||
| @@ -118,6 +118,7 @@ | |||
| 118 | (let ((map (make-sparse-keymap))) | 118 | (let ((map (make-sparse-keymap))) |
| 119 | (suppress-keymap map) | 119 | (suppress-keymap map) |
| 120 | (define-key map "q" 'eww-quit) | 120 | (define-key map "q" 'eww-quit) |
| 121 | (define-key map "g" 'eww-reload) | ||
| 121 | (define-key map [tab] 'widget-forward) | 122 | (define-key map [tab] 'widget-forward) |
| 122 | (define-key map [backtab] 'widget-backward) | 123 | (define-key map [backtab] 'widget-backward) |
| 123 | (define-key map [delete] 'scroll-down-command) | 124 | (define-key map [delete] 'scroll-down-command) |
| @@ -158,6 +159,12 @@ | |||
| 158 | (let ((prev (pop eww-history))) | 159 | (let ((prev (pop eww-history))) |
| 159 | (url-retrieve (car prev) 'eww-render (list (car prev) (cadr prev))))) | 160 | (url-retrieve (car prev) 'eww-render (list (car prev) (cadr prev))))) |
| 160 | 161 | ||
| 162 | (defun eww-reload () | ||
| 163 | "Reload the current page." | ||
| 164 | (interactive) | ||
| 165 | (url-retrieve eww-current-url 'eww-render | ||
| 166 | (list eww-current-url (point)))) | ||
| 167 | |||
| 161 | ;; Form support. | 168 | ;; Form support. |
| 162 | 169 | ||
| 163 | (defvar eww-form nil) | 170 | (defvar eww-form nil) |
| @@ -174,40 +181,112 @@ | |||
| 174 | 'eww-form eww-form))) | 181 | 'eww-form eww-form))) |
| 175 | 182 | ||
| 176 | (defun eww-tag-input (cont) | 183 | (defun eww-tag-input (cont) |
| 177 | (let ((start (point)) | 184 | (let* ((start (point)) |
| 178 | (widget (list | 185 | (type (downcase (or (cdr (assq :type cont)) |
| 179 | 'editable-field | 186 | "text"))) |
| 180 | :size (string-to-number | 187 | (widget |
| 181 | (or (cdr (assq :size cont)) | 188 | (cond |
| 182 | "40")) | 189 | ((equal type "submit") |
| 183 | :value (or (cdr (assq :value cont)) "") | 190 | (list |
| 184 | :action 'eww-submit | 191 | 'push-button |
| 185 | :name (cdr (assq :name cont)) | 192 | :notify 'eww-submit |
| 186 | :eww-form eww-form))) | 193 | :name (cdr (assq :name cont)) |
| 187 | (apply 'widget-create widget) | 194 | :eww-form eww-form |
| 188 | (shr-generic cont) | 195 | (or (cdr (assq :value cont)) "Submit"))) |
| 196 | ((or (equal type "radio") | ||
| 197 | (equal type "checkbox")) | ||
| 198 | (list 'checkbox | ||
| 199 | :notify 'eww-click-radio | ||
| 200 | :name (cdr (assq :name cont)) | ||
| 201 | :checkbox-value (cdr (assq :value cont)) | ||
| 202 | :eww-form eww-form | ||
| 203 | (cdr (assq :checked cont)))) | ||
| 204 | ((equal type "hidden") | ||
| 205 | (list 'hidden | ||
| 206 | :name (cdr (assq :name cont)) | ||
| 207 | :value (cdr (assq :value cont)))) | ||
| 208 | (t | ||
| 209 | (list | ||
| 210 | 'editable-field | ||
| 211 | :size (string-to-number | ||
| 212 | (or (cdr (assq :size cont)) | ||
| 213 | "40")) | ||
| 214 | :value (or (cdr (assq :value cont)) "") | ||
| 215 | :action 'eww-submit | ||
| 216 | :name (cdr (assq :name cont)) | ||
| 217 | :eww-form eww-form))))) | ||
| 218 | (if (eq (car widget) 'hidden) | ||
| 219 | (when shr-final-table-render | ||
| 220 | (nconc eww-form (list widget))) | ||
| 221 | (apply 'widget-create widget)) | ||
| 189 | (put-text-property start (point) 'eww-widget widget))) | 222 | (put-text-property start (point) 'eww-widget widget))) |
| 190 | 223 | ||
| 191 | (defun eww-submit (widget dummy) | 224 | (defun eww-click-radio (widget &rest ignore) |
| 192 | (let ((form (getf (cdr widget) :eww-form)) | 225 | (let ((form (plist-get (cdr widget) :eww-form)) |
| 226 | (name (plist-get (cdr widget) :name))) | ||
| 227 | (if (widget-value widget) | ||
| 228 | ;; Switch all the other radio buttons off. | ||
| 229 | (dolist (overlay (overlays-in (point-min) (point-max))) | ||
| 230 | (let ((field (plist-get (overlay-properties overlay) 'button))) | ||
| 231 | (when (and (eq (plist-get (cdr field) :eww-form) form) | ||
| 232 | (equal name (plist-get (cdr field) :name))) | ||
| 233 | (unless (eq field widget) | ||
| 234 | (widget-value-set field nil))))) | ||
| 235 | (widget-value-set widget t)) | ||
| 236 | (eww-fix-widget-keymap))) | ||
| 237 | |||
| 238 | (defun eww-submit (widget &rest ignore) | ||
| 239 | (let ((form (plist-get (cdr widget) :eww-form)) | ||
| 240 | (first-button t) | ||
| 193 | values) | 241 | values) |
| 194 | (dolist (overlay (overlays-in (point-min) (point-max))) | 242 | (dolist (overlay (sort (overlays-in (point-min) (point-max)) |
| 195 | (let ((field (getf (overlay-properties overlay) 'field))) | 243 | (lambda (o1 o2) |
| 196 | (when (eq (getf (cdr field) :eww-form) form) | 244 | (< (overlay-start o1) (overlay-start o2))))) |
| 197 | (let ((name (getf (cdr field) :name))) | 245 | (let ((field (or (plist-get (overlay-properties overlay) 'field) |
| 246 | (plist-get (overlay-properties overlay) 'button) | ||
| 247 | (plist-get (overlay-properties overlay) 'eww-hidden)))) | ||
| 248 | (when (eq (plist-get (cdr field) :eww-form) form) | ||
| 249 | (let ((name (plist-get (cdr field) :name))) | ||
| 198 | (when name | 250 | (when name |
| 199 | (push (cons name (widget-value field)) | 251 | (cond |
| 200 | values)))))) | 252 | ((eq (car field) 'checkbox) |
| 253 | (when (widget-value field) | ||
| 254 | (push (cons name (plist-get (cdr field) :checkbox-value)) | ||
| 255 | values))) | ||
| 256 | ((eq (car field) 'eww-hidden) | ||
| 257 | (push (cons name (plist-get (cdr field) :value)) | ||
| 258 | values)) | ||
| 259 | ((eq (car field) 'push-button) | ||
| 260 | ;; We want the values from buttons if we hit a button, | ||
| 261 | ;; or we're submitting something and this is the first | ||
| 262 | ;; button displayed. | ||
| 263 | (when (or (and (eq (car widget) 'push-button) | ||
| 264 | (eq widget field)) | ||
| 265 | (and (not (eq (car widget) 'push-button)) | ||
| 266 | (eq (car field) 'push-button) | ||
| 267 | first-button)) | ||
| 268 | (setq first-button nil) | ||
| 269 | (push (cons name (widget-value field)) | ||
| 270 | values))) | ||
| 271 | (t | ||
| 272 | (push (cons name (widget-value field)) | ||
| 273 | values)))))))) | ||
| 274 | (dolist (elem form) | ||
| 275 | (when (and (consp elem) | ||
| 276 | (eq (car elem) 'hidden)) | ||
| 277 | (push (cons (plist-get (cdr elem) :name) | ||
| 278 | (plist-get (cdr elem) :value)) | ||
| 279 | values))) | ||
| 201 | (let ((shr-base eww-current-url)) | 280 | (let ((shr-base eww-current-url)) |
| 202 | (if (and (stringp (getf form :method)) | 281 | (if (and (stringp (plist-get form :method)) |
| 203 | (equal (downcase (getf form :method)) "post")) | 282 | (equal (downcase (plist-get form :method)) "post")) |
| 204 | (let ((url-request-method "POST") | 283 | (let ((url-request-method "POST") |
| 205 | (url-request-data (mm-url-encode-www-form-urlencoded values))) | 284 | (url-request-data (mm-url-encode-www-form-urlencoded values))) |
| 206 | (eww-browse-url (shr-expand-url (getf form :action)))) | 285 | (eww-browse-url (shr-expand-url (plist-get form :action)))) |
| 207 | (eww-browse-url | 286 | (eww-browse-url |
| 208 | (shr-expand-url | 287 | (shr-expand-url |
| 209 | (concat | 288 | (concat |
| 210 | (getf form :action) | 289 | (cdr (assq :action form)) |
| 211 | "?" | 290 | "?" |
| 212 | (mm-url-encode-www-form-urlencoded values)))))))) | 291 | (mm-url-encode-www-form-urlencoded values)))))))) |
| 213 | 292 | ||
| @@ -217,10 +296,19 @@ | |||
| 217 | (while (setq start (next-single-property-change start 'eww-widget)) | 296 | (while (setq start (next-single-property-change start 'eww-widget)) |
| 218 | (setq widget (get-text-property start 'eww-widget)) | 297 | (setq widget (get-text-property start 'eww-widget)) |
| 219 | (goto-char start) | 298 | (goto-char start) |
| 220 | (delete-region start (next-single-property-change start 'eww-widget)) | 299 | (let ((end (next-single-property-change start 'eww-widget))) |
| 221 | (apply 'widget-create widget) | 300 | (dolist (overlay (overlays-in start end)) |
| 222 | (put-text-property start (point) 'not-read-only t)) | 301 | (when (plist-get (overlay-properties overlay) 'button) |
| 223 | (widget-setup))) | 302 | (delete-overlay overlay))) |
| 303 | (delete-region start end)) | ||
| 304 | (apply 'widget-create widget)) | ||
| 305 | (widget-setup) | ||
| 306 | (eww-fix-widget-keymap))) | ||
| 307 | |||
| 308 | (defun eww-fix-widget-keymap () | ||
| 309 | (dolist (overlay (overlays-in (point-min) (point-max))) | ||
| 310 | (when (plist-get (overlay-properties overlay) 'button) | ||
| 311 | (overlay-put overlay 'local-map widget-keymap)))) | ||
| 224 | 312 | ||
| 225 | (provide 'eww) | 313 | (provide 'eww) |
| 226 | 314 | ||
diff --git a/lisp/gnus/shr.el b/lisp/gnus/shr.el index bf9f5a4e3d4..d9e267e5288 100644 --- a/lisp/gnus/shr.el +++ b/lisp/gnus/shr.el | |||
| @@ -115,6 +115,7 @@ cid: URL as the argument.") | |||
| 115 | (defvar shr-base nil) | 115 | (defvar shr-base nil) |
| 116 | (defvar shr-ignore-cache nil) | 116 | (defvar shr-ignore-cache nil) |
| 117 | (defvar shr-external-rendering-functions nil) | 117 | (defvar shr-external-rendering-functions nil) |
| 118 | (defvar shr-final-table-render nil) | ||
| 118 | 119 | ||
| 119 | (defvar shr-map | 120 | (defvar shr-map |
| 120 | (let ((map (make-sparse-keymap))) | 121 | (let ((map (make-sparse-keymap))) |
| @@ -490,6 +491,7 @@ size, and full-buffer size." | |||
| 490 | ;; Absolute URL. | 491 | ;; Absolute URL. |
| 491 | url | 492 | url |
| 492 | (let ((base shr-base)) | 493 | (let ((base shr-base)) |
| 494 | ;; Chop off query string. | ||
| 493 | (when (string-match "^\\([^?]+\\)[?]" base) | 495 | (when (string-match "^\\([^?]+\\)[?]" base) |
| 494 | (setq base (match-string 1 base))) | 496 | (setq base (match-string 1 base))) |
| 495 | (cond | 497 | (cond |
| @@ -499,6 +501,9 @@ size, and full-buffer size." | |||
| 499 | ((and (not (string-match "/\\'" base)) | 501 | ((and (not (string-match "/\\'" base)) |
| 500 | (not (string-match "\\`/" url))) | 502 | (not (string-match "\\`/" url))) |
| 501 | (concat base "/" url)) | 503 | (concat base "/" url)) |
| 504 | ((and (string-match "\\`/" url) | ||
| 505 | (string-match "\\(\\`[^:]*://[^/]+\\)/" base)) | ||
| 506 | (concat (match-string 1 base) url)) | ||
| 502 | (t | 507 | (t |
| 503 | (concat base url)))))) | 508 | (concat base url)))))) |
| 504 | 509 | ||
| @@ -1177,7 +1182,8 @@ ones, in case fg and bg are nil." | |||
| 1177 | (frame-width)) | 1182 | (frame-width)) |
| 1178 | (setq truncate-lines t)) | 1183 | (setq truncate-lines t)) |
| 1179 | ;; Then render the table again with these new "hard" widths. | 1184 | ;; Then render the table again with these new "hard" widths. |
| 1180 | (shr-insert-table (shr-make-table cont sketch-widths t) sketch-widths)) | 1185 | (let ((shr-final-table-render t)) |
| 1186 | (shr-insert-table (shr-make-table cont sketch-widths t) sketch-widths))) | ||
| 1181 | ;; Finally, insert all the images after the table. The Emacs buffer | 1187 | ;; Finally, insert all the images after the table. The Emacs buffer |
| 1182 | ;; model isn't strong enough to allow us to put the images actually | 1188 | ;; model isn't strong enough to allow us to put the images actually |
| 1183 | ;; into the tables. | 1189 | ;; into the tables. |