;; .emacs file for CS 312

;;----------------------------------------------------------------------
;; Disable the middle-mouse-button paste feature
(global-set-key [mouse-2]
  '(lambda () (interactive)
     (message "Pasting with middle-button disabled in .emacs file!")))

;;----------------------------------------------------------------------
;; General settings

(setq scroll-step 3)                    ; Move only one line at a time
(setq scroll-conservatively 200)
(setq next-line-add-newlines nil)       ; No newlines on down key
(setq make-backup-files nil)            ; Avoid backup litter
(setq auto-save-list-file-prefix nil)   ; Avoid .save litter
(setq-default indent-tabs-mode nil)     ; Prevent extraneous tabs
(add-hook 'text-mode-hook 'turn-on-auto-fill) ; Automatically wrap text
(line-number-mode t)         ; Show line number in the modeline
(column-number-mode t)       ; Show column number in the modeline
(global-font-lock-mode t)    ; Automatically highlight when possible
(setq font-lock-support-mode 'lazy-lock-mode)   ; refontify automatically
;; Key bindings are similar to standard Windows accelerators.
(pc-selection-mode)
;; Match up the parens without being too annoying.
(show-paren-mode 1)

;;----------------------------------------------------------------------
;; Make Emacs colors similar to those seen in lecture.

(set-face-foreground 'font-lock-comment-face       "red")
(set-face-foreground 'font-lock-keyword-face       "blue")
(set-face-foreground 'font-lock-string-face        "forest green")
(set-face-foreground 'font-lock-variable-name-face "black")
(set-face-foreground 'font-lock-function-name-face "black")
(set-face-background 'show-paren-match-face        "light green")
(set-face-background 'show-paren-mismatch-face     "red")




;; ***NOTE***: if you get here when you start Emacs, then you have a problem
;; setting the standard font.  Move the cursor to the end of the line  below
;; (the one with the -> arrow), and then hit C-x C-e and select a fixed-
;; width font (such as Courier).  Use the resulting string in place of the
;; two ugly strings below.
;;
;; --> (insert (format "\n%S" (w32-select-font)))
;;
(condition-case nil
    (progn
      (set-face-font 'font-lock-comment-face
                     "-*-Courier New-bold-r-*-*-13-97-96-96-c-*-iso8859-1")
      (set-face-font 'font-lock-keyword-face
                     "-*-Courier New-bold-r-*-*-13-97-96-96-c-*-iso8859-1"))
  (error nil))

;;;; Can use the below instead of the (error nil) above.
;;(error
;; (message "You have a problem with the default font setting in your .emacs")
;; (sit-for 2)
;; (find-file user-init-file)
;; (and (search-forward "w32-select-font" nil t) (end-of-line))))




;;----------------------------------------------------------------------
;; Add missing functionality

(defun make-temp-file (prefix &optional dir-flag)
  "Create a temporary file.
The returned file name (created by appending some random characters at the end
of PREFIX, and expanding against `temporary-file-directory' if necessary)
is guaranteed to point to a newly created empty file.
You can then use `write-region' to write new data into the file.

If DIR-FLAG is non-nil, create a new empty directory instead of a file."
  (let (file)
    (while (condition-case ()
               (progn
                 (setq file
                       (make-temp-name
                        (expand-file-name prefix temporary-file-directory)))
                 (if dir-flag
                     (make-directory file)
                   (write-region "" nil file nil 'silent nil 'excl))
                 nil)
            (file-already-exists t))
      ;; the file was somehow created by someone else between
      ;; `make-temp-name' and `write-region', let's try again.
      nil)
    file))



;;----------------------------------------------------------------------
;; Include sml-mode in Emacs.

(setq load-path (cons "c:/program files/emacs/sml/" load-path))
(autoload 'sml-mode "sml-mode" "Major mode for editing SML." t)
(setq sml-mode-info "c:/program files/emacs/sml/sml-mode.info")
(setq sml-program-name "runsml")
(setq auto-mode-alist
      (append '(("\\.[sS]?[mM][lL]$" . sml-mode) ("\\.sig$" . sml-mode))
              auto-mode-alist))


(and (memq system-type '(ms-dos windows-nt))
     (getenv "USERPROFILE")
     (setq temporary-file-directory
           (concat (file-name-as-directory (getenv "USERPROFILE"))
                   "Local Settings/Temp/")))


(eval-after-load "sml-mode" '(require 'sml-font))

;;----------------------------------------------------------------------
;; Make sml-mode conform to CS312 style standards.

(setq sml-indent-level       2)
(setq sml-pipe-indent        -2)
(setq sml-case-indent        t)
(setq sml-nested-if-indent   t)
(setq sml-type-of-indent     nil)       ; JHR style
(setq sml-electric-semi-mode nil)

;;----------------------------------------------------------------------
;; Allow user to define how certain style violations are indicated.
;;
;; The variable "cs312-style-setting" can be set to one of the following
;; for dealing with lines with over 80 characters (and also lines with
;; useless spaces at the end):
;;
;; highlight    - colors the lines which are wrong
;; whensaving   - removes space from ends of lines and jumps to long lines
;;                before saving
;; t            - does both of the above
;; nil          - does neither

(defvar cs312-style-setting t
  "*How style (long lines and extraneous spaces) are kept.
'highlight uses color;
'whensaving removes extra spaces and jumps to long lines;
also, t uses both and nil uses none.")

(when (memq cs312-style-setting '(t highlight))
  ;; Method #1 for style warning: use color
  (make-face 'bad-style-face)
  (set-face-background 'bad-style-face "gray80")
  (setq sml-font-lock-extra-keywords
        (list (list (concat "^" (make-string 80 ?.) ".+$")
                    '(0 'bad-style-face append))
              '(" +$" . 'bad-style-face))))

(when (memq cs312-style-setting '(t whensaving))
  ;; Method #2: delete spaces and warn on long lines
  (add-hook 'sml-mode-hook
            (lambda ()
              (add-hook 'local-write-file-hooks 'clear-extra-spaces)
              (make-local-hook 'after-save-hook)
              (add-hook 'after-save-hook 'warn-on-long-lines nil t)))
  (defun clear-extra-spaces ()
    (let ((x nil))
      (save-excursion
        (goto-char (point-min))
        (while (re-search-forward "[ \t]+$" nil t)
          (replace-match "")
          (setq x t)))
      (when x
        (message "Some extraneous spaces deleted.")
        (sit-for 2)))
    nil) ; must return nil
  (defun warn-on-long-lines ()
    (let ((point nil) (line nil))
      (save-excursion
        (goto-char (point-min))
        (when (re-search-forward (concat "^" (make-string 80 ?.) ".+$") nil t)
          (setq point (point)
                line  (count-lines (point) (point-min)))))
      (when point
        (message "A line longer than 80 chars found at %S, [esc] to get there."
                 line)
        (ding)
        (let ((ev (read-event)))
          (if (memq ev '(?\e escape))
            (progn (goto-char point) (recenter '(4)))
            (setq unread-command-events
                  (append unread-command-events (list ev)))))))))
