{"action":"created","issue":{"url":"https://api.github.com/repos/company-mode/company-mode/issues/286","labels_url":"https://api.github.com/repos/company-mode/company-mode/issues/286/labels{/name}","comments_url":"https://api.github.com/repos/company-mode/company-mode/issues/286/comments","events_url":"https://api.github.com/repos/company-mode/company-mode/issues/286/events","html_url":"https://github.com/company-mode/company-mode/issues/286","id":55389153,"number":286,"title":"company-clang doc-buffer implementation","user":{"login":"mehw","id":6450450,"avatar_url":"https://avatars.githubusercontent.com/u/6450450?v=3","gravatar_id":"","url":"https://api.github.com/users/mehw","html_url":"https://github.com/mehw","followers_url":"https://api.github.com/users/mehw/followers","following_url":"https://api.github.com/users/mehw/following{/other_user}","gists_url":"https://api.github.com/users/mehw/gists{/gist_id}","starred_url":"https://api.github.com/users/mehw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mehw/subscriptions","organizations_url":"https://api.github.com/users/mehw/orgs","repos_url":"https://api.github.com/users/mehw/repos","events_url":"https://api.github.com/users/mehw/events{/privacy}","received_events_url":"https://api.github.com/users/mehw/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":15,"created_at":"2015-01-24T23:36:01Z","updated_at":"2015-01-28T21:38:57Z","closed_at":null,"body":"Clang can parse comments/documentation with **-Xclang -code-completion-brief-comments**, but this feature is not implemented in company-clang backend.\r\n\r\nI propose a patch which will make the comments/documentation available when **company-show-doc-buffer** (*F1*) is called; you may customize this behaviour by **M-x customize-group** *RET* **company-clang** once the patch is applyed:\r\n* **Company Clang Parse Documentation**: *When non-nil, clang will parse completion's comments/documentation.*\r\n* **Company Clang Documentation Fill Column**: *Column beyond which automatic line-wrapping should happen.*\r\n* **Company Clang Documentation Justify**: *Specifies which  kind of justification to do.*\r\n\r\n[company-quickhelp] (https://gist.github.com/dgutov/6dd7669697c5c0cd7e8f/) proposed in the \"Documentation popup\" #138 issue will show a popup containing comments/documentation parsed by clang.\r\n\r\n# diff file:\r\n```diff\r\nAuthor: mehw\r\n\r\nClang doc-buffer implementation.\r\n\r\n\r\ndiff -U 4 a/company-clang.el b/company-clang.el\r\n--- a/company-clang.el\t2015-01-24 13:18:20.000000000 +0100\r\n+++ b/company-clang.el\t2015-01-24 22:41:50.601346782 +0100\r\n@@ -79,8 +79,78 @@\r\n   (with-temp-buffer\r\n     (insert-file-contents-literally file nil beg end)\r\n     (buffer-string)))\r\n \r\n+(defcustom company-clang-parse-documentation t\r\n+  \"When non-nil, clang will parse completion's comments/documentation.\"\r\n+  :type 'boolean)\r\n+\r\n+(defcustom company-clang-documentation-fill-column 70\r\n+  \"Column beyond which automatic line-wrapping should happen.\"\r\n+  :type 'integer)\r\n+\r\n+(defcustom company-clang-documentation-justify 'full\r\n+  \"Specifies which  kind of justification to do.\"\r\n+  :type '(choice (const :tag \"Full\" full)\r\n+\t\t (const :tag \"Left\" left)\r\n+\t\t (const :tag \"Right\" right)\r\n+\t\t (const :tag \"Center\" center)\r\n+                 (const :tag \"None\" none)))\r\n+\r\n+(defvar company-clang-summary-list\r\n+  \"Association list of tags and them related documentation.\")\r\n+\r\n+(defun company-clang-meta-for-tag (tag)\r\n+  \"Extract the meta data of a TAG from `company-clang-summary-list'.\"\r\n+  (let ((element (assoc tag company-clang-summary-list))\r\n+\t(match)\r\n+\t(meta))\r\n+    (when element\r\n+      (setq match (car element))\r\n+      (setq meta (get-text-property 0 'meta match))\r\n+      meta)))\r\n+\r\n+(defun company-clang-documentation-for-tag (tag)\r\n+  \"Extract the documentation of a TAG from `company-clang-summary-list'.\"\r\n+  (let ((element (assoc tag company-clang-summary-list))\r\n+\t(doc))\r\n+    (when element\r\n+      (setq doc (car (cdr element)))\r\n+      doc)))\r\n+\r\n+(defun company-clang-doc-buffer (tag)\r\n+  \"Create the documentation buffer for a TAG.\"\r\n+  (let ((meta (company-clang-meta-for-tag tag))\r\n+\t(doc (company-clang-documentation-for-tag tag))\r\n+\t(emptylines \"\\n\\n\"))\r\n+    (unless (and doc meta)\r\n+      (setq emptylines \"\"))\r\n+    (when (or doc meta)\r\n+      (company-doc-buffer\r\n+       (concat meta\r\n+\t       emptylines\r\n+\t       (company-clang-string-to-paragraph\r\n+\t\tdoc\r\n+\t\tcompany-clang-documentation-fill-column\r\n+\t\tcompany-clang-documentation-justify))))))\r\n+\r\n+(defun company-clang-string-to-paragraph (str &optional len justify)\r\n+  \"Convert STR to a paragraph.\r\n+\r\n+LEN controls the width.\r\n+\r\n+JUSTIFY specifies which kind of justification to do: `full',\r\n+`left', `right', `center', or `none' (equivalent to nil).  A\r\n+value of t means handle each paragraph as specified by its text\r\n+properties.\"\r\n+  (when str\r\n+    (with-temp-buffer\r\n+      (insert str)\r\n+      (when len\r\n+\t(setq fill-column len))\r\n+      (fill-region (point-min) (point-max) justify)\r\n+      (buffer-string))))\r\n+\r\n (defun company-clang-guess-prefix ()\r\n   \"Try to guess the prefix file for the current buffer.\"\r\n   ;; Prefixes seem to be called .pch.  Pre-compiled headers do, too.\r\n   ;; So we look at the magic number to rule them out.\r\n@@ -108,10 +178,11 @@\r\n ;; parsing ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r\n \r\n ;; TODO: Handle Pattern (syntactic hints would be neat).\r\n ;; Do we ever see OVERLOAD (or OVERRIDE)?\r\n+;; Parse completion's comments/documentation too\r\n (defconst company-clang--completion-pattern\r\n-  \"^COMPLETION: \\\\_<\\\\(%s[a-zA-Z0-9_:]*\\\\)\\\\(?: : \\\\(.*\\\\)$\\\\)?$\")\r\n+   \"^COMPLETION: \\\\_<\\\\(%s[a-zA-Z0-9_:]*\\\\) : \\\\(.*?\\\\)\\\\(?: : \\\\(.*\\\\)\\\\)\\\\{,1\\\\}$\")\r\n \r\n (defconst company-clang--error-buffer-name \"*clang-error*\")\r\n \r\n (defun company-clang--lang-option ()\r\n@@ -136,9 +207,11 @@\r\n           (when (and meta (not (string= match meta)))\r\n             (put-text-property 0 1 'meta\r\n                                (company-clang--strip-formatting meta)\r\n                                match)))\r\n-        (push match lines)))\r\n+        (push match lines)\r\n+        (let ((doc (match-string-no-properties 3)))\r\n+          (push (list match doc) company-clang-summary-list))))\r\n     lines))\r\n \r\n (defun company-clang--meta (candidate)\r\n   (get-text-property 0 'meta candidate))\r\n@@ -186,8 +259,9 @@\r\n         (setq buffer-read-only t)\r\n         (goto-char (point-min))))))\r\n \r\n (defun company-clang--start-process (prefix callback &rest args)\r\n+  (setq company-clang-summary-list nil)\r\n   (let ((objc (derived-mode-p 'objc-mode))\r\n         (buf (get-buffer-create \"*clang-output*\"))\r\n         (process-adaptive-read-buffering nil))\r\n     (with-current-buffer buf (erase-buffer))\r\n@@ -226,8 +300,10 @@\r\n                   t))))))\r\n \r\n (defsubst company-clang--build-complete-args (pos)\r\n   (append '(\"-fsyntax-only\" \"-Xclang\" \"-code-completion-macros\")\r\n+\t  (when company-clang-parse-documentation\r\n+\t    (list \"-Xclang\" \"-code-completion-brief-comments\"))\r\n           (unless (company-clang--auto-save-p)\r\n             (list \"-x\" (company-clang--lang-option)))\r\n           company-clang-arguments\r\n           (when (stringp company-clang--prefix)\r\n@@ -321,8 +397,9 @@\r\n     (candidates (cons :async\r\n                       (lambda (cb) (company-clang--candidates arg cb))))\r\n     (meta       (company-clang--meta arg))\r\n     (annotation (company-clang--annotation arg))\r\n+    (doc-buffer (company-clang-doc-buffer arg))\r\n     (post-completion (let ((anno (company-clang--annotation arg)))\r\n                        (when (and company-clang-insert-arguments anno)\r\n                          (insert anno)\r\n                          (if (string-match \"\\\\`:[^:]\" anno)\r\n\r\n```"},"comment":{"url":"https://api.github.com/repos/company-mode/company-mode/issues/comments/71921699","html_url":"https://github.com/company-mode/company-mode/issues/286#issuecomment-71921699","issue_url":"https://api.github.com/repos/company-mode/company-mode/issues/286","id":71921699,"user":{"login":"dgutov","id":271877,"avatar_url":"https://avatars.githubusercontent.com/u/271877?v=3","gravatar_id":"","url":"https://api.github.com/users/dgutov","html_url":"https://github.com/dgutov","followers_url":"https://api.github.com/users/dgutov/followers","following_url":"https://api.github.com/users/dgutov/following{/other_user}","gists_url":"https://api.github.com/users/dgutov/gists{/gist_id}","starred_url":"https://api.github.com/users/dgutov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dgutov/subscriptions","organizations_url":"https://api.github.com/users/dgutov/orgs","repos_url":"https://api.github.com/users/dgutov/repos","events_url":"https://api.github.com/users/dgutov/events{/privacy}","received_events_url":"https://api.github.com/users/dgutov/received_events","type":"User","site_admin":false},"created_at":"2015-01-28T21:38:57Z","updated_at":"2015-01-28T21:38:57Z","body":"That's a good result, thanks!"}}