   "Major mode for Factor source code."
   :group 'fuel
   :group 'languages)
+
+(defcustom factor-mode-cycle-always-ask-p t
+  "Whether to always ask for file creation when cycling to a
+source/docs/tests file.
+
+When set to false, you'll be asked only once."
+  :type 'boolean
+  :group 'factor-mode)
 
 (defcustom factor-mode-use-fuel t
   "Whether to use the full FUEL facilities in factor mode.

  (factor-mode--keymap-setup)
  (factor-mode--indentation-setup)
  (factor-mode--syntax-setup)
  (when factor-mode-use-fuel (require 'fuel-mode) (fuel-mode))
  (run-hooks 'factor-mode-hook))


(defconst factor-mode--cycle-endings
  '(".factor" "-tests.factor" "-docs.factor"))

(make-local-variable
 (defvar factor-mode--cycling-no-ask nil))

(defvar factor-mode--cycle-ring
  (let ((ring (make-ring (length factor-mode--cycle-endings))))
    (dolist (e factor-mode--cycle-endings ring)
      (ring-insert ring e))
    ring))

(defconst factor-mode--cycle-basename-regex
  (format "\\(.+?\\)\\(%s\\)$" (regexp-opt factor-mode--cycle-endings)))

(defun factor-mode--cycle-split (basename)
  (when (string-match factor-mode--cycle-basename-regex basename)
    (cons (match-string 1 basename) (match-string 2 basename))))

(defun factor-mode--cycle-next (file)
  (let* ((dir (file-name-directory file))
         (basename (file-name-nondirectory file))
         (p/s (factor-mode--cycle-split basename))
         (prefix (car p/s))
         (ring factor-mode--cycle-ring)
         (idx (or (ring-member ring (cdr p/s)) 0))
         (len (ring-size ring))
         (i 1)
         (result nil))
    (while (and (< i len) (not result))
      (let* ((suffix (ring-ref ring (+ i idx)))
             (path (expand-file-name (concat prefix suffix) dir)))
        (when (or (file-exists-p path)
                  (and (not (member suffix factor-mode--cycling-no-ask))
                       (y-or-n-p (format "Create %s? " path))))
          (setq result path))
        (when (and (not factor-mode-cycle-always-ask-p)
                   (not (member suffix factor-mode--cycling-no-ask)))
          (setq factor-mode--cycling-no-ask
                (cons name factor-mode--cycling-no-ask))))
      (setq i (1+ i)))
    result))

(defsubst factor-mode--cycling-setup ()
  (setq factor-mode--cycling-no-ask nil))

(defun factor-mode-visit-other-file (&optional file)
  "Cycle between code, tests and docs factor files."
  (interactive)
  (let ((file (factor-mode--cycle-next (or file (buffer-file-name)))))
    (unless file (error "No other file found"))
    (find-file file)
    (unless (file-exists-p file)
      (set-buffer-modified-p t)
      (save-buffer))))


