;;; highlight-long-lines-mode.el --- Highlight lines over a certain length.

;; Author: Mark Triggs <mst@dishevelled.net>

;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; This file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.

;;; Commentary:

;; I prefer my code to have a line length of under 79 characters, so up until
;; now I've used `highlight-lines-matching-regexp' to mark overly long lines
;; in my buffer.  This didn't work when people used tabs instead of spaces to
;; indent, so I finally decided to write something a little more robust.

;; To use it, simply (require 'highlight-long-lines-mode) and
;; M-x highlight-long-lines-mode (or add a form like
;; "(highlight-long-lines-mode)" to the appropriate hook for your major mode.

;;; Code:


(defvar highlight-long-lines-length fill-column
  "The length of a long line in the current buffer.
Defaults to the buffer's fill-column")

(defvar highlight-long-lines-mode-hook '()
  "Hook run when highlight-long-lines-mode is activated")

(make-variable-buffer-local 'highlight-long-lines-length)

(make-face 'long-line-face)
(set-face-attribute 'long-line-face nil :bold nil
                    :foreground (face-foreground 'default)
                    :underline "#2e4965")


(defun highlight-long-lines-fontify (beg end)
  (highlight-long-lines-unfontify beg end)
  (save-excursion
    (goto-char beg)
    (while (< (point) end)
      (when (> (save-excursion (end-of-line) (current-column))
               highlight-long-lines-length)
        (let ((o (make-overlay (point-at-bol) (point-at-eol))))
          (overlay-put o 'type 'long-line)
          (overlay-put o 'evaporate t)
          (overlay-put o 'face 'long-line-face)))
      (forward-line 1))))


(defun highlight-long-lines-unfontify (beg end)
  (mapc #'(lambda (o)
            (when (eq (overlay-get o 'type) 'long-line)
              (delete-overlay o)))
        (overlays-in beg end)))


(define-minor-mode highlight-long-lines-mode
  "Highlight lines that are above a certain length in the current buffer."
  nil " hl" nil
  (setq highlight-long-lines-length fill-column)
  (cond ((not highlight-long-lines-mode)
         (jit-lock-unregister 'highlight-long-lines-fontify)
         (highlight-long-lines-unfontify (point-min) (point-max)))
        (t (highlight-long-lines-fontify (point-min) (point-max))
           (jit-lock-register 'highlight-long-lines-fontify)
           (run-hooks 'highlight-long-lines-mode-hook))))


(provide 'highlight-long-lines-mode)
;;; highlight-long-lines-mode.el ends here
