unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* C Headers completion candidates
@ 2016-07-14  4:51 B.V. Raghav
  2016-07-14 13:02 ` Stefan Monnier
  2016-07-14 14:27 ` Drew Adams
  0 siblings, 2 replies; 9+ messages in thread
From: B.V. Raghav @ 2016-07-14  4:51 UTC (permalink / raw)
  To: help-gnu-emacs

Hi,

I want a set of completion candidates for c-headers, something like
`auto-complete c headers'. Only, I do not want the complete ac-library
tagged along, nor do I want the popups.

Personally, I want to use the icicles interface, where I feel
comfortable.

Step 1. Identifying the context
--- Example
#include <vec|>
---
`|' represents the cursor here
I think I can code the regexp here

Step 2. Set of completion candidates
Search the $INCLUDE environment variable, with `visited' flags on the
folders that have been visited; and create the set of completion
candidates, one in a line

I hope there is a smarter way?

Step 3. Tell Icicles to invoke these set of completion candidates, when
the context is active. How? I do not know.

Help appreciated.

Thanks,
r

-- 
(B.V. Raghav)
Ph.D. Student,
Design Programme, IIT Kanpur




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: C Headers completion candidates
  2016-07-14  4:51 C Headers completion candidates B.V. Raghav
@ 2016-07-14 13:02 ` Stefan Monnier
  2016-07-14 14:27 ` Drew Adams
  1 sibling, 0 replies; 9+ messages in thread
From: Stefan Monnier @ 2016-07-14 13:02 UTC (permalink / raw)
  To: help-gnu-emacs

> I want a set of completion candidates for c-headers, something like
> `auto-complete c headers'. Only, I do not want the complete ac-library
> tagged along, nor do I want the popups.
> Personally, I want to use the icicles interface, where I feel
> comfortable.

That's part of the motivation behind completion-at-point-functions: some
way to specify which completions make sense at the current position in
the buffer, which can then be used by different UIs (don't know if
Icicles supports it, but it's supported by company-mode as well as by
the default `completion-at-point` (bound to M-TAB by default or to TAB
if you set `tab-always-indent` to `complete`))


        Stefan




^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: C Headers completion candidates
  2016-07-14  4:51 C Headers completion candidates B.V. Raghav
  2016-07-14 13:02 ` Stefan Monnier
@ 2016-07-14 14:27 ` Drew Adams
  2016-07-17  8:40   ` B.V. Raghav
  1 sibling, 1 reply; 9+ messages in thread
From: Drew Adams @ 2016-07-14 14:27 UTC (permalink / raw)
  To: bvraghav, help-gnu-emacs

> I want a set of completion candidates for c-headers, something like
> `auto-complete c headers'. Only, I do not want the complete ac-library
> tagged along, nor do I want the popups.
> 
> Personally, I want to use the icicles interface, where I feel
> comfortable.

Icicles does not provide anything special for completing symbols
in C headers.  Whatever is already available for vanilla Emacs
(e.g. to determine the possible completions for a partial symbol
before the cursor) should be usable with Icicles.

> Step 1. Identifying the context
> --- Example
> #include <vec|>
> ---
> `|' represents the cursor here
> I think I can code the regexp here

What regexp do you mean, here?  If the cursor is at that location
then all that should be needed is a function that takes the name
just before the cursor (e.g. "vec") and returns completions for
it (your step 2).

> Step 2. Set of completion candidates
> Search the $INCLUDE environment variable, with `visited' flags on the
> folders that have been visited; and create the set of completion
> candidates, one in a line

Sounds reasonable.  Maybe someone familiar with Emacs C mode(s)
can speak to what is already available wrt such gathering of
completion candidates.  (Icicles does nothing specific for this,
but if you have a function that provides the completions then
Icicles can make use of it.)

> I hope there is a smarter way?

Maybe there is already a function that gathers completions here.
Wait to hear from those who are familiar with Emacs C modes.

If there is not then you can code it, along the lines you
suggested (using $INCLUDE etc.).

> Step 3. Tell Icicles to invoke these set of completion candidates,
> when the context is active. How? I do not know.

