File 2879-Emacs-erlang-mode-make-show-doc-for-function-more-ro.patch of Package erlang

From 9a7a38539fa3a311ab454f6ab17253e198372bae Mon Sep 17 00:00:00 2001
From: Kjell Winblad <kjellwinblad@gmail.com>
Date: Wed, 16 Oct 2019 16:49:40 +0200
Subject: [PATCH 09/10] Emacs erlang-mode: make show doc for function more
 robust

This commit makes the functionality for opening the documentation for
a function more robust than previously and should work even if the API
of the Emacs man package changes, given that the name of the man
buffer for a module contains the module name and the word man. The
previous fix broke the open documentation for a function functionality
in Emacs 24.3. The code in this commit has been tested to work in
Emacs 24.3, Emacs 25 and Emacs 26.
---
 lib/tools/emacs/erlang.el | 132 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 105 insertions(+), 27 deletions(-)

diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
index c95ef14ae6..6f1b190854 100644
--- a/lib/tools/emacs/erlang.el
+++ b/lib/tools/emacs/erlang.el
@@ -2135,6 +2135,14 @@ This function is aware of imported functions."
 ;; chosen to keep it since it provides a very useful functionality
 ;; which is not possible to achieve using a clean approach.
 ;;   / AndersL
+;;
+;; The previous hack seems to have broken in Emacs 25. This is fixed
+;; by trying to find the function in the man buffer a few times with a
+;; delay in between (see function
+;; erlang-man-repeated-search-for-function). This fix is also a hack
+;; but it should be quite robust and will work even if the function
+;; that erlang-man-function-display-man-page tries to hook into
+;; disappears or changes.
 
 (defvar erlang-man-function-name nil
   "Name of function for last `erlang-man-function' call.
@@ -2154,7 +2162,7 @@ patch to `Man-notify-when-ready'.")
     (when (or (null modname) (string= modname ""))
       (error "No Erlang module name given"))
     (cond ((fboundp 'Man-notify-when-ready)
-           ;; Emacs 19:  The man command could possibly start an
+           ;; From Emacs 19:  The man command could possibly start an
            ;; asynchronous process, i.e. we must hook ourselves into
            ;; the system to be activated when the man-process
            ;; terminates.
@@ -2169,7 +2177,9 @@ patch to `Man-notify-when-ready'.")
           (t
            (erlang-man-module modname)
            (when funcname
-             (erlang-man-find-function (current-buffer) funcname))))))
+             (erlang-man-repeated-search-for-function nil
+                                                      funcname
+                                                      modname))))))
 
 (defun erlang-man-function (&optional name)
   "Find manual page for NAME, where NAME is module:function.
@@ -2190,12 +2200,6 @@ This function is aware of imported functions."
   (require 'man)
   (setq name (or name
                  (erlang-default-function-or-module)))
-  (erlang-man-function-display-man-page name)
-  (sleep-for 0 600)
-  ;; A hack to make sure that the function scrolls
-  ;; to the description of the function when it is
-  ;; the first time that the man page for a module
-  ;; is opened
   (erlang-man-function-display-man-page name))
 
 
@@ -2211,6 +2215,54 @@ opening the man page for the function."
         (erlang-man-function name)
       (error "No function name under the cursor"))))
 
