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

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

Re: replacing a function with another one


From: lee
Subject: Re: replacing a function with another one
Date: Mon, 10 Mar 2014 16:29:41 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (gnu/linux)

Michael Heerdegen <michael_heerdegen@web.de> writes:

> lee <lee@yun.yagibdah.de> writes:
>
>> Thank you!  It seems rather complicated --- I´ll look into it tomorrow
>> and try to figure it out.
>
> Actually, it's only abstract, but quite simple.

Too abstract, maybe:  I understand by removing abstractions and don´t
know how else I could understand something.  I can only do it the other
way round, i. e. understand something first and then come up with
abstractions.  That´s a barrier which has its merits.

> About the original question you raised (not forgetting patterns), would
> something like this do what you want:
>
> (advice-add
>  'hi-lock-write-interactive-patterns :around
>  ;; also include `hi-lock-file-patterns'
>  (lambda (f &rest args)

What does (f &rest args) do or mean?

>    (let ((hi-lock-interactive-patterns
>         (append hi-lock-interactive-patterns
>                 hi-lock-file-patterns))))

So this makes one list from both variables (lists) and assigns it to one
of them.  Then, I suppose, the intention is to have
hi-lock-write-interactive-patterns write them --- i. e. combine both
lists just before writing them and otherwise keep them separate.  This
would be better than my approach because it avoids duplication.

I´ll have to try that out.

>    (apply f args)))

f args?

hi-lock-write-interactive-patterns doesn´t have any arguments.

>> (defvar patterns-other-buffer nil)
>> (defvar original-buffer nil)
>>
>> (defadvice hi-lock-set-file-patterns (after my-test-obtain-patterns)
>>   (setq patterns-other-buffer (ad-get-arg 0))
>>   (ad-deactivate 'hi-lock-set-file-patterns)
>>   (pop-to-buffer original-buffer)
>>   (hi-lock-set-file-patterns patterns-other-buffer))
>>
>> (defadvice hi-lock-find-patterns (before hi-lock-find-other-patterns 
>> activate)
>>   (my-test))
>>
>> (defun my-test ()
>>   (interactive)
>>   (ad-activate 'hi-lock-set-file-patterns)
>>   (save-excursion
>>     (save-restriction
>>       (widen)
>>       (goto-char (point-min))
>>       (when (re-search-forward "^// ext-fontify-defs: " nil t)
>>      (message "found marker")
>>      (let ((filename (thing-at-point 'filename)))
>>        (message "filename at %d: %s/%s for buffer %s" (point) filename 
>> (thing-at-point 'filename) (buffer-name original-buffer))
>>        (when filename
>>          (when (file-exists-p filename)
>>            (setq original-buffer (current-buffer))
>>            (find-file filename)
>>            (set-auto-mode-0 'hi-lock-mode t))))))))
>>
>>
>> This actually works, i. e. it lets me save hi-lock-mode
>> highlighting-patterns to an arbitrary file and put a line like "//
>> ext-fontify-defs: name-of-file-with-patterns" into the file to load the
>> highlighting-patterns from the file the name of which is specified in
>> that line.  The patterns are then applied.
>>
>> But I don´t like this.  It´s a really terrible hack.
>
> I'm not sure I completely understand what you are trying to do.

I´m trying to make an extension to hi-lock-mode.

The mode keeps the highlighting-patterns in the same buffer as the text
that is being highlighted.  Instead, I want to be able to keep the
highlighting-patterns in a separate file.  From the buffer that has the
text which is to be highlighted, I want to refer to this separate file
so that the highlighting-patterns kept in the separate file are used to
highlight the text in the buffer.

Think of it as a form of '#include "highlighting.patterns"'.


To achieve this, I´m inserting my own function before
hi-lock-find-patterns.  My own function searches for the equivalent of
the '#include "highlighting.patterns"' statement.  When it finds one, it
visits[1] the specified file (like "highlighting.patterns").  That puts
this file into the current buffer.

Since hi-lock-find-patterns reads the highlighting-patterns from the
current buffer, it now reads them from the file I have included rather
than from the original buffer.  And hi-lock-find-patterns calls
hi-lock-set-file-patterns, giving the patterns as an argument to it so
that hi-lock-set-file-patterns can apply the highlighting to the current
buffer.

At that point, the current buffer is the included file and not the
original buffer I want the highlighting-patterns applied to.  Therefore,
I need to get a copy of the patterns, switch back to the original buffer
and apply the patterns from my copy.  To get a copy of the patterns and
to apply them to the original buffer, I use hi-lock-set-file-patterns:

So I first advise hi-lock-set-file-patterns to get a copy of the
patterns.  Then I disable the advice, switch to the original buffer and
run the non-advised version of hi-lock-set-file-patterns again to
finally apply my copy of the patterns to the buffer I want them applied
to.

It´s self-modifying code, a creative (ab)use of defadvice.

I think it´s an awkward way to do this and a terrible hack: I´m cheating
an "unexpected" buffer underneath hi-lock-find-patterns to read
"unexpected" patterns.  This isn´t necessarily too bad, but much worse,
I´m bending hi-lock-set-file-patterns in a weird way.

> Generally, you could use directory local variables for storing your
> patterns, but these would of course not be automatically updated, what
> you presumably want.

Hmm ...  First I should make the variables I´m using to remember what
was the original buffer and to have a copy of the patterns local.  Then
I should somehow follow your approach to avoid duplication of the
patterns.

Another step is to modify things so that when adding a new pattern, the
new pattern is added to the included file rather than to the original
file.  Avoiding the duplication might make this easier.

> Nitpick: instead of activating and deactivating pieces of advice, define
> a variable and use it as a flag.  The flag says whether the advice
> should kick in.  In the advice's body, look at the variable and decide
> what to do.

That´s a good idea.  I don´t need to bend hi-lock-set-file-patterns so
much when I use a variable.  And I can probably use add-advice because I
don´t need to disable the advice anymore.


[1]: Another question:

To get patterns from a separate file, I´m using find-file.  This is
probably not very efficient:  I suspect that the file is actually loaded
every time, with all what that implies.  So when I have X files that
want to read highlighting-patterns from the same file, that same file is
loaded and processed X times.

It would be more efficient to load and to process the file only once.  I
don´t know how to go about that, though.  Is there a function that tells
me for a given file which buffer is visiting it?  I could write one that
goes through the buffer list and returns the buffer visiting the file,
but maybe there is something better for this.

As to processing the file only once, I´d have to somehow check whether
the currently available copy of patterns is from the file that is to be
included.  If it is, just apply the copy, if not, read the file.

But then, suppose I have X files each of which include patterns-A and
patterns-B:  This caching strategy would fail, and patterns-A and
patterns-B would be processed X times.

Can I somehow have a (global) "collection" of included files and their
patterns?  In that case, once patterns-A has been processed, the
patterns would be available and could be applied to any file which
includes patterns-A, no matter in which order the pattern-files are
included.


-- 
Knowledge is volatile and fluid.  Software is power.



reply via email to

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