As Stefan mentioned, `completion-at-point-functions' is a list
of functions that, in the current mode (e.g. C mode), perform
completion for a name (e.g. a "symbol") that is just before the
cursor.

If there is already a function on the list that is the value of
that variable when you are in C mode, then try it.  `C-M-i'
is bound to `complete-symbol' - this is what you would use to
complete the symbol (name) at point.

If that command uses the minibuffer to let you choose among
completions when there is more than one, then (in Icicle mode)
you can take advantages of Icicles completion automatically.

But probably it does not use the minibuffer for this.

If `C-M-i' does not use the minibuffer when there are multiple
choices, but instead expects you to keep hitting `C-M-i' to
cycle to another choice, then you will need to use another
command instead, which does use the minibuffer (e.g. bind it
to `C-M-i' or some other key, in C mode).  (If a command uses
the minibuffer with completion then you can use it with Icicles
completion.)

In that case, you will need to code that command.  If there is
already a function on list `completion-at-point-functions' in
C mode, then you can model the Icicles command that you will
add to list `completion-at-point-functions' on that existing
function.

The only change you should need to make is for the case when
multiple completions are available.  In that case, call
`completing-read', passing the list of completions as argument,
to read the chosen candidate.  Then, delete the partial name
just before the cursor and replace it by that chosen completion
(just as the vanilla code does).



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: C Headers completion candidates
  2016-07-14 14:27 ` Drew Adams
@ 2016-07-17  8:40   ` B.V. Raghav
  2016-07-17 15:02     ` Drew Adams
  0 siblings, 1 reply; 9+ messages in thread
From: B.V. Raghav @ 2016-07-17  8:40 UTC (permalink / raw)
  To: Drew Adams; +Cc: help-gnu-emacs

Drew Adams <drew.adams@oracle.com> writes:

[snip]
>
>> Step 1. Identifying the context
>> --- Example
>> #include <vec|>
>> ---
>> `|' represents the cursor here
>> I think I can code the regexp here

I have no experience with using using the point so far inside of an
interactive function. But I think it is do-able. Albeit, not with a
regexp, but somehow.

I leave it for another rainy day.

[snip]
>
>> Step 2. Set of completion candidates
>> Search the $INCLUDE environment variable, with `visited' flags on the
>> folders that have been visited; and create the set of completion
>> candidates, one in a line

I realised the environment variables, that I had initialized in
~/.bashrc are not avaliable at the X server environment (probably, not
even with ~/.profile). So I hard coded the list, and copy-pasted from
the bashrc. 

