 ;;; merlin-imenu.el --- Merlin and imenu integration.   -*- coding: utf-8 -*-
 ;; Licensed under the MIT license.
 
-;; Author: tddsg
-;; Created: 10 July 2016
-;; Updated: 27 April 2017
-;; Version: 0.2
+;; Author: tddsg (Ta Quang Trung)
+;; Version: 0.3
+;; Release log:
+;;   - v0.1: July 2016
+;;   - v0.2: 27 April 2017
+;;   - v0.3: 21 August 2019
 ;; Keywords: ocaml, imenu, merlin
 ;; URL:
 

          (point))
      (error -1))))

(defun parse-outline-item (prefix item)
  "Parse one item of the outline tree."
  (let* ((start-line (cdr (nth 2 (nth 1 item))))
         (start-col (cdr (nth 3 (nth 1 item))))
         (item-name (cdr (nth 3 item)))
         (item-kind (cdr (nth 4 item)))
         (sub-trees (cdr (nth 6 item)))
         (item-full-name (concat prefix item-name))
         (item-pos (compute-pos start-line start-col))
         (marker (set-marker (make-marker) item-pos))
         (item-marker (cons item-full-name marker)))
    (cond ((string= item-kind "Value")
           (setq value-list (cons item-marker value-list)))
          ((string= item-kind "Type")
           (setq type-list (cons item-marker type-list)))
          ((string= item-kind "Class")
           (setq class-list (cons item-marker class-list)))
          ((string= item-kind "Module")
           (setq module-list (cons item-marker module-list)))
          ((string= item-kind "Exn")
           (setq exception-list (cons item-marker exception-list)))
          ((string= item-kind "Constructor")
           (setq constructor-list (cons item-marker constructor-list)))
          ((string= item-kind "Label")
           (setq label-list (cons item-marker label-list)))
          (t (setq misc-list (cons item-marker misc-list))))
    (if (not (null sub-trees))
        (parse-outline-tree (concat prefix item-name " / ") sub-trees))))

(defun parse-outline-tree (prefix outline)
  "Parse outline tree."
  (when (not (null outline))
    (parse-outline-item prefix (car outline))
    (parse-outline-tree prefix (cdr outline))))

(defun merlin-imenu-create-index ()
  "Create data for imenu using the merlin outline feature."
  (interactive)
  ;; Reset local vars
  (setq module-list nil
        value-list nil
        type-list nil
        class-list nil
        exception-list nil
        constructor-list nil
        label-list nil
        misc-list nil)
  ;; Read outline tree
  (parse-outline-tree "" (merlin/call "outline"))
  (let ((index ()))
    (when module-list (push (cons "Module" module-list) index))
    (when exception-list (push (cons "Exception" exception-list) index))
    (when label-list (push (cons "Label" label-list) index))
    (when constructor-list (push (cons "Constructor" constructor-list) index))
    (when type-list (push (cons "Type" type-list) index))
    (when class-list (push (cons "Class" class-list) index))
    (when value-list (push (cons "Value" value-list) index))
    (when misc-list (push (cons "Misc" misc-list) index))
    index))

;; enable Merlin to use the merlin-imenu module

(setq max-specpdl-size 10000)

;; lists of different outline items
(defvar-local value-list nil)
(defvar-local type-list nil)
(defvar-local exception-list nil)

(defun merlin-imenu-compute-position (line col)
  "Get location of the item."
  (save-excursion
    (condition-case nil
