;;; Definition formatting: \deffn, \defun, etc

;; What definition formatting produces:
;;
;; \deffn category name args...
;;     In Info, `Category: name ARGS'
;;     In index: name:  node. line#.
;;
;; \defvr category name 
;;     In Info, `Category: name'
;;     In index: name:  node. line#.
;;
;; \deftp category name attributes...
;; `category name attributes...'       Note: \deftp args in lower case.
;;     In index: name:  node. line#.
;;
;; Specialized function-like or variable-like entity:
;;
;; \defun, \defmac, \defspec, \defvar, \defopt
;;
;; \defun name args           In Info, `Function: name ARGS'
;; \defmac name args          In Info, `Macro: name ARGS'
;; \defvar name               In Info, `Variable: name'
;; etc.
;;     In index: name:  node. line#.
;;
;; Generalized typed-function-like or typed-variable-like entity:
;; \deftypefn category data-type name args...
;;     In Info, `Category:  data-type name args...'
;; \deftypevr category data-type name 
;;     In Info, `Category:  data-type name'
;;     In index: name:  node. line#.
;;
;; Specialized typed-function-like or typed-variable-like entity:
;; \deftypefun data-type name args...
;;     In Info, `Function:  data-type name ARGS'
;;     In index: name:  node. line#.   
;;
;; \deftypevar data-type name 
;;     In Info, `Variable:  data-type name'
;;     In index: name:  node. line#.   but include args after name!?
;;
;; Generalized object oriented entity: 
;; \defop category class name args...
;;     In Info, `Category on class: name ARG'
;;     In index: name on class: node. line#.
;;
;; \defcv category class name         
;;     In Info, `Category of class: name'
;;     In index: name of class: node. line#.
;;
;; Specialized object oriented entity:
;; \defmethod class name args... 
;;     In Info, `Method on class: name ARGS'
;;     In index: name on class: node. line#.
;;
;; \defivar class name
;;     In Info, `Instance variable of class: name'
;;     In index: name of class: node. line#.


;;; The definition formatting functions

