     (let ((dirs (split-string (buffer-file-name) "/" t))
           my-dir
           found)
+      ;; FIXME use built-in filename manipulation utils
       (loop for i from (1- (length dirs)) downto 0 do
             (let ((dir "/"))
               (loop for j from 0 below i do

                     (with-current-buffer buffer (funcall f data)))
                    ((and (eq (cadar err) 'connection-failed) (not retrying))
                     (setf retrying t)
                     (tern-find-server callback t))
                    (t (message "Failed to start a Tern server"))))))
    (tern-find-server callback)))
  
(defun tern-do-complete (data)
  (let ((cs (cdr (assoc 'completions data))))
    (when (> (length cs) 0)
      (tern-complete-word (cdr (assoc 'name (elt cs 0)))))))

(defun tern-complete-word (word)
  (let (start end)
    (save-excursion
      (if (re-search-backward "[^a-zA-Z_$]" nil t)
          (forward-char)
        (goto-char 0))
      (setf start (point) end start)
      (when (re-search-forward "[^a-zA-Z_$]" nil t)
        (setf end (1- (point))))
      (delete-region start end)
      (goto-char start)
      (insert word))
    (goto-char (+ start (length word)))))

;; Mode


              (if (or (file-exists-p (concat dir ".tern-project"))
                      (file-exists-p (concat dir ".tern-port")))
                  (progn (setf found dir) (return)))))
      (setf tern-project-dir (or found my-dir))
      (if (and found (not ignore-port-file) (file-exists-p (concat found ".tern-port")))
          (let ((port (string-to-number (with-temp-buffer
                                          (insert-file-contents (concat found ".tern-port"))
                                          (buffer-string)))))
            (setf tern-known-port port)
            (funcall c port))
        (tern-start-server tern-project-dir c)))))

;; FIXME this probably won't work on other systems...
(defvar tern-command '("/usr/bin/node" "/home/marijn/src/js/tern/desktop.js"))
