legacy-dotfiles/emacs.d/nxhtml/util/pause.el
Tom Willemsen 94d2fc1815 Django, org
* Added nxhtml, mostly for django support.

  * Changed some org settings.
2011-03-07 09:04:49 +01:00

794 lines
29 KiB
EmacsLisp

;;; pause.el --- Take a break!
;;
;; Author: Lennart Borgman (lennart O borgman A gmail O com)
;; Created: 2008-01-19 Sat
(defconst pause:version "0.70");; Version:
;; Last-Updated: 2010-01-18 Mon
;; URL:
;; Keywords:
;; Compatibility:
;;
;; Features that might be required by this library:
;;
;; None
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Commentary:
;;
;; If you are using Emacs then don't you need a little reminder to
;; take a pause? This library makes Emacs remind you of that. And
;; gives you a link to a yoga exercise to try in the pause.
;;
;; There are essentially two different ways to use this library.
;; Either you run a separate Emacs process that just reminds you of
;; pauses. To use it that way see `pause-start-in-new-emacs'.
;;
;; Or run it in the current Emacs. To do that add to your .emacs
;;
;; (require 'pause)
;;
;; and do
;;
;; M-x customize-group RET pause RET
;;
;; and set `pause-mode' to t.
;;
;;
;; Note: I am unsure if it works on all systems to use a separate
;; Emacs process. It does work on w32 though. Please tell me
;; about other systems.
;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Change log:
;;
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; This program 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.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Code:
;;;###autoload
(defgroup pause nil
"Customize your health personal Emacs health saver!"
:group 'convenience)
(defcustom pause-after-minutes 15
"Pause after this number of minutes."
:type 'number
:group 'pause)
(defcustom pause-1-minute-delay 60
"Number of seconds to wait in 1 minutes delay."
:type 'number
:group 'pause)
(defcustom pause-idle-delay 5
"Seconds to wait for user to be idle before pause."
:type 'number
:group 'pause)
(defcustom pause-even-if-not-in-emacs t
"Jump up pause even if not in Emacs."
:type 'boolean
:group 'pause)
(defcustom pause-restart-anyway-after 2
"If user does not use Emacs restart timer after this minutes.
This is used when a user has clicked a link."
:type 'number
:group 'pause)
(defcustom pause-tell-again-after 2
"If user does not exit pause tell again after this minutes."
:type 'number
:group 'pause)
(defcustom pause-extra-fun 'pause-start-get-yoga-poses
"Function to call for extra fun when pausing.
Default is to show a link to a yoga exercise (recommended!).
Set this variable to nil if you do not want any extra fun.
If this variable's value is a function it will be called when the
pause frame has just been shown."
:type '(choice (function :tag "Extra function")
(const :tag "No extra function" nil))
:group 'pause)
(defvar pause-exited-from-button nil)
(defcustom pause-background-color "orange"
"Background color during pause."
:type 'color
:group 'pause)
(defcustom pause-mode-line-color "sienna"
"Mode line color during pause."
:type 'color
:group 'pause)
(defcustom pause-1-minute-mode-line-color "yellow"
"Mode line color during 1 minute phase of pause."
:type 'color
:group 'pause)
(defface pause-text-face
'((t (:foreground "sienna" :height 1.5 :bold t)))
"Face main text in pause buffer."
:group 'pause)
(defface pause-info-text-face
'((t (:foreground "yellow")))
"Face info text in pause buffer."
:group 'pause)
(defface pause-message-face
'((t (:inherit secondary-selection)))
"Face for pause messages."
:group 'pause)
(defface pause-1-minute-message-face
'((t (:inherit mode-line-inactive)))
"Face for pause messages."
:group 'pause)
(defcustom pause-break-text
(concat "\n\tHi there,"
"\n\tYou are worth a PAUSE!"
"\n\nTry some mindfulness:"
"\n\t- Look around and observe."
"\n\t- Listen."
"\n\t- Feel your body.")
"Text to show during pause."
:type 'integer
:group 'pause)
(defvar pause-el-file (or load-file-name
(when (boundp 'bytecomp-filename) bytecomp-filename)
buffer-file-name))
(defvar pause-default-img-dir
(let ((this-dir (file-name-directory pause-el-file)))
(expand-file-name "../etc/img/pause/" this-dir)))
(defcustom pause-img-dir pause-default-img-dir
"Image directory for pause.
A random image is choosen from this directory for pauses."
:type 'directory
:group 'pause)
(defvar pause-timer nil)
;;(defvar pause-break-exit-calls nil)
(defun pause-start-timer ()
(pause-start-timer-1 (* 60 pause-after-minutes)))
(defun pause-start-timer-1 (sec)
(pause-cancel-timer)
(setq pause-timer (run-with-timer sec nil 'pause-pre-break)))
(defun pause-one-minute ()
"Give you another minute ..."
(pause-start-timer-1 pause-1-minute-delay)
(message (propertize " OK, I will come back in a minute! -- greatings from pause"
'face 'pause-message-face)))
(defun pause-save-me ()
(pause-start-timer)
(message (propertize " OK, I will save you again in %d minutes! -- greatings from pause "
'face 'pause-message-face)
pause-after-minutes))
(defun pause-pre-break ()
(condition-case err
(save-match-data ;; runs in timer
(pause-cancel-timer)
(setq pause-timer (run-with-idle-timer pause-idle-delay nil 'pause-break-in-timer)))
(error
(lwarn 'pause-pre-break
:error "%s" (error-message-string err)))))
(defvar pause-break-mode-map
(let ((map (make-sparse-keymap)))
(define-key map [(control meta shift ?p)] 'pause-break-exit)
(define-key map [tab] 'forward-button)
(define-key map [(meta tab)] 'backward-button)
(define-key map [(shift tab)] 'backward-button)
(define-key map [backtab] 'backward-button)
map))
(defvar pause-buffer nil)
(defvar pause-frame nil)
(define-derived-mode pause-break-mode nil "Pause"
"Mode used during pause in pause buffer.
It defines the following key bindings:
\\{pause-break-mode-map}"
(set (make-local-variable 'buffer-read-only) t)
(setq show-trailing-whitespace nil)
;;(set (make-local-variable 'cursor-type) nil)
;; Fix-me: workaround for emacs bug
;;(run-with-idle-timer 0 nil 'pause-hide-cursor)
)
;; Fix-me: make one state var
(defvar pause-break-exit-active nil)
(defvar pause-break-1-minute-state nil)
(defun pause-break ()
(pause-cancel-timer)
(let ((wcfg (current-frame-configuration))
(old-mode-line-bg (face-attribute 'mode-line :background))
old-frame-bg-color
old-frame-left-fringe
old-frame-right-fringe
old-frame-tool-bar-lines
old-frame-menu-bar-lines
old-frame-vertical-scroll-bars)
(dolist (f (frame-list))
(add-to-list 'old-frame-bg-color (cons f (frame-parameter f 'background-color)))
(add-to-list 'old-frame-left-fringe (cons f (frame-parameter f 'left-fringe)))
(add-to-list 'old-frame-right-fringe (cons f (frame-parameter f 'right-fringe)))
(add-to-list 'old-frame-tool-bar-lines (cons f (frame-parameter f 'tool-bar-lines)))
(add-to-list 'old-frame-menu-bar-lines (cons f (frame-parameter f 'menu-bar-lines)))
(add-to-list 'old-frame-vertical-scroll-bars (cons f (frame-parameter f 'vertical-scroll-bars))))
;; Fix-me: Something goes wrong with the window configuration, try a short pause
(remove-hook 'window-configuration-change-hook 'pause-break-exit)
(run-with-idle-timer 0.2 nil 'pause-break-show)
(setq pause-break-exit-active nil)
(setq pause-break-1-minute-state nil) ;; set in `pause-break-show'
(setq pause-exited-from-button nil)
(unwind-protect
(let ((n 0)
(debug-on-error nil))
(while (and (> 3 (setq n (1+ n)))
(not pause-break-exit-active)
(not pause-break-1-minute-state))
(condition-case err
(recursive-edit)
(error (message "%s" (error-message-string err))))
(unless (or pause-break-exit-active
pause-break-1-minute-state)
(when (> 2 n) (message "Too early to pause (%s < 2)" n))
(add-hook 'window-configuration-change-hook 'pause-break-exit))))
(remove-hook 'window-configuration-change-hook 'pause-break-exit)
(pause-tell-again-cancel-timer)
;;(set-frame-parameter nil 'background-color "white")
(dolist (f (frame-list))
(set-frame-parameter f 'background-color (cdr (assq f old-frame-bg-color)))
(set-frame-parameter f 'left-fringe (cdr (assq f old-frame-left-fringe)))
(set-frame-parameter f 'right-fringe (cdr (assq f old-frame-right-fringe)))
(set-frame-parameter f 'tool-bar-lines (cdr (assq f old-frame-tool-bar-lines)))
(set-frame-parameter f 'menu-bar-lines (cdr (assq f old-frame-menu-bar-lines)))
(set-frame-parameter f 'vertical-scroll-bars (cdr (assq f old-frame-vertical-scroll-bars))))
;; Fix-me: The frame grows unless we do redisplay here:
(redisplay t)
(set-frame-configuration wcfg t)
(when pause-frame(lower-frame pause-frame))
(set-face-attribute 'mode-line nil :background old-mode-line-bg)
(run-with-idle-timer 2.0 nil 'run-hooks 'pause-break-exit-hook)
(kill-buffer pause-buffer)
(cond (pause-exited-from-button
;; Do not start timer until we start working again.
(run-with-idle-timer 1 nil 'add-hook 'post-command-hook 'pause-save-me-post-command)
;; But if we do not do that within some minutes then start timer anyway.
(run-with-idle-timer (* 60 pause-restart-anyway-after) nil 'pause-save-me))
(pause-break-1-minute-state
(run-with-idle-timer 0 nil 'pause-one-minute))
(t
(run-with-idle-timer 0 nil 'pause-save-me))))))
(defun pause-save-me-post-command ()
(pause-start-timer))
(defvar pause-break-exit-hook nil
"Hook run after break exit.
Frame configuration has been restored when this is run.
Please note that it is run in a timer.")
(defun pause-break-show ()
;; In timer
(save-match-data
(condition-case err
(pause-break-show-1)
(error
;;(remove-hook 'window-configuration-change-hook 'pause-break-exit)
(pause-break-exit)
(message "pause-break-show error: %s" (error-message-string err))))))
(defvar pause-break-last-wcfg-change (float-time))
(defun pause-break-show-1 ()
;; Do these first if something goes wrong.
(setq pause-break-last-wcfg-change (float-time))
;;(run-with-idle-timer (* 1.5 (length (frame-list))) nil 'add-hook 'window-configuration-change-hook 'pause-break-exit)
;; fix-me: temporary:
;;(add-hook 'window-configuration-change-hook 'pause-break-exit)
(unless pause-extra-fun (run-with-idle-timer 1 nil 'pause-break-message))
(run-with-idle-timer 10 nil 'pause-break-exit-activate)
(setq pause-break-1-minute-state t)
(set-face-attribute 'mode-line nil :background pause-1-minute-mode-line-color)
(with-current-buffer (setq pause-buffer
(get-buffer-create "* P A U S E *"))
(let ((inhibit-read-only t))
(erase-buffer)
(pause-break-mode)
(setq left-margin-width 25)
(pause-insert-img)
(insert (propertize pause-break-text 'face 'pause-text-face))
(goto-char (point-min))
(when (search-forward "mindfulness" nil t)
(make-text-button (- (point) 11) (point)
'face '(:inherit pause-text-face :underline t)
'action (lambda (btn)
(browse-url "http://www.jimhopper.com/mindfulness/"))))
(goto-char (point-max))
(insert (propertize "\n\nClick on a link below to exit pause\n" 'face 'pause-info-text-face))
;;(add-text-properties (point-min) (point-max) (list 'keymap (make-sparse-keymap)))
(insert-text-button "Exit pause"
'action `(lambda (button)
(condition-case err
(pause-break-exit-from-button)
(error (message "%s" (error-message-string err))))))
(insert "\n")
(dolist (m '(hl-needed-mode))
(when (and (boundp m) (symbol-value m))
(funcall m -1)))))
(dolist (f (frame-list))
(pause-max-frame f))
(pause-tell-again)
(when pause-extra-fun (funcall pause-extra-fun))
;;(setq pause-break-exit-calls 0)
(setq pause-break-last-wcfg-change (float-time))
(pause-tell-again-start-timer))
(defun pause-max-frame (f)
(let* ((avail-width (- (display-pixel-width)
(* 2 (frame-parameter f 'border-width))
(* 2 (frame-parameter f 'internal-border-width))))
(avail-height (- (display-pixel-height)
(* 2 (frame-parameter f 'border-width))
(* 2 (frame-parameter f 'internal-border-width))))
(cols (/ avail-width (frame-char-width)))
(rows (- (/ avail-height (frame-char-height)) 2)))
;;(set-frame-parameter (selected-frame) 'fullscreen 'fullboth)
;;(set-frame-parameter (selected-frame) 'fullscreen 'maximized)
(setq pause-break-last-wcfg-change (float-time))
(with-selected-frame f
(delete-other-windows (frame-first-window f))
(with-selected-window (frame-first-window)
(switch-to-buffer pause-buffer)
(goto-char (point-max))))
(modify-frame-parameters f
`((background-color . ,pause-background-color)
(left-fringe . 0)
(right-fringe . 0)
(tool-bar-lines . 0)
(menu-bar-lines . 0)
(vertical-scroll-bars . nil)
(left . 0)
(top . 0)
(width . ,cols)
(height . ,rows)
))))
(defvar pause-tell-again-timer nil)
(defun pause-tell-again-start-timer ()
(pause-tell-again-cancel-timer)
(setq pause-tell-again-timer
(run-with-idle-timer (* 60 pause-tell-again-after) t 'pause-tell-again)))
(defun pause-tell-again-cancel-timer ()
(when (timerp pause-tell-again-timer)
(cancel-timer pause-tell-again-timer))
(setq pause-tell-again-timer nil))
(defun pause-tell-again ()
(when (and window-system pause-even-if-not-in-emacs)
(pause-max-frame pause-frame)
(raise-frame pause-frame)))
(defun pause-break-message ()
(when (/= 0 (recursion-depth))
(message "%s" (propertize "Please take a pause! (Or exit now to take it in 1 minute.)"
'face 'pause-1-minute-message-face))))
(defun pause-break-exit-activate ()
(when (/= 0 (recursion-depth))
(setq pause-break-exit-active t)
(setq pause-break-1-minute-state nil)
(set-face-attribute 'mode-line nil :background pause-mode-line-color)
(message nil)
(with-current-buffer pause-buffer
(let ((inhibit-read-only t))
;; Fix-me: This interfere with text buttons.
;;(add-text-properties (point-min) (point-max) (list 'keymap nil))
))))
(defun pause-break-exit ()
(interactive)
(let ((elapsed (- (float-time) pause-break-last-wcfg-change)))
;;(message "elapsed=%s pause-break-last-wcfg-change=%s" elapsed pause-break-last-wcfg-change)
(setq pause-break-last-wcfg-change (float-time))
(when (> elapsed 1.0)
(setq pause-break-exit-active t)
(remove-hook 'window-configuration-change-hook 'pause-break-exit)
;;(pause-tell-again-cancel-timer)
(when (/= 0 (recursion-depth))
(exit-recursive-edit)))))
(defun pause-break-exit-from-button ()
(setq pause-break-1-minute-state nil)
(setq pause-exited-from-button t)
(pause-break-exit))
(defun pause-insert-img ()
(let* ((inhibit-read-only t)
img
src
(slice '(0 0 200 300))
(imgs (directory-files pause-img-dir nil nil t))
skip
)
(setq imgs (delete nil
(mapcar (lambda (d)
(unless (file-directory-p d) d))
imgs)))
(if (not imgs)
(setq img "No images found")
(setq skip (random (length imgs)))
(while (> skip 0)
(setq skip (1- skip))
(setq imgs (cdr imgs)))
(setq src (expand-file-name (car imgs) pause-img-dir))
(if (file-exists-p src)
(condition-case err
(setq img (create-image src nil nil
:relief 1
;;:margin inlimg-margins
))
(error (setq img (error-message-string err))))
(setq img (concat "Image not found: " src))))
(if (stringp img)
(insert img)
(insert-image img nil 'left-margin slice)
)
))
(defun pause-hide-cursor ()
;; runs in timer, save-match-data
(with-current-buffer pause-buffer
(set (make-local-variable 'cursor-type) nil)))
(defun pause-cancel-timer ()
(remove-hook 'post-command-hook 'pause-save-me-post-command)
(when (timerp pause-timer) (cancel-timer pause-timer))
(setq pause-timer nil))
(defun pause-break-in-timer ()
(save-match-data ;; runs in timer
(pause-cancel-timer)
(if (or (active-minibuffer-window)
(and (boundp 'edebug-active)
edebug-active))
(let ((pause-idle-delay 5))
(pause-pre-break))
(let ((there-was-an-error nil))
(condition-case err
(pause-break)
(error
(setq there-was-an-error t)))
(when there-was-an-error
(condition-case err
(progn
(select-frame last-event-frame)
(let ((pause-idle-delay nil))
(pause-pre-break)))
(error
(lwarn 'pause-break-in-timer2 :error "%s" (error-message-string err))
)))))))
(defcustom pause-only-when-server-mode t
"Allow `pause-mode' inly in the Emacs that has server-mode enabled.
This is to prevent multiple Emacs with `pause-mode'."
:type 'boolean
:group 'pause)
;;;###autoload
(define-minor-mode pause-mode
"This minor mode tries to make you take a break.
It will jump up and temporary stop your work - even if you are
not in Emacs. If you are in Emacs it will however try to be
gentle and wait until you have been idle with the keyboard for a
short while. \(If you are not in Emacs it can't be gentle. How
could it?)
Then it will show you a special screen with a link to a yoga
exercise you can do when you pause.
After the pause you continue your work where you were
interrupted."
:global t
:group 'pause
:set-after '(server-mode)
(if pause-mode
(if (and pause-only-when-server-mode
(not server-mode)
(not (with-no-warnings (called-interactively-p))))
(progn
(setq pause-mode nil)
(message "Pause mode canceled because not server-mode"))
(pause-start-timer))
(pause-cancel-timer)))
;; (emacs-Q "-l" buffer-file-name "--eval" "(pause-temp-err)")
;; (emacs-Q "-l" buffer-file-name "--eval" "(run-with-timer 1 nil 'pause-temp-err)")
;; (pause-temp-err)
(defun pause-temp-err ()
(switch-to-buffer (get-buffer-create "pause-temp-err buffer"))
(setq buffer-read-only t)
(let ((inhibit-read-only t))
(add-text-properties (point-min) (point-max) (list 'keymap nil))
(insert-text-button "click to test"
'action (lambda (btn)
(message "Click worked")))
;;(add-text-properties (point-min) (point-max) (list 'keymap nil))
))
;; (customize-group-other-window 'pause)
;; (apply 'custom-set-variables (pause-get-group-saved-customizations 'pause custom-file))
;; (pause-get-group-saved-customizations 'w32shell custom-file)
(defun pause-get-group-saved-customizations (group cus-file)
"Return customizations saved for GROUP in CUS-FILE."
(let* ((cus-buf (find-buffer-visiting cus-file))
(cus-old cus-buf)
(cus-point (when cus-old (with-current-buffer cus-old (point))))
(cusg-all (get group 'custom-group))
(cusg-vars (delq nil (mapcar (lambda (elt)
(when (eq (nth 1 elt) 'custom-variable)
(car elt)))
cusg-all)))
cus-vars-form
cus-face-form
cus-saved-vars
cus-saved-face)
(unless cus-buf (setq cus-buf (find-file-noselect cus-file)))
(with-current-buffer cus-buf
(save-restriction
(widen)
(goto-char (point-min))
(while (progn
(while (progn (skip-chars-forward " \t\n\^l")
(looking-at ";"))
(forward-line 1))
(not (eobp)))
(let ((form (read (current-buffer))))
(cond
((eq (car form) 'custom-set-variables)
(setq cus-vars-form form))
((eq (car form) 'custom-set-faces)
(setq cus-face-form form))
)))))
(dolist (vl (cdr cus-vars-form))
(when (memq (car (cadr vl)) cusg-vars)
(setq cus-saved-vars (cons (cadr vl) cus-saved-vars))))
cus-saved-vars))
;; (emacs-Q "-l" buffer-file-name "--eval" "(pause-start 0.1 nil)")
(defun pause-start (after-minutes cus-file)
"Start `pause-mode' with interval AFTER-MINUTES.
This bypasses `pause-only-when-server-mode'.
You can use this funciton to start a separate Emacs process that
handles pause, for example like this if you want a pause every 15
minutes:
emacs -Q -l pause --eval \"(pause-start 15 nil)\"
Note: Another easier alternative might be to use
`pause-start-in-new-emacs'."
(interactive "nPause after how many minutes: ")
(pause-start-1 after-minutes cus-file))
(defun pause-start-1 (after-minutes cus-file)
(setq debug-on-error t)
(pause-cancel-timer)
(when (and cus-file (file-exists-p cus-file))
(let ((args (pause-get-group-saved-customizations 'pause cus-file)))
;;(message "cus-file=%S" cus-file)
;;(message "args=%S" args)
(apply 'custom-set-variables args)))
(setq pause-after-minutes after-minutes)
(let ((pause-only-when-server-mode nil))
(pause-mode 1))
(switch-to-buffer (get-buffer-create "Pause information"))
(insert (propertize "Emacs pause\n"
'face '(:inherit variable-pitch :height 1.5)))
(insert (format "Pausing every %d minute.\n" after-minutes))
(insert "Or, ")
(insert-text-button "pause now"
'action `(lambda (button)
(condition-case err
(pause-break)
(error (message "%s" (error-message-string err))))))
(insert "!\n")
;;(setq buffer-read-only t)
(pause-break-mode)
(delete-other-windows)
(setq mode-line-format nil)
(setq pause-frame (selected-frame))
(message nil)
(set-frame-parameter nil 'background-color pause-background-color))
;; (pause-start-in-new-emacs 0.3)
;; (pause-start-in-new-emacs 15)
;;;###autoload
(defun pause-start-in-new-emacs (after-minutes)
"Start pause with interval AFTER-MINUTES in a new Emacs instance.
The new Emacs instance will be started with -Q. However if
`custom-file' is non-nil it will be loaded so you can still
customize pause.
One way of using this function may be to put in your .emacs
something like
;; for just one Emacs running pause
(when server-mode (pause-start-in-new-emacs 15))
See `pause-start' for more info.
"
(interactive (list pause-after-minutes))
(let* ((this-emacs (locate-file invocation-name
(list invocation-directory)
exec-suffixes))
(cus-file (if custom-file custom-file "~/.emacs"))
(args `("-l" ,pause-el-file
"--geometry=40x3"
"-D"
"--eval" ,(format "(pause-start %s %S)" after-minutes cus-file))))
(setq args (cons "-Q" args))
(apply 'call-process this-emacs nil 0 nil args)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Link to yoga poses
;; (defun w3-download-callback (fname)
;; (let ((coding-system-for-write 'binary))
;; (goto-char (point-min))
;; (search-forward "\n\n" nil t)
;; (write-region (point) (point-max) fname))
;; (url-mark-buffer-as-dead (current-buffer))
;; (message "Download of %s complete." (url-view-url t))
;; (sit-for 3))
;;(run-with-idle-timer 0 nil 'pause-get-yoga-poses)
(defvar pause-yoga-poses-host-url "http://www.abc-of-yoga.com/")
;;(pause-start-get-yoga-poses)
(defun pause-start-get-yoga-poses ()
(require 'url-vars)
(let ((url-show-status nil)) ;; do not show download messages
(url-retrieve (concat pause-yoga-poses-host-url "yogapractice/mountain.asp")
'pause-callback-get-yoga-poses)))
(defun pause-callback-get-yoga-poses (status)
(let ((pose (pause-random-yoga-pose (pause-get-yoga-poses-1 (current-buffer)))))
(message nil)
(when (and pose (buffer-live-p pause-buffer))
(pause-insert-yoga-link pose))))
(defun pause-insert-yoga-link (pose)
(with-current-buffer pause-buffer
(let ((here (point))
(inhibit-read-only t)
(pose-url (concat pause-yoga-poses-host-url (car pose))))
(goto-char (point-max))
(insert "Link to yoga posture for you: ")
(insert-text-button (cdr pose)
'action `(lambda (button)
(condition-case err
(progn
(browse-url ,pose-url)
(run-with-idle-timer 1 nil 'pause-break-exit-from-button))
(error (message "%s" (error-message-string err))))))
(insert "\n")
(pause-break-message))))
(defun pause-get-yoga-poses ()
(let* ((url-show-status nil) ;; do not show download messages
(buf (url-retrieve-synchronously "http://www.abc-of-yoga.com/yogapractice/mountain.asp")))
(pause-get-yoga-poses-1 buf)))
;; (setq x (url-retrieve-synchronously "http://www.abc-of-yoga.com/yogapractice/mountain.asp"))
;; (setq x (url-retrieve-synchronously "http://www.emacswiki.org/emacs/EmacsFromBazaar"))
;; (defun temp-y ()
;; (message "before y")
;; ;;(setq y (url-retrieve-synchronously "http://www.emacswiki.org/emacs/EmacsFromBazaar"))
;; (setq x (url-retrieve-synchronously "http://www.abc-of-yoga.com/yogapractice/mountain.asp"))
;; (message "after x")
;; )
;; (run-with-idle-timer 0 nil 'temp-y)
(defun pause-get-yoga-poses-1 (buf)
(require 'url)
(setq url-debug t)
;; url-insert-file-contents
(let* ((first-marker "<p>These are all the Yoga Poses covered in this section:</p>")
(table-patt "<table\\(?:.\\|\n\\)*?</table>")
table-beg
table-end
(pose-patt "<A HREF=\"\\([^\"]*?\\)\" class=\"LinkBold\">\\([^<]*?\\)</A>")
poses
(trouble-msg
(catch 'trouble
;;(switch-to-buffer-other-window buf)
(with-current-buffer buf
(goto-char 1)
(rename-buffer "YOGA" t)
(unless (search-forward first-marker nil t)
(throw 'trouble "Can't find marker for the poses on the page"))
(backward-char 10)
(unless (re-search-forward table-patt nil t)
(throw 'trouble "Can't find table with poses on the page"))
(setq table-beg (match-beginning 0))
(setq table-end (match-end 0))
(goto-char table-beg)
(while (re-search-forward pose-patt table-end t)
(setq poses (cons (cons (match-string 1) (match-string 2))
poses)))
(unless poses
(throw 'trouble "Can't find poses in table on the page"))
(kill-buffer)
nil))))
(if trouble-msg
(progn
(message "%s" trouble-msg)
nil)
(message "Number of yoga poses found=%s" (length poses))
poses)))
(defun pause-random-yoga-pose (poses)
(when poses
(random t)
(let* ((n-poses (length poses))
(pose-num (random (1- n-poses)))
(the-pose (nth pose-num poses)))
the-pose)))
;;(pause-random-yoga-pose (pause-get-yoga-poses))
(provide 'pause)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; pause.el ends here