help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [QUESTION] I have problem on my org-contacts capf function source co


From: Christopher M. Miles
Subject: Re: [QUESTION] I have problem on my org-contacts capf function source code
Date: Mon, 15 Nov 2021 17:05:40 +0800
User-agent: mu4e 1.7.0; emacs 28.0.60

Here is my changed source code:

#+begin_src emacs-lisp
(defun org-contacts-org-complete--annotation-function (candidate)
  "Return org-contacts tags of contact candidate."
  ;; TODO
  "Tags: ")

(defun org-contacts-org-complete--doc-function (candidate)
  "Return org-contacts content of contact 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)))))))

(defun org-contacts-org-complete--location-function (candidate)
  "Return org-contacts location of contact 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))))

(defun org-contacts-org-complete-function ()
  "Function used in `completion-at-point-functions' in `org-mode' to complete 
@name."
  (when-let* ((bounds (bounds-of-thing-at-point 'symbol))
              (begin (car bounds))
              (end (cdr bounds))
              (symbol (buffer-substring-no-properties begin end))
              (@-prefix-p (string-prefix-p "@" symbol))
              (prefix (substring-no-properties symbol 1 nil))
              )
    (list begin
          end
          
          ;; (all-completions
          ;;  nil
          ;;  (mapcar
          ;;   (lambda (contact) (plist-get contact :name))
          ;;   (org-contacts--all-contacts))
          ;;  'stringp)

          ;; FIXME
          (completion-table-dynamic
           (lambda (input)
             (mapcar
              (lambda (contact) (plist-get contact :name))
              (org-contacts--all-contacts))))

          ;; :exclusive 'no
          ;; :annotation-function 
#'org-contacts-org-complete--annotation-function

          ;; :company-docsig #'identity                                    ; 
metadata
          ;; :company-doc-buffer #'org-contacts-org-complete--doc-function ; 
doc popup
          ;; :company-location #'org-contacts-org-complete--location-function
          )))

(add-hook 'completion-at-point-functions 'org-contacts-org-complete-function 
nil 'local)
#+end_src

When I evaluated upper code, and test by typing in "@Chri", I have not seen 
org-contacts related
complete popup candidates. So I describe it not working. I also try to edebug 
on the source code.
Have not found error stacktrace. Don't know where is the problem. If you have 
time, can you try my
code and take a testing debug? Thanks a lot.


Stefan Monnier via Users list for the GNU Emacs text editor 
<help-gnu-emacs@gnu.org> writes:

>> 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.

Advice taken.

>
>>     (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.
>

So, does that mean the "prefix" should be nil?

>>           ;; (completion-table-dynamic
>>           ;;  (lambda (input)
>>           ;;    (mapcar
>>           ;;     (lambda (contact) (plist-get contact :name))
>>           ;;     (org-contacts--all-contacts))))
>
> That would be better, yes.

Don't know whether my code is right.

>
>>           :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.

I read the ~:exclusive 'no~ docstring of ~completion-at-point-functions~ which 
means auto pass to next
completion backend if this completion backend failed. I think it should be used 
here.

>
>>           :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.
>

I moved those lambda functions to single functions now. Thanks for your 
suggestions.

-- 
[ stardiviner ]
       I try to make every word tell the meaning that I want to express.

       Blog: https://stardiviner.github.io/
       IRC(freenode): stardiviner, Matrix: stardiviner
       GPG: F09F650D7D674819892591401B5DF1C95AE89AC3

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]