unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* completing on makefile targets
@ 2019-09-12 18:24 Stephen Leake
  2019-09-12 19:41 ` Stefan Monnier
  0 siblings, 1 reply; 5+ messages in thread
From: Stephen Leake @ 2019-09-12 18:24 UTC (permalink / raw)
  To: emacs-devel

When I start a compile from a Makefile, sometimes the completion
recognizes the makefile targets, sometimes it doesn't. Some recent
change to master made it stop working at all; it still sort of works in
emacs 26.

makefile-mode provides a function `makefile-completion-at-point', which
could do the right thing, but it is not called by the default setup.

Investigating, it seems the situation is quite complex. I'm
not at all clear why it seemed to work.

The completion is done by `completion-at-point', bound to TAB in the
minibuffer.

`completion-at-point' essentially runs the hook
`completion-at-point-functions'.

The completion is done in the minibuffer set up by `compilation-read-command',
which calls `read-shell-command'. That calls `read-from-minibuffer' with
a setup hook that includes `shell-completion-vars'. That sets many
things, including `completion-at-point-functions', which is set to
`comint-completion-at-point'.

`comint-completion-at-point' just runs the hook
`comint-dynamic-complete-functions'.

`shell-completion-vars' also sets `comint-dynamic-complete-functions' to
`shell-dynamic-complete-functions'.

`shell-dynamic-complete-functions' does not include
`makefile-completion-at-point' by default, so I added a let-binding of
that in my custom function to start a compilation. Alternately, I could
add the makefile completion function to the default value; this approach
seems cleaner for debugging.

That almost works; makefile-completion-at-point is called, but returns
nil. That's because it uses the buffer-local variable
`makefile-target-table' to store the targets for completion. The function
`makefile-pickup-targets' fills that local variable.

For some reason, let-binding `makefile-target-table' in my top level
function does not work, so I now have this workaround:

(defun sal-makefile-completions-at-point ()
  (let ((makefile-target-table sal-makefile-target-table))
    (makefile-completions-at-point)))

