;; SYNOPSIS: Word Move Stopping At EachCaseChangeNewLineEtc
;; Also vim's #/* word under cursor search .
;; AUTHOR: GPL(C) Mohsin Ahmed, http://www.cs.albany.edu/~mosh

(defun mosh-move-word (count &optional speed)
  "Move as to kill, use this to move by words but carefully.
   Used to kill words, yank words for isearch.
   Count can be > or < 0. Move faster if speed.
   MoveNicelyOverSuchLongVariableNames.
   * Always compiled, as used heavily. *
   "
  (interactive)
  (let (case-fold-search)
    (setq case-fold-search nil)

    (if (<  count 0)

        ;; Backward

        (if (and (bolp) (not (eolp))) (backward-char)
          (backward-char)
          (cond
           ((looking-at "[ \t]")    (skip-chars-backward " \t"))
           ((looking-at "[a-z]")    (skip-chars-backward "a-z")
              (backward-char 1)
              ;; Slow down unless speed or Capiltalized word.
              (or speed (looking-at "[A-Z]") (forward-char 1))
              ;; C-backspace goes slower.
           )
           ((looking-at "[A-Z]")    (skip-chars-backward "A-Z"))
           ((looking-at "[0-9]")    (skip-chars-backward "0-9"))
           (t (skip-syntax-backward (char-to-string (char-syntax
                                                     (following-char)))))
          )
      )

      ;; Forward

      (cond
         ((and (eolp) (not (bolp)))  (forward-char))
         ((looking-at "[ \t]")    (skip-chars-forward " \t"))
         ((looking-at "[A-Z]") (forward-char)
          (if (looking-at "[A-Z]") (skip-chars-forward "A-Z")
            (skip-chars-forward "a-z")
          ))
         ((looking-at "[a-z]") (skip-chars-forward "a-z")
          (and speed (looking-at "\\W\\w") (forward-char))
         )
         ((looking-at "_")  (skip-chars-forward "_"))
         ((looking-at "[0-9]")    (skip-chars-forward "0-9"))
         (t
          (skip-syntax-forward (char-to-string (char-syntax
                                                (following-char)))))
))))

;; =========================================================
;; Like vim's #* search word under cursor.
;; hyper key is hard to type on PC, so meta.
;; todo: rewrite current-word, see simple.el

;; [(meta  f7)] '(re-search-backward (concat "\\<" (current-word) "\\>"))
;; [(meta  f8)] '(re-search-forward  (concat "\\<" (current-word) "\\>"))

(defun mosh-vim-search-backward ()
  (interactive)
  (message "searching for prev word %s" (current-word))
  (hs-discard-overlays (point-min) (point-max) 'face 'bold)
  (mosh-color-regexp (current-word) 'bold)
  (re-search-backward (concat "\\<" (current-word) "\\>"))
)

(defun mosh-vim-search-forward  ()
  (interactive)
  (message "searching for next word %s" (current-word))
  (hs-discard-overlays (point-min) (point-max) 'face 'bold)
  (mosh-color-regexp (current-word) 'bold)
  (re-search-forward  (concat "\\<" (current-word) "\\>"))
)

(provide 'mword)

;;; EOF

