ocaml-indent / ocaml-indent.el

; HOW-TO-USE
;
; ; add ocaml-indent.el directory to load-path
; 
; (setq ocaml-indent-command "WHERE-YOU-INSTALLED-ocaml-indent/ocaml-indent")
; (require 'ocaml-indent)
; 
; (add-hook 
;  'tuareg-mode-hook
;  '(lambda ()
;        ...
;        (local-set-key (kbd "<C-tab>") 'ocaml-indent) ; Use <tab> if you dare.
;        ...
;        )...)

(defgroup ocaml-indent ()
  "OCaml-indent: OCaml indenter writtein OCaml."
  :group 'languages)

(defcustom ocaml-indent-command "WHERE-YOU-INSTALLED-ocaml-indent/ocaml-indent"
  "*The command which invokes ocaml-indent."
  :type 'string :group 'ocaml-indent)

(defconst ocaml-indent-process-buffer "*ocaml-indent-process*"
  "The name of ocaml-indent communication buffer")

(defun ocaml-indent-run (&optional debug)
  (let ((region-active (and transient-mark-mode mark-active)))
    (let* 
	((start-lnum
	  (save-excursion 
	    (line-number-at-pos (progn
				  (if region-active (goto-char (region-beginning)))
				  (point)))))
	 (end-lnum- 
	  (save-excursion 
	    (line-number-at-pos (progn
				  (if region-active (progn
						      (goto-char (region-end))
						      (forward-char -1))) 
				  (point)))))

	 ; When the region is active but size 0, at the line head, end-lnum- < start-lnum .
 	 ; Fix is required.
	 (end-lnum (max start-lnum end-lnum-)) 
	 (start-char
	  (save-excursion
	    (goto-char (point-min)) (forward-line (1- start-lnum)) ; to line (start-lnum)
	    (point)))

	 (end-char
	  (save-excursion
	    (goto-char (point-min)) (forward-line end-lnum) ; to line (end-lnum + 1)
	    (point))))

      (save-excursion 

	(with-current-buffer (get-buffer-create ocaml-indent-process-buffer)
	  (erase-buffer))

	;; We cannot stop sending contenst to the process at end-char,
	;; Since comments and strings may not end at end-char
	(let* ((base-command '(call-process-region 1 (point-max)
						   ocaml-indent-command
						   nil ; delete
						   ocaml-indent-process-buffer ; buffer
						   nil ;display
						   ))
	       (base-options (list "-lines" (format "%d-%d" start-lnum end-lnum)))
	       (options (if debug (append (list "-debug") base-options) base-options))
	       (function (append base-command options))
	       )
	  (message "%S %S" ocaml-indent-command options)
	  (eval function))

        ;; (display-buffer ocaml-indent-process-buffer)
	(let ((indented
	       (with-current-buffer ocaml-indent-process-buffer
		 (buffer-substring (point-min) (point-max)))))
	  (save-excursion
	    (delete-region start-char end-char)
	    (goto-char start-char)
	    (insert indented)))
	))))

(defun ocaml-indent ()
  (interactive)
  (ocaml-indent-run))

(defun ocaml-indent-debug ()
  (interactive)
  (ocaml-indent-run t))

(provide 'ocaml-indent)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.