(defun make-compile (command)
  (interactive
   (progn
     (makefile-pickup-targets)
     (list
      (let ((shell-dynamic-complete-functions (list #'sal-makefile-completions-at-point))
	    (sal-makefile-target-table (copy-sequence makefile-target-table)))
	(compilation-read-command compile-command)))))

 (compilation-start compile-command))


This works, but seems unnecessarily complicated (and mysterious).

Why does let-binding `makefile-target-table' work in
`sal-makefile-completions-at-point', but not in `make-compile'?


One step to improving this to to provide a new function `makefile-targets'
that always reads the Makefile and returns the target list, avoiding the
local variable cache. There may be some very large makefile where this
is too slow; the time is not noticeable in the Emacs master top level
makefile (1190 lines).

That requires knowing the "source" buffer while in the minibuffer; is
there a standard way to get that?

--
-- Stephe



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

* Re: completing on makefile targets
  2019-09-12 18:24 completing on makefile targets Stephen Leake
@ 2019-09-12 19:41 ` Stefan Monnier
  2019-09-12 21:38   ` Stephen Leake
  0 siblings, 1 reply; 5+ messages in thread
From: Stefan Monnier @ 2019-09-12 19:41 UTC (permalink / raw)
  To: Stephen Leake; +Cc: emacs-devel

> Why does let-binding `makefile-target-table' work in
> `sal-makefile-completions-at-point', but not in `make-compile'?

Because makefile-target-table is buffer-local, so the let-binding in
`make-compile` only affects the buffer-local value of that var.

BTW, an alternative approach is to add a pcomplete/make function which
will compute the completions for `make` (regardless if called
from`make-compile` or from, say, M-!) by looking at the Makefile in the
current directory.

> That requires knowing the "source" buffer while in the minibuffer; is
> there a standard way to get that?

I think you want `minibuffer-selected-window`


        Stefan




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

* Re: completing on makefile targets
  2019-09-12 19:41 ` Stefan Monnier
@ 2019-09-12 21:38   ` Stephen Leake
  2019-09-12 22:26     ` Stefan Monnier
  0 siblings, 1 reply; 5+ messages in thread
From: Stephen Leake @ 2019-09-12 21:38 UTC (permalink / raw)
  To: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> Why does let-binding `makefile-target-table' work in
>> `sal-makefile-completions-at-point', but not in `make-compile'?
>
> Because makefile-target-table is buffer-local, so the let-binding in
> `make-compile` only affects the buffer-local value of that var.

And the Makefile is current when make-compile is called, but the
minibuffer is current when completion-at-point and
sal-makefile-completions-at-point are called.

Ok, I thought it was something like that, but could not sort out the
logic.

> BTW, an alternative approach is to add a pcomplete/make function which
> will compute the completions for `make` (regardless if called
> from`make-compile` or from, say, M-!) by looking at the Makefile in the
> current directory.

Yeah, but I hate making assumptions like that; the relevant Makefile
could easily be somewhere else.

>> That requires knowing the "source" buffer while in the minibuffer; is
>> there a standard way to get that?
>
> I think you want `minibuffer-selected-window`

ok, thanks.

I'd like to get the same completion in the *compilation* buffer, but I
don't see anything in compilation-start that remembers the calling
buffer. I'll have to add a global variable, or store it in the current
project.

-- 
-- Stephe



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

* Re: completing on makefile targets
  2019-09-12 21:38   ` Stephen Leake
@ 2019-09-12 22:26     ` Stefan Monnier
  2019-09-14  0:55       ` Stephen Leake
  0 siblings, 1 reply; 5+ messages in thread
From: Stefan Monnier @ 2019-09-12 22:26 UTC (permalink / raw)
  To: Stephen Leake; +Cc: emacs-devel

> Yeah, but I hate making assumptions like that; the relevant Makefile
> could easily be somewhere else.

For the general pcomplete functionality to work, it's necessary for the
minibuffer's default-directory to be the same as that where the command
will be run.  So, in the pcomplete/make function you *can* presume that
the default-directory is the one where `make` will run (and hence follow
`make`s rule about how to find the appropriate makefile).

Maybe the makefile you find won't be the one in the original make-mode
buffer, but if so (presumably) `make` itself will also use the other
makefile rather than one in the buffer.


        Stefan




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

* Re: completing on makefile targets
  2019-09-12 22:26     ` Stefan Monnier
@ 2019-09-14  0:55       ` Stephen Leake
  0 siblings, 0 replies; 5+ messages in thread
From: Stephen Leake @ 2019-09-14  0:55 UTC (permalink / raw)
  To: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> Yeah, but I hate making assumptions like that; the relevant Makefile
>> could easily be somewhere else.
>
> For the general pcomplete functionality to work, it's necessary for the
> minibuffer's default-directory to be the same as that where the command
> will be run.  So, in the pcomplete/make function you *can* presume that
> the default-directory is the one where `make` will run (and hence follow
> `make`s rule about how to find the appropriate makefile).

Hmm. Looking at the current pcomplete/make in pcmpl-gnu.el, that's what
it does. It even handles the 'make' -f option. So I could just use that
function.

Hmm. pcomplete-completions-at-point is already in
shell-dynamic-complete-functions, so maybe that's why completion on
makefile targets was working, sometimes. So now I could try to figure
out why it stopped working.

I've now written a completion-at-point function that also handles
targets in included makefiles, which I've wanted for a long time. I'll
test that for a while, then look into adding that (with a controlling
option) to pcomplete/make.

-- 
-- Stephe



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

end of thread, other threads:[~2019-09-14  0:55 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-12 18:24 completing on makefile targets Stephen Leake
2019-09-12 19:41 ` Stefan Monnier
2019-09-12 21:38   ` Stephen Leake
2019-09-12 22:26     ` Stefan Monnier
2019-09-14  0:55       ` Stephen Leake

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

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