(require 'cl-lib)
(defun c-include-path()
    (cl-reduce #'append
	       (mapcar #'parse-colon-path
		       `("/usr/include/c++/5:/usr/include/c++/4.9"
			 ,(format "%s/usr/include" (getenv "HOME"))
			 "/usr/include:/usr/local/include:/usr/include/x86_64-linux-gnu"))))

The order of directories is important here.

May be it looks dirty, but work for now.

Then, I retrieved all the files at first level depth of each of this
list. And mapped all the directory elements to their absolute paths.

;; (c-include-path)
(defun c-include-libs-raw(path)
  (cl-reduce #'append
	     (mapcar (lambda (x)
		       (mapcar (lambda (y)
				 (let ((long-y (format "%s%s" x y)))
				   (if (file-accessible-directory-p long-y)
				       long-y
				     y)))
			       (when (file-accessible-directory-p x)
				 (directory-files x))))
		     path)))

Then I removed the unnecessary files

(defun sanitize-dir-read (path-list)
  (cl-remove-if (lambda(x)
		  (or (string-suffix-p "." x)
		      (string-suffix-p "~" x)
		      (string-prefix-p "_" x)))
		path-list))

[snip]
>
>> Step 3. Tell Icicles to invoke these set of completion candidates,
>> when the context is active. How? I do not know.
[snip]

Here I used the completion in two steps. Though not as `smart', or
seamless; but works

(defun c-header()
  (let* ((include-path-list (c-include-path))
	 (lib-name-list (sanitize-dir-read (c-include-libs-raw (c-include-path))))
	 (selected-path (completing-read "Library: " lib-name-list))
	 (final-path (if (file-accessible-directory-p selected-path)
			 (read-file-name "Header: " (format "%s/" selected-path))
		       selected-path))
	 (inclusive-path (which-c-prefix final-path include-path-list))
	 (include-file-name (file-relative-name final-path inclusive-path)))
    include-file-name))

First completing the name from the files (and folders) at first
level. Then using the response to aid the next level completion.

Most C-libraries, that I require, are first class citizens, and are
completed within the first level of completion. Like <vector>,
<utility>, <unordered_map>, <iterator> --- all completed using the same
set of functions above, work like charm with Icicles.

For other libraries, I have to use the name of the library and S-TAB,
like <boost/algorithm/string/case_conv.hpp> This is a little longer, but
way faster (and cleaner) than what I used to do earlier. Either, I copy
pasted from the earlier files, or used a snippet.

Way forward, I want to implement this:
1. Implement a list of completions, at the user level; quite like
   persistent completions; 

   a. Any completion, after being pruned for prefix (before being
      returned), goes as into the list of completions, without
      duplicacy.

   b. This list is read, and appened to the lib-name-list; before the
      first completion is invoked.

Thanks,
r
-- 
(B.V. Raghav)
Ph.D. Student,
Design Programme, IIT Kanpur




^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: C Headers completion candidates
  2016-07-17  8:40   ` B.V. Raghav
@ 2016-07-17 15:02     ` Drew Adams
  2016-07-18  3:07       ` B.V. Raghav
  0 siblings, 1 reply; 9+ messages in thread
From: Drew Adams @ 2016-07-17 15:02 UTC (permalink / raw)
  To: bvraghav; +Cc: help-gnu-emacs

.. Lots of fantastic stuff, and explanation of the code...

> Way forward, I want to implement this:
> 1. Implement a list of completions, at the user level; quite like
>    persistent completions;
> 
>    a. Any completion, after being pruned for prefix (before being
>       returned), goes as into the list of completions, without
>       duplicacy.
> 
>    b. This list is read, and appened to the lib-name-list; before the
>       first completion is invoked.

(There was no #2, right?  Not that one was needed - this is
already quite a lot. ;-))

By "persistent completions" I guess you mean a persistent list
of completions such as those you gather, as in 
https://www.emacswiki.org/emacs/Icicles_-_Persistent_Completions.
Or maybe you would even add a defcustom that has, as its default
value, a list of such completions.

It all sounds good to me.  And I expect it could be useful to
others too.  And this is so whether or not people use Icicles.
That's the beauty of using just `completing-read': it works
whether or not one uses Icicles.

And the code creating the persistent completions could also be
used by other completion libraries besides Icicles - they too
could no doubt make use of such a persistent list, even if they
do their thing otherwise than by `completing-read'.

Please consider, if you haven't already, posting your code as
a library somewhere (e.g. Emacs Wiki, MELPA).  Others will not
only use it but also offer suggestions etc.

[There might be better (in some sense) ways to code some of
what you have.  For example, it might be that using dolist
instead of the more functional-style nested mapcars, etc.
would be faster.  And maybe just use `string-match-p' with a
regexp such as "[.~_]$", instead of bothering with testing
multiple suffixes separately using `string-suffix-p'.  But
such considerations, even assuming they make sense, are not
important.]



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: C Headers completion candidates
  2016-07-17 15:02     ` Drew Adams
@ 2016-07-18  3:07       ` B.V. Raghav
  2016-07-18  5:17         ` Drew Adams
  0 siblings, 1 reply; 9+ messages in thread
From: B.V. Raghav @ 2016-07-18  3:07 UTC (permalink / raw)
  To: Drew Adams; +Cc: help-gnu-emacs

Drew Adams <drew.adams@oracle.com> writes:

> .. Lots of fantastic stuff, and explanation of the code...
>
Your acknowledgement is very encouraging. Thank you.

>> Way forward, I want to implement this:
>> 1. Implement a list of completions, at the user level; quite like
>>    persistent completions;
>> 
>>    a. Any completion, after being pruned for prefix (before being
>>       returned), goes as into the list of completions, without
>>       duplicacy.
>> 
>>    b. This list is read, and appened to the lib-name-list; before the
>>       first completion is invoked.
>
> (There was no #2, right?  Not that one was needed - this is
> already quite a lot. ;-))

Yes, in fact there were #2 and #3
2. Projectile use a completion set for projectile-find-file (probably
   using completing-read).

   a. Leverage it on the include list for first level of completions,
      with a user custom regexp variable for filter, e.g. "\\.h[pp]\?$"

   b. May be it is just worth accumulating the results of a shell `find'
      on the projectile-root with flags `-type f -iname ...' and so
      forth.

3. Make use of the point, e.g.
   #include <vec|>

   If I invoke the command `insert-c-header' here, then the software
   should:
   a. mark a region like ...<[vec]|>... (`[]' representing the region, and
      `|' -- the point)
   b. send this as completion string to match against. e.g. using
      argument initial for the `completing-read' function. But
      Info document for Elisp > Minibuffers > Initial Input, says:

      " This is a mostly-deprecated feature for specifying that the
      minibuffer should start out with certain text, instead of empty as
      usual.
      
      AND

      " *We discourage use of a non-‘nil’ value for INITIAL*

      Is there another way? What more should I read?

>
> By "persistent completions" I guess you mean a persistent list
> of completions such as those you gather, as in 
> https://www.emacswiki.org/emacs/Icicles_-_Persistent_Completions.

Yes very much so. I will open another thread, to understand why
Icicles-PersistentCompletions does not like me!

> Or maybe you would even add a defcustom that has, as its default
> value, a list of such completions.
>
Does it mean that the variable will be initialized once using 'customize
variable' interface, and then subsequent automatic edits will be lost
between different emacs sessions.

> It all sounds good to me.  And I expect it could be useful to
> others too.  And this is so whether or not people use Icicles.
> That's the beauty of using just `completing-read': it works
> whether or not one uses Icicles.
>
> And the code creating the persistent completions could also be
> used by other completion libraries besides Icicles - they too
> could no doubt make use of such a persistent list, even if they
> do their thing otherwise than by `completing-read'.
>
I did not realize that the code creating persistent list may be
orthogonal to `c-header', also --- until I read this. Thank you.

> Please consider, if you haven't already, posting your code as
> a library somewhere (e.g. Emacs Wiki, MELPA).  Others will not
> only use it but also offer suggestions etc.
>
I am just a novice with lisp... Flattered with the suggestion. I will
definitely try to package this, put it up on melpa, and discuss it on
Emacs Wiki.

> [There might be better (in some sense) ways to code some of
> what you have.  For example, it might be that using dolist
`C-h i m elisp RET i dolist RET' Thanks, I did not know about this. `C-x
r m'

> instead of the more functional-style nested mapcars, etc.
> would be faster.  And maybe just use `string-match-p' with a
> regexp such as "[.~_]$", instead of bothering with testing
Yeah... Thank you this looks both simpler to read and easy to type.

> multiple suffixes separately using `string-suffix-p'.  But
> such considerations, even assuming they make sense, are not
> important.]

Thanks... 

-- 
(B.V. Raghav)
Ph.D. Student,
Design Programme, IIT Kanpur



^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: C Headers completion candidates
  2016-07-18  3:07       ` B.V. Raghav
@ 2016-07-18  5:17         ` Drew Adams
  2016-07-18 11:21           ` B.V. Raghav
  0 siblings, 1 reply; 9+ messages in thread
From: Drew Adams @ 2016-07-18  5:17 UTC (permalink / raw)
  To: bvraghav; +Cc: help-gnu-emacs

I can't comment on most of what you wrote - I have no special
competence about the use case etc.  But I can at least speak
to the use of Icicles etc.

>    b. send this as completion string to match against. e.g. using
>       argument initial for the `completing-read' function. But
>       Info document for Elisp > Minibuffers > Initial Input, says:
> 
>        " This is a mostly-deprecated feature for specifying that the
>        minibuffer should start out with certain text, instead of empty
>        as usual.
>       AND
>        " *We discourage use of a non-'nil' value for INITIAL*

Vanilla Emacs considers parameter INITIAL-INPUT to be deprecated.
Icicles does not.  But even vanilla Emacs still respects it.  IMO,
it is up to _you_ to decide whether, for your context, it is more
useful to use INITIAL-INPUT or DEF (or both).

(`C-h f completing-read' in Icicle mode mentions this.)

In Icicle mode you can also choose to insert the default value
(DEF) if INITIAL-INPUT is nil.  You use var `icicle-default-value'
to control such behavior.  This is a user option, but you can also
bind it in code if you want.

> > By "persistent completions" I guess you mean a persistent list
> > of completions such as those you gather, as in
> > https://www.emacswiki.org/emacs/Icicles_-_Persistent_Completions.
> 
> Yes very much so. I will open another thread, to understand why
> Icicles-PersistentCompletions does not like me!

OK.  You can also take it off the mailing list, if you think
others might not be too interested.  It's up to you.  If you
think you've found a bug, that's best reported directly using
`icicle-send-bug-report'.

> > Or maybe you would even add a defcustom that has, as its default
> > value, a list of such completions.
> >
> Does it mean that the variable will be initialized once using 'customize
> variable' interface, and then subsequent automatic edits will be lost
> between different emacs sessions.

Automatic changes to a user option can also be saved persistently
(not lost), if that's what you want, using `customize-save-variable'.

The behavior depends on what you want.  But if you use a user
option then unless the user has explicitly chosen automatic
updating you generally don't want to change the value.

IMO it is OK for code to change an option value outside the
Customize UI (e.g. using `customize-save-variable'), but only
if the user is aware of this behavior and has chosen it.  I.e.,
you don't want to do something behind the user's back.

> > Please consider, if you haven't already, posting your code as
> > a library somewhere (e.g. Emacs Wiki, MELPA).  Others will not
> > only use it but also offer suggestions etc.
> >
> I am just a novice with lisp... Flattered with the suggestion. I will
> definitely try to package this, put it up on melpa, and discuss it on
> Emacs Wiki.

It can't hurt. ;-)  If something is useful for you it is likely
it will be useful for someone else.  Even code that doesn't do
something that someone else finds directly useful can serve as
food for thought for other uses.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: C Headers completion candidates
  2016-07-18  5:17         ` Drew Adams
@ 2016-07-18 11:21           ` B.V. Raghav
  2016-07-18 14:17             ` Drew Adams
  0 siblings, 1 reply; 9+ messages in thread
From: B.V. Raghav @ 2016-07-18 11:21 UTC (permalink / raw)
  To: Drew Adams; +Cc: help-gnu-emacs

Drew Adams <drew.adams@oracle.com> writes:

> Vanilla Emacs considers parameter INITIAL-INPUT to be deprecated.
> Icicles does not.  But even vanilla Emacs still respects it.  IMO,
> it is up to _you_ to decide whether, for your context, it is more
> useful to use INITIAL-INPUT or DEF (or both).
>
> (`C-h f completing-read' in Icicle mode mentions this.)
>
> In Icicle mode you can also choose to insert the default value
> (DEF) if INITIAL-INPUT is nil.  You use var `icicle-default-value'
> to control such behavior.  This is a user option, but you can also
> bind it in code if you want.

I refactored `c-header' to accept an optional `initial' argument,

(defun c-header(&optional initial)
  ;; code.. code.. code..
  (completing-read var1 var2 nil nil initial)
  ;; code.. code.. code..)

Then combined it with yasnippets, the following way:

# -*- mode: snippet -*-
# name : #include <...>
# key  : inc
# binding: C-c C-c C-i
# --
#include <`(c-header yas/selected-text)`>

The key binding makes it simpler for me to fulfill the use-case.

Example:
(_ represents point and [] represents region)

| Description                        | On Display   |
|------------------------------------+--------------|
| write vec                          | vec_         |
| mark (may be C-S-a)                | [vec]_       |
| Invoke yasnippets with C-c C-c C-i | #include <_> |

On the minibuffer I can see the selected text following the prompt

-----------------
Header: vec_

All I require is a TAB (or S-TAB) with Icicles and I am good to go!

Thanks,

-- 
(B.V. Raghav)
Ph.D. Student,
Design Programme, IIT Kanpur



^ permalink raw reply	[flat|nested] 9+ messages in thread

* RE: C Headers completion candidates
  2016-07-18 11:21           ` B.V. Raghav
@ 2016-07-18 14:17             ` Drew Adams
  0 siblings, 0 replies; 9+ messages in thread
From: Drew Adams @ 2016-07-18 14:17 UTC (permalink / raw)
  To: bvraghav; +Cc: help-gnu-emacs

> All I require is a TAB (or S-TAB) with Icicles and I am good to go!

You can also have the completions displayed without hitting
TAB or S-TAB, if you want.  To do that, just customize or
bind option `icicle-show-Completions-initially-flag' to `t'.

Or to have completions shown not initially (i.e., even from
empty input) but only as soon as you start typing, just set
`icicle-incremental-completion' to non-`nil' and non-`t'.

You might also want to define different sort orders on the
candidates.

See also:

* Option `icicle-top-level-when-sole-completion-flag'

* https://www.emacswiki.org/emacs/Icicles_-_Icompletion#IncrementalCompletion

  (options `icicle-incremental-completion',
  `icicle-incremental-completion-delay',
  `icicle-incremental-completion-threshold', and
  `icicle-show-Completions-initially-flag')

* https://www.emacswiki.org/emacs/Icicles_-_Sorting_Candidates



^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-07-18 14:17 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-07-14  4:51 C Headers completion candidates B.V. Raghav
2016-07-14 13:02 ` Stefan Monnier
2016-07-14 14:27 ` Drew Adams
2016-07-17  8:40   ` B.V. Raghav
2016-07-17 15:02     ` Drew Adams
2016-07-18  3:07       ` B.V. Raghav
2016-07-18  5:17         ` Drew Adams
2016-07-18 11:21           ` B.V. Raghav
2016-07-18 14:17             ` Drew Adams

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).