+(defun erlang-man-repeated-search-for-function (man-buffer
+                                                function-name
+                                                &optional
+                                                module-name)
+  "This function tries to scroll MAN-BUFFER to the documentation
+of function FUNCTION-NAME. The function will try again a few
+times if the documentation for FUNCTION-NAME can't be found. This
+is necessary as the man page is loaded asynchronously from Emacs
+19 and the correct function to hook into depends on the Emacs
+version. The function will automatically try to find the correct
+buffer from the list of opened buffers if MAN-BUFFER is nil. The
+optional parameter MODULE-NAME will make the search for the
+buffer more accurate."
+  (let* ((time-between-attempts 0.5)
+         (max-wait-time 5.1)
+         (search-for-function
+          (lambda (self
+                   time-waited
+                   time-between-attempts
+                   max-wait-time
+                   man-buffer
+                   function-name
+                   module-name
+                   )
+            (when (and (not (erlang-man-find-function man-buffer function-name module-name))
+                       (<= (+ time-waited time-between-attempts)
+                           max-wait-time))
+              (message "Finding function %s..." function-name)
+                                        ; Call this function again later
+              (run-at-time time-between-attempts nil
+                           self
+                           self
+                           (+ time-waited time-between-attempts)
+                           time-between-attempts
+                           max-wait-time
+                           man-buffer
+                           function-name
+                           module-name)
+              ))))
+    (funcall search-for-function
+             search-for-function
+             0.0
+             time-between-attempts
+             max-wait-time
+             man-buffer
+             function-name
+             module-name)))
+
 ;; Should the defadvice be at the top level, the package `advice' would
 ;; be required.  Now it is only required when this functionality
 ;; is used.  (Emacs 19 specific.)
@@ -2233,31 +2285,57 @@ command is executed asynchronously."
     "Set point at the documentation of the function name in
 `erlang-man-function-name' when the man page is displayed."
     (if erlang-man-function-name
-        (erlang-man-find-function (ad-get-arg 0) erlang-man-function-name))
-    (setq erlang-man-function-name nil)))
+        (erlang-man-repeated-search-for-function (ad-get-arg 0)
+                                                 erlang-man-function-name)
+      (setq erlang-man-function-name nil))))
 
 
-(defun erlang-man-find-function (buf func)
-  "Find manual page for function in `erlang-man-function-name' in buffer BUF."
-  (if func
-      (let ((win (get-buffer-window buf)))
-        (if win
-            (progn
-              (set-buffer buf)
-              (goto-char (point-min))
-              (if (re-search-forward
-                   (concat "^[ \t]*\\([a-z0-9_]*[ \t]*:\\)?[ \t]*" func "[ \t]*([A-Za-z0-9 \t:,_()]*)[ \t]*->")
-                   (point-max) t)
-                  (progn
-                    (forward-word -1)
-                    (set-window-point win (point)))
+
+
+(defun erlang-man-find-function (buf func &optional module-name)
+  "Find manual page for function `erlang-man-function-name' in buffer BUF.
+The function will automatically try to find the correct buffer among the
+opened buffers if BUF is nil. The optional parameter MODULE-NAME will make
+the search for the buffer more accurate."
+  (let ((buffer (or buf
+                    (progn
+                      ; find buffer containing man page
+                      (require 'cl-lib)
+                      (car (cl-remove-if-not (lambda (buf)
+                                               (string-match
+                                                (or module-name "")
+                                                (format "%s" buf)))
+                                             (cl-remove-if-not
+                                              (lambda (buf)
+                                                (string-match
+                                                 "[Mm][Aa][Nn]"
+                                                 (format "%s" buf)))
+                                              (buffer-list))))))))
+    (if (and func buffer)
+        (let ((win (get-buffer-window buffer)))
+          (if win
+              (progn
+                (set-buffer buffer)
+                (goto-char (point-min))
                 (if (re-search-forward
-                     (concat "^[ \t]*\\([a-z0-9_]*[ \t]*:\\)?[ \t]*" func "[ \t]*\(")
+                     (concat "^[ \t]*\\([a-z0-9_]*[ \t]*:\\)?[ \t]*" func "[ \t]*([A-Za-z0-9 \t:,_()]*)[ \t]*->")
                      (point-max) t)
                     (progn
                       (forward-word -1)
-                      (set-window-point win (point)))
-                  (message "Could not find function `%s'" func))))))))
+                      (set-window-point win (point))
+                      (message "Found documentation for function `%s'" func)
+                      t)
+                  (if (re-search-forward
+                       (concat "^[ \t]*\\([a-z0-9_]*[ \t]*:\\)?[ \t]*" func "[ \t]*\(")
+                       (point-max) t)
+                      (progn
+                        (forward-word -1)
+                        (set-window-point win (point))
+                        (message "Found documentation for function `%s'" func)
+                        t)
+                    (progn
+                      (message "Could not find function `%s'" func)
+                      nil)))))))))
 
 (defvar erlang-man-file-regexp
   "\\(.*\\)/man[^/]*/\\([^.]+\\)\\.\\([124-9]\\|3\\(erl\\)?\\)\\(\\.gz\\)?$")
-- 
2.16.4

openSUSE Build Service is sponsored by