   defconst. It is not, however, treated as a constant by this
   code. This value gets set in ycmd-open.")
 
+(defconst ycmd-server-process "ycmd-server"
+  "The emacs name of the server process. This is used by
+  functions like start-process, get-process, and delete-process.")
+
 (defun ycmd-generate-hmac-secret ()
+  "Generate a new, random 16-byte HMAC secret key."
   (let ((result '()))
     (dotimes (x 16 result)
       (setq result (cons (byte-to-string (random 256)) result)))
     (apply 'concat result)))
-
-(defconst ycmd-server-process "ycmd-server"
-  "The emacs name of the server process. This is used by
-  functions like start-process, get-process, and delete-process.")
 
 (defun ycmd-json-encode (obj)
   "A version of json-encode that uses {} instead of null for nil

	    (when (< 3000 cont) ; timeout after 3 seconds
	      (error "Server timeout.")))))))))

(defun ycmd-load-conf-file (filename)
  (interactive
   (list
    (read-file-name "Filename: ")))
  (let ((filename (expand-file-name filename)))
    (ycmd-request
     "/load_extra_conf_file"
     `(("filepath" . ,filename)))))

(defun ycmd-display-completions (pos)
  (interactive "d")
  (let ((completions (ycmd-get-completions pos)))
    (pop-to-buffer "*ycmd-completions*")
    (erase-buffer)
    (insert (pp-to-string completions))))

(defun ycmd-get-completions (pos)
  (let* ((column-num (+ 1 (save-excursion (goto-char pos) (current-column))))
         (line-num (line-number-at-pos (point)))
         (full-path (buffer-file-name))
         (file-contents (buffer-string))
         (file-types '("cpp"))
         (content `(("column_num" . ,column-num)
                    ("file_data" .
                     ((,full-path . (("contents" . ,file-contents)
                                     ("filetypes" . ,file-types)))))
                    ("filepath" . ,full-path)
                    ("line_num" . ,line-num))))
         (ycmd-request "/completions" content :parser 'json-read)))

(defun* ycmd-request (location content &key (parser 'buffer-string))
  (let* ((content (json-encode content))
         (hmac (ycmd-hmac-function content ycmd-hmac-secret))
         (hex-hmac (encode-hex-string hmac))

  :type '()
  :group 'ycmd)

(defun ycmd-open (filename)
  "Start a new ycmd server using the 'ycm extra conf' file FILENAME.

This kills any ycmd server already running (under ycmd.el's
control.) The newly started server will have a new HMAC secret."
  (interactive
  (list
   (read-file-name "Filename: ")))
  (ycmd-close)
  (let ((hmac-secret (ycmd-generate-hmac-secret)))
    (ycmd-start-server hmac-secret)
    (setq ycmd-hmac-secret hmac-secret)
    (ycmd-load-conf-file filename)))

(defun ycmd-close ()
  "Shutdown any running ycmd server.

This does nothing if no server is running."
  (interactive)
  (if (ycmd-running?)
      (delete-process ycmd-server-process)))

(defun ycmd-load-conf-file (filename)
  "Tell the ycmd server to load the configuration file FILENAME."
  (interactive
   (list
    (read-file-name "Filename: ")))
  (let ((filename (expand-file-name filename)))
    (ycmd-request
     "/load_extra_conf_file"
     `(("filepath" . ,filename)))))

(defun ycmd-display-completions (pos)
  "Get completions at the current point and display them in a buffer.

This is really a utility/debugging function for developers, but
it might be interesting for some users."
  (interactive "d")
  (let ((completions (ycmd-get-completions pos)))
    (pop-to-buffer "*ycmd-completions*")
    (erase-buffer)
    (insert (pp-to-string completions))))

(defun ycmd-get-completions (pos)
  "Get completions at POS from the ycmd server.

To see what the returned structure looks like, you can use
ycmd-display-completions."
  (let* ((column-num (+ 1 (save-excursion (goto-char pos) (current-column))))
         (line-num (line-number-at-pos (point)))
         (full-path (buffer-file-name))
         (file-contents (buffer-string))
         (file-types '("cpp" "python"))
         (content `(("column_num" . ,column-num)
                    ("file_data" .
                     ((,full-path . (("contents" . ,file-contents)
                                     ("filetypes" . ,file-types)))))
                    ("filepath" . ,full-path)
                    ("line_num" . ,line-num))))
         (ycmd-request "/completions" content :parser 'json-read)))

;; Private: Stuff users should probably not touch.

(defconst ycmd-server-actual-port 0
  "The actual port being used by the ycmd server. This is set
  based on the output from the server itself. Users should never
  change this.")

(defconst ycmd-hmac-secret nil
  "This is populated with the hmac secret of the current
