;;my-test-mode
;; マイナーモードの定義
(easy-mmode-define-minor-mode
 test-mode
 ;; ドキュメント
 "This is Test Mode."
 ;; 初期値
 nil
 ;; on の時のモード行への表示
 " TestMode"
 ;; マイナーモード用キーマップの初期値
 '(
;;   ("\C-o" . test-function)
   ("\r" . test-mode)
   ))

(add-hook 'test-mode-on-hook 'test-mode-init)
(add-hook 'test-mode-off-hook 'test-mode-finish)

(put 'indented-line 'forward-op 'forward-to-indentation)

(defun test-hoge ()
  (interactive)
  (test-mode 0)
  (setq unread-command-events
	(append (listify-key-sequence(this-command-keys))
		unread-command-events)))

(defun my-point-list(thing-list beginningp descp)
  (let ((getfunc (if beginningp 'car '(lambda(bounds)(if bounds (1- (cdr bounds)))))))
    (sort
     ;;(delq nil
     (let ((ret-list (list(list(point)))))
       (dolist (i thing-list ret-list)
	 (let ((bounds (list(funcall getfunc (bounds-of-thing-at-point i))i)))
	   (if (and (not (assoc (car bounds) ret-list)) (not (eq (car bounds) nil)))
	       (setq ret-list (cons bounds ret-list))))));;)
     (if descp 
	 '(lambda(a b) (> (car a) (car b)))
       '(lambda(a b) (< (car a) (car b))))
     )
    )
  )


(defun test-mode-init()
  (if my-hoge-bounds-list
      (progn
	(message "%s" my-hoge-bounds-list)
	(setq test-mode-count 1)
	(setq my-overlay-list
	      (mapcar '(lambda(bounds)
			 (make-overlay (car bounds) (1+ (car bounds))))
		      my-hoge-bounds-list))
	(mapcar '(lambda(my-ov)
		   (overlay-put my-ov 'face 'lazy-highlight))my-overlay-list)
	)))

(defun test-mode-finish()
  (mapcar '(lambda(my-ov)
	     (delete-overlay my-ov))my-overlay-list))

(defvar test-mode-count 0)
(defvar my-hoge-bounds-list nil)
(defvar my-overlay-list nil)

(defun test-function ()
  (interactive)
  (if (not (eq last-command this-command))
      (setq my-hoge-bounds-list 
	    ;;	(my-bounds-list 
	    (my-point-list 
	     '(line word symbol sentence sexp defun indented-line) t t)))
  (if (eq test-mode nil) (test-mode))
  (goto-char 
   (car (nth (mod test-mode-count 
		  (length my-hoge-bounds-list))
	     my-hoge-bounds-list)))
  (setq test-mode-count (1+ test-mode-count))
  )

(defun test-function-a ()
  (interactive)
  (if (not (eq last-command this-command))
      (setq my-hoge-bounds-list 
	    ;;	(my-bounds-list 
	    (my-point-list 
	     '(line defun indented-line buffer) t t)))
  (if (eq test-mode nil) (test-mode))
  (goto-char 
   (car (nth (mod test-mode-count 
		  (length my-hoge-bounds-list))
	     my-hoge-bounds-list)))
  (setq test-mode-count (1+ test-mode-count))
  )

(defun test-function-e ()
  (interactive)
  (if (not (eq last-command this-command))
      (setq my-hoge-bounds-list 
	    ;;	(my-bounds-list 
	    (my-point-list 
	     '(line defun indented-line buffer) nil nil)))
  (if (eq test-mode nil) (test-mode))
  (goto-char 
   (car (nth (mod test-mode-count 
		  (length my-hoge-bounds-list))
	     my-hoge-bounds-list)))
  (setq test-mode-count (1+ test-mode-count))
  )

(let ((i 0))
  (while (< i ?\s)
    (define-key test-mode-map (make-string 1 i) 'test-hoge)
    (setq i (1+ i))))
(define-key test-mode-map "\r" 'test-mode)

;;(define-key test-mode-map "\C-u" 'test-hoge)

(global-set-key (kbd "C-o") 'test-function)
(define-key test-mode-map "\C-o" 'test-function)
(global-set-key (kbd "C-a") 'test-function-a)
(define-key test-mode-map "\C-a" 'test-function-a)
(global-set-key (kbd "C-e") 'test-function-e)
(define-key test-mode-map "\C-e" 'test-function-e)

(setq debug-on-error t)

(defun test-function-e ()
  (interactive)
  (if (not (eq last-command this-command))
      (setq my-hoge-bounds-list 
	    ;;	(my-bounds-list 
	    (my-point-list 
	     '(line defun indented-line buffer) nil nil)))
  (if (eq test-mode nil) (test-mode))
  (goto-char 
   (car (nth (mod test-mode-count 
		  (length my-hoge-bounds-list))
	     my-hoge-bounds-list)))
  (setq test-mode-count (1+ test-mode-count))
  )

;; (defmacro define-sequential-command (name &rest commands)
;;   "Define a command whose behavior is changed by sequence of calls of the same command."
;;   (let ((cmdary (apply 'vector commands)))
;;     `(defun ,name ()
;;        ,(concat "Sequential command of "
;;                 (mapconcat
;;                  (lambda (cmd) (format "`%s'" (symbol-name cmd)))
;;                  commands " and ")
;;                 ".")
;;        (interactive)
;;        (call-interactively
;;         (aref ,cmdary (mod (seq-count) ,(length cmdary)))))))

;; (macroexpand '(define-sequential-command foo beginning-of-line beginning-of-buffer))