(defun latexinfo-format-defun ()
  (latexinfo-push-stack 'defun nil)
  (setq fill-column (- fill-column 5))
  (latexinfo-format-defun-1 t))

(defun latexinfo-end-defun ()
  (setq fill-column (+ fill-column 5))
  (latexinfo-discard-command)
  (let ((start (nth 1 (latexinfo-pop-stack 'defun))))
    (latexinfo-do-itemize start)
    ;; Delete extra newline inserted after header.
    (save-excursion
      (goto-char start)
      (delete-char -1))))

(defun latexinfo-format-defunx ()
  (latexinfo-format-defun-1 nil))

(defun latexinfo-format-defun-1 (first-p)
  (let ((parse-args (latexinfo-format-parse-defun-args))
	(command-type (get latexinfo-command-name 'latexinfo-defun-type)))
    (latexinfo-discard-command)
    ;; Delete extra newline inserted after previous header line.
    (if (not first-p)
	(delete-char -2))
    (funcall
     (get latexinfo-command-name 'latexinfo-deffn-formatting-property) parse-args)
    ;; Insert extra newline so that paragraph filling does not mess
    ;; with header line.
    (insert "\n\n")
    (rplaca (cdr (cdr (car latexinfo-stack))) (point))
    (funcall
     (get latexinfo-command-name 'latexinfo-defun-indexing-property) parse-args)))


;;; Formatting the first line of a definition

(defun latexinfo-format-parse-defun-args ()
  (goto-char latexinfo-command-end)
  (let ((start (point))
	(nargs
	 (get latexinfo-command-name 'latexinfo-numargs)))
    (if (not (integerp nargs))
	(error "Unknown number of arguments to %s: %s"
	       latexinfo-command-name nargs))
    (forward-list 1)			; required arg 
    (if (looking-at "[\\[]")		; optional arg 
	(delete-region (point)
		       (save-excursion
			 (forward-sexp 1) (point))))
    (setq nargs (1- nargs))
    (while (> nargs 0)
      (skip-chars-forward " \t\n")
      (if (looking-at "{")		; required arg 
	  (forward-list 1)
	(error "Argument %s missing from function" nargs))
      (setq nargs (1- nargs)))
    (setq latexinfo-command-end (point))
    (let ((marker (move-marker (make-marker) latexinfo-command-end)))
      (latexinfo-format-expand-region start (point))
      (setq latexinfo-command-end (marker-position marker))
      (move-marker marker nil))
    (goto-char start)
    (let ((args '())
	  beg end)
      (skip-chars-forward " \t\n")
      (while (< (point) latexinfo-command-end)
	(cond ((looking-at "[{[]")
	       (setq beg (1+ (point)))
	       (forward-list 1)
	       (setq end (1- (point))))
	      (t
	       (setq beg (point))
	       (re-search-forward "[\n ]")
	       (forward-char -1)
	       (setq end (point))))
	(if (> end (1+ beg))
	    (setq args 
		  (cons (buffer-substring beg end) args)))
	(skip-chars-forward " \t\n"))
      (nreverse args))))


;; \deffn, \defvr, \deftp
(put 'deffn 'latexinfo-deffn-formatting-property 'latexinfo-format-deffn)
(put 'defvr 'latexinfo-deffn-formatting-property 'latexinfo-format-deffn)
(put 'deftp 'latexinfo-deffn-formatting-property 'latexinfo-format-deffn)
(defun latexinfo-format-deffn (parsed-args)
  ;; Generalized function-like, variable-like, or generic data-type entity:
  ;; \deffn category name args...
  ;;     In Info, `Category: name ARGS'
  ;; \deftp category name attributes...
  ;; `category name attributes...'       Note: \deftp args in lower case.
  (let ((category (car parsed-args))
        (name (car (cdr parsed-args)))
        (args (cdr (cdr parsed-args))))
    (if (not (looking-at "\n")) (insert "\n"))
    (insert " -- " category ": " name)
    (while args
      (insert " "
              (if (or (= ?& (aref (car args) 0))
                      (eq (eval (car command-type)) 'deftp-type))
                  (car args)
                (upcase (car args))))
      (setq args (cdr args)))))

;; \defun, \defmac, \defspec, \defvar, \defopt: Specialized, simple
(put 'defun 'latexinfo-deffn-formatting-property
     'latexinfo-format-specialized-defun)
(put 'defmac 'latexinfo-deffn-formatting-property
     'latexinfo-format-specialized-defun)
(put 'defspec 'latexinfo-deffn-formatting-property
     'latexinfo-format-specialized-defun)
(put 'defvar 'latexinfo-deffn-formatting-property
     'latexinfo-format-specialized-defun)
(put 'defopt 'latexinfo-deffn-formatting-property
     'latexinfo-format-specialized-defun)
(defun latexinfo-format-specialized-defun (parsed-args)
  ;; Specialized function-like or variable-like entity:
  ;; \defun{name}{args}           In Info, `Function: Name ARGS'
  ;; \defmac{name}{args}          In Info, `Macro: Name ARGS'
  ;; \defvar{name}               In Info, `Variable: Name'
  ;; Use cdr of command-type to determine category:
  (let ((category (car (cdr command-type)))
        (name (car parsed-args))
        (args (cdr parsed-args)))
    (if (not (looking-at "\n")) (insert "\n"))
    (insert " -- " category ": " name)
    (while args
      (insert " "
              (if (= ?& (aref (car args) 0))
                  (car args)
                (upcase (car args)))
	      "\n")
      (setq args (cdr args)))))

;; \deftypefn, \deftypevr: Generalized typed
(put 'deftypefn 'latexinfo-deffn-formatting-property 'latexinfo-format-deftypefn)
(put 'deftypevr 'latexinfo-deffn-formatting-property 'latexinfo-format-deftypefn)
(defun latexinfo-format-deftypefn (parsed-args)
  ;; Generalized typed-function-like or typed-variable-like entity:
  ;; \deftypefn category data-type name args...
  ;;     In Info, `Category:  data-type name args...'
  ;; \deftypevr category data-type name 
  ;;     In Info, `Category:  data-type name'
  ;; Note: args in lower case, unless modified in command line.
  (let ((category (car parsed-args))
        (data-type (car (cdr parsed-args)))
        (name (car (cdr (cdr parsed-args))))
        (args (cdr (cdr (cdr parsed-args)))))
    (if (not (looking-at "\n")) (insert "\n"))
    (if (null (and category data-type name))
	(error "Null arg: %s %s %s" category data-type name)
      (insert " -- " category ": " data-type " " name))
    (while args
      (insert " " (car args))
      (setq args (cdr args)))))

;; \deftypefun, \deftypevar: Specialized typed
(put 'deftypefun 'latexinfo-deffn-formatting-property 'latexinfo-format-deftypefun)
(put 'deftypevar 'latexinfo-deffn-formatting-property 'latexinfo-format-deftypefun)
(defun latexinfo-format-deftypefun (parsed-args)
  ;; Specialized typed-function-like or typed-variable-like entity:
  ;; \deftypefun data-type name args...
  ;;     In Info, `Function:  data-type name ARGS'
  ;; \deftypevar data-type name 
  ;;     In Info, `Variable:  data-type name'
  ;; Note: args in lower case, unless modified in command line.
  ;; Use cdr of command-type to determine category:
  (let ((category (car (cdr command-type)))
        (data-type (car parsed-args))
        (name (car (cdr  parsed-args)))
        (args (cdr (cdr parsed-args))))
    (if (not (looking-at "\n")) (insert "\n"))
    (if (null (and category data-type name))
	(error "Null arg: %s %s %s" category data-type name)
      (insert " -- " category ": " data-type " " name))
    (while args
      (insert " " (car args))
      (setq args (cdr args)))))

;; \defop: Generalized object-oriented
(put 'defop 'latexinfo-deffn-formatting-property 'latexinfo-format-defop)
(defun latexinfo-format-defop (parsed-args)
  ;; Generalized object oriented entity: 
  ;; \defop category class name args...
  ;;     In Info, `Category on class: name ARG'
  ;; Note: args in upper case; use of `on'
  (let ((category (car parsed-args))
        (class (car (cdr parsed-args)))
        (name (car (cdr (cdr parsed-args))))
        (args (cdr (cdr (cdr parsed-args)))))
    (if (not (looking-at "\n")) (insert "\n"))
    (if (null (and category data-type name))
	(error "Null arg: %s %s %s" category class name)
      (insert " -- " category " on " class ": " name))
    (while args
      (insert " " (upcase (car args)))
      (setq args (cdr args)))))

;; \defcv: Generalized object-oriented
(put 'defcv 'latexinfo-deffn-formatting-property 'latexinfo-format-defcv)
(defun latexinfo-format-defcv (parsed-args)
  ;; Generalized object oriented entity: 
  ;; \defcv category class name         
  ;;     In Info, `Category of class: name'
  ;; Note: args in upper case; use of `of'
  (let ((category (car parsed-args))
        (class (car (cdr parsed-args)))
        (name (car (cdr (cdr parsed-args))))
        (args (cdr (cdr (cdr parsed-args)))))
    (if (not (looking-at "\n")) (insert "\n"))
    (if (null (and category data-type name))
	(error "Null arg: %s %s %s" category class name)
      (insert " -- " category " of " class ": " name))
    (while args
      (insert " " (upcase (car args)))
      (setq args (cdr args)))))

;; \defmethod: Specialized object-oriented
(put 'defmethod 'latexinfo-deffn-formatting-property 'latexinfo-format-defmethod)
(defun latexinfo-format-defmethod (parsed-args)
  ;; Specialized object oriented entity:
  ;; \defmethod class name args... 
  ;;     In Info, `Method on class: name ARGS'
  ;; Note: args in upper case; use of `on'
  ;; Use cdr of command-type to determine category:
  (let ((category (car (cdr command-type)))
        (class (car parsed-args))
        (name (car (cdr  parsed-args)))
        (args (cdr  (cdr parsed-args))))
    (if (not (looking-at "\n")) (insert "\n"))
    (if (null (and category data-type name))
	(error "Null arg: %s %s %s" category class name)
      (insert " -- " category " on " class ": " name))
    (while args
      (insert " " (upcase (car args)))
      (setq args (cdr args)))))

;; \defivar: Specialized object-oriented
(put 'defivar 'latexinfo-deffn-formatting-property 'latexinfo-format-defivar)
(defun latexinfo-format-defivar (parsed-args)
  ;; Specialized object oriented entity:
  ;; \defivar class name
  ;;     In Info, `Instance variable of class: name'
  ;; Note: args in upper case; use of `of'
  ;; Use cdr of command-type to determine category:
  (let ((category (car (cdr command-type)))
        (class (car parsed-args))
        (name (car (cdr  parsed-args)))
        (args (cdr  (cdr parsed-args))))
    (if (not (looking-at "\n")) (insert "\n"))
    (if (null (and category data-type name))
	(error "Null arg: %s %s %s" category class name)
      (insert " -- " category " of " class ": " name))
    (while args
      (insert " " (upcase (car args)))
      (setq args (cdr args)))))


;;; Indexing for definitions

;; An index entry has three parts: the `entry proper', the node name, and the
;; line number.  Depending on the which command is used, the entry is
;; formatted differently:
;;
;; \defun, 
;; \defmac, 
;; \defspec, 
;; \defvar, 
;; \defopt          all use their 1st argument as the entry-proper 
;;
;; \deffn, 
;; \defvr, 
;; \deftp 
;; \deftypefun
;; \deftypevar      all use their 2nd argument as the entry-proper
;;
;; \deftypefn, 
;; \deftypevr       both use their 3rd argument as the entry-proper  
;;
;; \defmethod       uses its 2nd and 1st arguments as an entry-proper 
;;                    formatted: NAME on CLASS

;; \defop           uses its 3rd and 2nd arguments as an entry-proper 
;;                    formatted: NAME on CLASS
;;        
;; \defivar         uses its 2nd and 1st arguments as an entry-proper
;;                    formatted: NAME of CLASS
;;
;; \defcv           uses its 3rd and 2nd argument as an entry-proper
;;                    formatted: NAME of CLASS

(put 'defun 'latexinfo-defun-indexing-property 'latexinfo-index-defun)
(put 'defun 'latexinfo-defun-indexing-property 'latexinfo-index-defun)
(put 'defmac 'latexinfo-defun-indexing-property 'latexinfo-index-defun)
(put 'defspec 'latexinfo-defun-indexing-property 'latexinfo-index-defun)
(put 'defvar 'latexinfo-defun-indexing-property 'latexinfo-index-defun)
(put 'defopt  'latexinfo-defun-indexing-property 'latexinfo-index-defun)

(defun latexinfo-index-defun (parsed-args)
  ;; use 1st parsed-arg  as entry-proper
  ;; `index-list' will be latexinfo-findex or the like
  (let ((index-list (get latexinfo-command-name 'latexinfo-defun-index)))
    (set index-list
         (cons 
          ;; Three elements: entry-proper, node-name, line-number
          (list
           (car parsed-args)
           latexinfo-last-node
           ;; Region formatting may not provide last node position.
           (if latexinfo-last-node-pos
               (1+ (count-lines latexinfo-last-node-pos (point)))
             1))
          (symbol-value index-list)))))

(put 'deffn 'latexinfo-defun-indexing-property 'latexinfo-index-deffn)
(put 'defvr 'latexinfo-defun-indexing-property 'latexinfo-index-deffn)
(put 'deftp 'latexinfo-defun-indexing-property 'latexinfo-index-deffn)
(put 'deftypefun 'latexinfo-defun-indexing-property 'latexinfo-index-deffn)
(put 'deftypevar 'latexinfo-defun-indexing-property 'latexinfo-index-deffn)
(defun latexinfo-index-deffn (parsed-args) 
 ;; use 2nd parsed-arg  as entry-proper
  ;; `index-list' will be latexinfo-findex or the like
  (let ((index-list (get latexinfo-command-name 'latexinfo-defun-index)))
    (set index-list
         (cons 
          ;; Three elements: entry-proper, node-name, line-number
          (list
           (car (cdr parsed-args))
           latexinfo-last-node
           ;; Region formatting may not provide last node position.
           (if latexinfo-last-node-pos
               (1+ (count-lines latexinfo-last-node-pos (point)))
             1))
          (symbol-value index-list)))))

(put 'deftypefn 'latexinfo-defun-indexing-property 'latexinfo-index-deftypefn)
(put 'deftypevr 'latexinfo-defun-indexing-property 'latexinfo-index-deftypefn)
(defun latexinfo-index-deftypefn (parsed-args)
  ;; use 3rd parsed-arg  as entry-proper
  ;; `index-list' will be latexinfo-findex or the like
  (let ((index-list (get latexinfo-command-name 'latexinfo-defun-index)))
    (set index-list
         (cons 
          ;; Three elements: entry-proper, node-name, line-number
          (list
           (car (cdr (cdr parsed-args)))
           latexinfo-last-node
           ;; Region formatting may not provide last node position.
           (if latexinfo-last-node-pos
               (1+ (count-lines latexinfo-last-node-pos (point)))
             1))
          (symbol-value index-list)))))

(put 'defmethod 'latexinfo-defun-indexing-property 'latexinfo-index-defmethod)
(defun latexinfo-index-defmethod (parsed-args)
  ;; use 2nd on 1st parsed-arg  as entry-proper
  ;; `index-list' will be latexinfo-findex or the like
  (let ((index-list (get latexinfo-command-name 'latexinfo-defun-index)))
    (set index-list
         (cons 
          ;; Three elements: entry-proper, node-name, line-number
          (list
           (format "%s on %s"            
                   (car (cdr parsed-args))
                   (car parsed-args))
           latexinfo-last-node
           ;; Region formatting may not provide last node position.
           (if latexinfo-last-node-pos
               (1+ (count-lines latexinfo-last-node-pos (point)))
             1))
          (symbol-value index-list)))))

(put 'defop 'latexinfo-defun-indexing-property 'latexinfo-index-defop)
(defun latexinfo-index-defop (parsed-args)
  ;; use 3rd on 2nd parsed-arg  as entry-proper
  ;; `index-list' will be latexinfo-findex or the like
  (let ((index-list (get latexinfo-command-name 'latexinfo-defun-index)))
    (set index-list
         (cons 
          ;; Three elements: entry-proper, node-name, line-number
          (list
           (format "%s on %s"            
                   (car (cdr (cdr parsed-args)))
                   (car (cdr parsed-args)))
           latexinfo-last-node
           ;; Region formatting may not provide last node position.
           (if latexinfo-last-node-pos
               (1+ (count-lines latexinfo-last-node-pos (point)))
             1))
          (symbol-value index-list)))))

(put 'defivar 'latexinfo-defun-indexing-property 'latexinfo-index-defivar)
(defun latexinfo-index-defivar (parsed-args)
  ;; use 2nd of 1st parsed-arg  as entry-proper
  ;; `index-list' will be latexinfo-findex or the like
  (let ((index-list (get latexinfo-command-name 'latexinfo-defun-index)))
    (set index-list
         (cons 
          ;; Three elements: entry-proper, node-name, line-number
          (list
           (format "%s of %s"            
                   (car (cdr parsed-args))
                   (car parsed-args))
           latexinfo-last-node
           ;; Region formatting may not provide last node position.
           (if latexinfo-last-node-pos
               (1+ (count-lines latexinfo-last-node-pos (point)))
             1))
          (symbol-value index-list)))))

(put 'defcv 'latexinfo-defun-indexing-property 'latexinfo-index-defcv)
(defun latexinfo-index-defcv (parsed-args)
  ;; use 3rd of 2nd parsed-arg  as entry-proper
  ;; `index-list' will be latexinfo-findex or the like
  (let ((index-list (get latexinfo-command-name 'latexinfo-defun-index)))
    (set index-list
         (cons 
          ;; Three elements: entry-proper, node-name, line-number
          (list
           (format "%s of %s"            
                   (car (cdr (cdr parsed-args)))
                   (car (cdr parsed-args)))
           latexinfo-last-node
           ;; Region formatting may not provide last node position.
           (if latexinfo-last-node-pos
               (1+ (count-lines latexinfo-last-node-pos (point)))
             1))
          (symbol-value index-list)))))


;;; Properties for definitions

;; Each primary definition command has six properties:
;;
;; 1. latexinfo-deffn-formatting-property      to format definition line
;; 2. latexinfo-defun-indexing-property        to create index entry
;; 3. latexinfo-format                         formatting command
;; 4. latexinfo-end                            end formatting command
;; 5. latexinfo-defun-type                     type of deffn to format
;; 6. latexinfo-defun-index                    type of index to use
;;
;; In addition, the `x' forms of each definition command have three
;; properties.

;; The latexinfo-deffn-formatting-property and latexinfo-defun-indexing-property
;; are listed just before the appropriate formatting and indexing commands.

(put 'deffn 'latexinfo-format 'latexinfo-format-defun)
(put 'deffnx 'latexinfo-format 'latexinfo-format-defunx)
(put 'deffn 'latexinfo-end 'latexinfo-end-defun)
(put 'enddeffn 'latexinfo-format 'latexinfo-end-defun)
(put 'deffn 'latexinfo-defun-type '('deffn-type nil))
(put 'deffnx 'latexinfo-defun-type '('deffn-type nil))
(put 'deffn 'latexinfo-defun-index 'latexinfo-findex)
(put 'deffnx 'latexinfo-defun-index 'latexinfo-findex)

(put 'defun 'latexinfo-format 'latexinfo-format-defun)
(put 'defunx 'latexinfo-format 'latexinfo-format-defunx)
(put 'enddefun 'latexinfo-format 'latexinfo-end-defun)
(put 'defun 'latexinfo-end 'latexinfo-end-defun)
(put 'defun 'latexinfo-defun-type '('defun-type "Function"))
(put 'defunx 'latexinfo-defun-type '('defun-type "Function"))
(put 'defun 'latexinfo-defun-index 'latexinfo-findex)
(put 'defunx 'latexinfo-defun-index 'latexinfo-findex)

(put 'defmac 'latexinfo-format 'latexinfo-format-defun)
(put 'defmacx 'latexinfo-format 'latexinfo-format-defunx)
(put 'defmac 'latexinfo-end 'latexinfo-end-defun)
(put 'enddefmac 'latexinfo-format 'latexinfo-end-defun)
(put 'defmac 'latexinfo-defun-type '('defun-type "Macro"))
(put 'defmacx 'latexinfo-defun-type '('defun-type "Macro"))
(put 'defmac 'latexinfo-defun-index 'latexinfo-findex)
(put 'defmacx 'latexinfo-defun-index 'latexinfo-findex)

(put 'defspec 'latexinfo-format 'latexinfo-format-defun)
(put 'defspecx 'latexinfo-format 'latexinfo-format-defunx)
(put 'defspec 'latexinfo-end 'latexinfo-end-defun)
(put 'enddefspec 'latexinfo-format 'latexinfo-end-defun)
(put 'defspec 'latexinfo-defun-type '('defun-type "Special form"))
(put 'defspecx 'latexinfo-defun-type '('defun-type "Special form"))
(put 'defspec 'latexinfo-defun-index 'latexinfo-findex)
(put 'defspecx 'latexinfo-defun-index 'latexinfo-findex)

(put 'defvr 'latexinfo-format 'latexinfo-format-defun)
(put 'defvrx 'latexinfo-format 'latexinfo-format-defunx)
(put 'defvr 'latexinfo-end 'latexinfo-end-defun)
(put 'enddefvr 'latexinfo-format 'latexinfo-end-defun)
(put 'defvr 'latexinfo-defun-type '('deffn-type nil))
(put 'defvrx 'latexinfo-defun-type '('deffn-type nil))
(put 'defvr 'latexinfo-defun-index 'latexinfo-vindex)
(put 'defvrx 'latexinfo-defun-index 'latexinfo-vindex)

(put 'defvar 'latexinfo-format 'latexinfo-format-defun)
(put 'defvarx 'latexinfo-format 'latexinfo-format-defunx)
(put 'defvar 'latexinfo-end 'latexinfo-end-defun)
(put 'enddefvar 'latexinfo-format 'latexinfo-end-defun)
(put 'defvar 'latexinfo-defun-type '('defun-type "Variable"))
(put 'defvarx 'latexinfo-defun-type '('defun-type "Variable"))
(put 'defvar 'latexinfo-defun-index 'latexinfo-vindex)
(put 'defvarx 'latexinfo-defun-index 'latexinfo-vindex)

(put 'defopt 'latexinfo-format 'latexinfo-format-defun)
(put 'defoptx 'latexinfo-format 'latexinfo-format-defunx)
(put 'defopt 'latexinfo-end 'latexinfo-end-defun)
(put 'enddefopt 'latexinfo-format 'latexinfo-end-defun)
(put 'defopt 'latexinfo-defun-type '('defun-type "User Option"))
(put 'defoptx 'latexinfo-defun-type '('defun-type "User Option"))
(put 'defopt 'latexinfo-defun-index 'latexinfo-vindex)
(put 'defoptx 'latexinfo-defun-index 'latexinfo-vindex)

(put 'deftp 'latexinfo-format 'latexinfo-format-defun)
(put 'deftpx 'latexinfo-format 'latexinfo-format-defunx)
(put 'deftp 'latexinfo-end 'latexinfo-end-defun)
(put 'enddeftp 'latexinfo-format 'latexinfo-end-defun)
(put 'deftp 'latexinfo-defun-type '('deftp-type nil))
(put 'deftpx 'latexinfo-defun-type '('deftp-type nil))
(put 'deftp 'latexinfo-defun-index 'latexinfo-tindex)
(put 'deftpx 'latexinfo-defun-index 'latexinfo-tindex)

;;; Object-oriented stuff is a little hairier.

(put 'defop 'latexinfo-format 'latexinfo-format-defun)
(put 'defopx 'latexinfo-format 'latexinfo-format-defunx)
(put 'defop 'latexinfo-end 'latexinfo-end-defun)
(put 'enddefop 'latexinfo-format 'latexinfo-end-defun)
(put 'defop 'latexinfo-defun-type '('defop-type nil))
(put 'defopx 'latexinfo-defun-type '('defop-type nil))
(put 'defop 'latexinfo-defun-index 'latexinfo-findex)
(put 'defopx 'latexinfo-defun-index 'latexinfo-findex)

(put 'defmethod 'latexinfo-format 'latexinfo-format-defun)
(put 'defmethodx 'latexinfo-format 'latexinfo-format-defunx)
(put 'defmethod 'latexinfo-end 'latexinfo-end-defun)
(put 'enddefmethod 'latexinfo-format 'latexinfo-end-defun)
(put 'defmethod 'latexinfo-defun-type '('defmethod-type "Method"))
(put 'defmethodx 'latexinfo-defun-type '('defmethod-type "Method"))
(put 'defmethod 'latexinfo-defun-index 'latexinfo-findex)
(put 'defmethodx 'latexinfo-defun-index 'latexinfo-findex)

(put 'defcv 'latexinfo-format 'latexinfo-format-defun)
(put 'defcvx 'latexinfo-format 'latexinfo-format-defunx)
(put 'defcv 'latexinfo-end 'latexinfo-end-defun)
(put 'enddefcv 'latexinfo-format 'latexinfo-end-defun)
(put 'defcv 'latexinfo-defun-type '('defop-type nil))
(put 'defcvx 'latexinfo-defun-type '('defop-type nil))
(put 'defcv 'latexinfo-defun-index 'latexinfo-vindex)
(put 'defcvx 'latexinfo-defun-index 'latexinfo-vindex)

(put 'defivar 'latexinfo-format 'latexinfo-format-defun)
(put 'defivarx 'latexinfo-format 'latexinfo-format-defunx)
(put 'defivar 'latexinfo-end 'latexinfo-end-defun)
(put 'enddefivar 'latexinfo-format 'latexinfo-end-defun)
(put 'defivar 'latexinfo-defun-type '('defmethod-type "Instance variable"))
(put 'defivarx 'latexinfo-defun-type '('defmethod-type "Instance variable"))
(put 'defivar 'latexinfo-defun-index 'latexinfo-vindex)
(put 'defivarx 'latexinfo-defun-index 'latexinfo-vindex)

;;; Typed functions and variables

(put 'deftypefn 'latexinfo-format 'latexinfo-format-defun)
(put 'deftypefnx 'latexinfo-format 'latexinfo-format-defunx)
(put 'deftypefn 'latexinfo-end 'latexinfo-end-defun)
(put 'enddeftypefn 'latexinfo-format 'latexinfo-end-defun)
(put 'deftypefn 'latexinfo-defun-type '('deftypefn-type nil))
(put 'deftypefnx 'latexinfo-defun-type '('deftypefn-type nil))
(put 'deftypefn 'latexinfo-defun-index 'latexinfo-findex)
(put 'deftypefnx 'latexinfo-defun-index 'latexinfo-findex)

(put 'deftypefun 'latexinfo-format 'latexinfo-format-defun)
(put 'deftypefunx 'latexinfo-format 'latexinfo-format-defunx)
(put 'deftypefun 'latexinfo-end 'latexinfo-end-defun)
(put 'enddeftypefun 'latexinfo-format 'latexinfo-end-defun)
(put 'deftypefun 'latexinfo-defun-type '('deftypefun-type "Function"))
(put 'deftypefunx 'latexinfo-defun-type '('deftypefun-type "Function"))
(put 'deftypefun 'latexinfo-defun-index 'latexinfo-findex)
(put 'deftypefunx 'latexinfo-defun-index 'latexinfo-findex)

(put 'deftypevr 'latexinfo-format 'latexinfo-format-defun)
(put 'deftypevrx 'latexinfo-format 'latexinfo-format-defunx)
(put 'deftypevr 'latexinfo-end 'latexinfo-end-defun)
(put 'enddeftypevr 'latexinfo-format 'latexinfo-end-defun)
(put 'deftypevr 'latexinfo-defun-type '('deftypefn-type nil))
(put 'deftypevrx 'latexinfo-defun-type '('deftypefn-type nil))
(put 'deftypevr 'latexinfo-defun-index 'latexinfo-vindex)
(put 'deftypevrx 'latexinfo-defun-index 'latexinfo-vindex)

(put 'deftypevar 'latexinfo-format 'latexinfo-format-defun)
(put 'deftypevarx 'latexinfo-format 'latexinfo-format-defunx)
(put 'deftypevar 'latexinfo-end 'latexinfo-end-defun)
(put 'enddeftypevar 'latexinfo-format 'latexinfo-end-defun)
(put 'deftypevar 'latexinfo-defun-type '('deftypevar-type "Variable"))
(put 'deftypevarx 'latexinfo-defun-type '('deftypevar-type "Variable"))
(put 'deftypevar 'latexinfo-defun-index 'latexinfo-vindex)
(put 'deftypevarx 'latexinfo-defun-index 'latexinfo-vindex)

(put 'defunx 'latexinfo-deffn-formatting-property
     'latexinfo-format-specialized-defun)
(put 'defmacx 'latexinfo-deffn-formatting-property
     'latexinfo-format-specialized-defun)
(put 'defspecx 'latexinfo-deffn-formatting-property
     'latexinfo-format-specialized-defun)
(put 'defvarx 'latexinfo-deffn-formatting-property
     'latexinfo-format-specialized-defun)
(put 'defoptx 'latexinfo-deffn-formatting-property
     'latexinfo-format-specialized-defun)

(put 'defunx 'latexinfo-defun-indexing-property 'latexinfo-index-defun)
(put 'defmacx 'latexinfo-defun-indexing-property 'latexinfo-index-defun)
(put 'defspecx 'latexinfo-defun-indexing-property 'latexinfo-index-defun)
(put 'defvarx 'latexinfo-defun-indexing-property 'latexinfo-index-defun)
(put 'defoptx  'latexinfo-defun-indexing-property 'latexinfo-index-defun)

;; Number of arguments
(put 'deffn 'latexinfo-numargs 3)
(put 'deffnx 'latexinfo-numargs 3)
(put 'defun 'latexinfo-numargs 2)
(put 'defunx 'latexinfo-numargs 2)
(put 'defmac 'latexinfo-numargs 2)
(put 'defmacx 'latexinfo-numargs 2)
(put 'defspec 'latexinfo-numargs 2)
(put 'defspecx 'latexinfo-numargs 2)
(put 'defvr 'latexinfo-numargs 2)
(put 'defvrx 'latexinfo-numargs 2)
(put 'defvar 'latexinfo-numargs 1)
(put 'defvarx 'latexinfo-numargs 1)
(put 'defopt 'latexinfo-numargs 1)
(put 'defoptx 'latexinfo-numargs 1)
(put 'deftp 'latexinfo-numargs 3)
(put 'deftpx 'latexinfo-numargs 3)
(put 'defop 'latexinfo-numargs 4)
(put 'defopx 'latexinfo-numargs 4)
(put 'defmethod 'latexinfo-numargs 3)
(put 'defmethodx 'latexinfo-numargs 3)
(put 'defcv 'latexinfo-numargs 3)
(put 'defcvx 'latexinfo-numargs 3)
(put 'defivar 'latexinfo-numargs 2)
(put 'defivarx 'latexinfo-numargs 2)
(put 'deftypefn 'latexinfo-numargs 4)
(put 'deftypefnx 'latexinfo-numargs 4)
(put 'deftypefun 'latexinfo-numargs 3)
(put 'deftypefunx 'latexinfo-numargs 3)
(put 'deftypevr 'latexinfo-numargs 3)
(put 'deftypevrx 'latexinfo-numargs 3)
(put 'deftypevar 'latexinfo-numargs 2)
(put 'deftypevarx 'latexinfo-numargs 2)

(provide 'elisp-fmt)