From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Stefan Monnier via Users list for the GNU Emacs text editor Newsgroups: gmane.emacs.help Subject: Re: [QUESTION] I have problem on my org-contacts capf function source code Date: Sun, 14 Nov 2021 18:10:29 -0500 Message-ID: References: Reply-To: Stefan Monnier Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="17294"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) To: help-gnu-emacs@gnu.org Cancel-Lock: sha1:opKE8u2xhrqt+7G4ZFWp4rq47w8= Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Mon Nov 15 00:11:28 2021 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mmOel-0004Lg-6K for geh-help-gnu-emacs@m.gmane-mx.org; Mon, 15 Nov 2021 00:11:27 +0100 Original-Received: from localhost ([::1]:35652 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mmOej-0007XC-Fx for geh-help-gnu-emacs@m.gmane-mx.org; Sun, 14 Nov 2021 18:11:25 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:50900) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mmOe2-0007Wn-2y for help-gnu-emacs@gnu.org; Sun, 14 Nov 2021 18:10:42 -0500 Original-Received: from ciao.gmane.io ([116.202.254.214]:47360) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mmOe0-00013l-D7 for help-gnu-emacs@gnu.org; Sun, 14 Nov 2021 18:10:41 -0500 Original-Received: from list by ciao.gmane.io with local (Exim 4.92) (envelope-from ) id 1mmOdw-0003SW-Cq for help-gnu-emacs@gnu.org; Mon, 15 Nov 2021 00:10:36 +0100 X-Injected-Via-Gmane: http://gmane.org/ Received-SPF: pass client-ip=116.202.254.214; envelope-from=geh-help-gnu-emacs@m.gmane-mx.org; helo=ciao.gmane.io X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.248, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "help-gnu-emacs" Xref: news.gmane.io gmane.emacs.help:134594 Archived-At: > I try to write a capf function for org-contacts to auto complete > contact names after "@". Here is my code, but it still does not > work. Some description of what you mean by "doesn't work" would be helpful. > #+begin_src emacs-lisp > (defun org-contacts-org-complete-function () > "Function used in `completion-at-point-functions' in `org-mode' to complete @name." > (when-let* ((@-prefix-p (string-prefix-p "@" (thing-at-point 'symbol))) > (symbol (thing-at-point 'symbol)) > (prefix (substring-no-properties symbol 1 nil)) > (bounds (bounds-of-thing-at-point 'symbol)) > (begin (car bounds)) > (end (cdr bounds))) You ask thingatpt to compute the same information 3 times. Not only it's inefficient, but if for some reason it doesn't return the same info all three times your code will be broken. So better start with `bounds-of-thing-at-point` and then use `buffer-substring` to extract `symbol` from it, and then use that in the `string-prefix-p` test. > (list begin > end > (all-completions > prefix > (mapcar > (lambda (contact) (plist-get contact :name)) > (org-contacts--all-contacts)) > 'stringp) Don't use `prefix` here. Provide the a general completion table which can be used with other prefixes as well: the CAPF function should only choose which kind of completion to perform and which part of the buffer. > ;; (completion-table-dynamic > ;; (lambda (input) > ;; (mapcar > ;; (lambda (contact) (plist-get contact :name)) > ;; (org-contacts--all-contacts)))) That would be better, yes. > :exclusive 'no Is this *really* necessary? This functionality is fundamentally very hard to implement, so it comes with a lot of warts and restrictions. Only use it if it's really really indispensable. > :annotation-function ; tags > ;; TODO > (lambda (candidate) > "Tags: ") > :company-docsig #'identity ; metadata > :company-doc-buffer ; doc popup > (lambda (candidate) > (let ((name (plist-get candidate :name)) > (file (plist-get candidate :file)) > (position (plist-get candidate :position))) > (company-doc-buffer > ;; get org-contact headline and property drawer. > (with-current-buffer (find-file-noselect file) > (goto-char position) > (when (derived-mode-p 'org-mode) > ;; `org-edit-src-code' is not a real narrowing command. > ;; Remove this first conditional if you don't want it. > (cond ((ignore-errors (org-edit-src-code)) > (delete-other-windows)) > ((org-at-block-p) > (org-narrow-to-block)) > (t (org-narrow-to-subtree))) > (buffer-substring (point-min) (point-max))))))) > :company-location (lambda (candidate) > (let ((name (plist-get candidate :name)) > (file (plist-get candidate :file)) > (position (plist-get candidate :position))) > (with-current-buffer (find-file-noselect file) > (goto-char position) > (cons (current-buffer) position))))))) I recommend you move those functions outside of the CAFP function instead, give them a name and refer to them by name here. Will make the code easier to read, will help indentation-depth, and can also help debugging. Stefan