texmacs-dev
[Top][All Lists]
Advanced

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

[Texmacs-dev] Re: extern-exec and "further customization"


From: Henri Lesourd
Subject: [Texmacs-dev] Re: extern-exec and "further customization"
Date: Wed, 08 Feb 2006 13:05:41 +0100
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.2) Gecko/20030208 Netscape/7.02

Lionel Elie Mamane wrote:

On Tue, Feb 07, 2006 at 10:33:05PM +0100, Henri Lesourd wrote:

- When the user types a command for the plug-in in a session, instead
of sending what he typed, call a scheme procedure with arguments:

* the string the user typed
* the port used to talk to the child process

You can already do this without changing
anything in the standard components
of TeXmacs (but this remains somehow
a hack) ; write a new plugin (let's
call it "foo", to define things clearly),
and in the plugin "foo", do :
<<
(define (foo-plugin-eval name session t)
(display* "foo-plugin-eval=" name "; session=" session "; t=" t "\n")
(if (equal? name "foo")
    (begin
       ... the stuff for the foo plugin ...
    )
  ; Default case
    (plugin-eval0 name session t))
)
(define plugin-eval0 plugin-eval)
(set! plugin-eval foo-plugin-eval)))

This way, (foo-plugin-eval) behaves as a
stub for the real (plugin-eval0) that uses
the socket, and you can preprocess/postprocess
the input & the output exactly the way you
want.

TeXmacs seems not to call plugin-eval itself when the user types
something in a field and "enter", so this fails to achieve the desired
result;

You are right...

it preprocesses only commands to the plugin called by scheme
code with plugin-eval, not commands typed by the user.

Here is exactly what I tried:

Open a document with a pnambic and a scheme session in. Don't launch
the pnambic plugin yet (don't type anything in its session). In the
scheme session, do:

 (define (foo-plugin-eval name session t)
         (display* "debug: " name session t)
          (if (equal? name "pnambic")
              (plugin-eval0 name session (string-append "pre: " t))
              (plugin-eval0 name session t)))
 (define plugin-eval0 plugin-eval)
 (set! plugin-eval foo-plugin-eval)

Then go to the pnambic session and type something. foo-plugin-eval
doesn't get called.

OK. Instead, another solution (that works) is to directly
hook the "enter" key, then. Do :
<<
(define-public (kbd-return) (display "Hello\\n"))
>>

, and you will see that in any context, the effect of
a "return" is a sole "Hello" display on the console.
Then, the next step is to contextually redefine
the (kbd-return), something like that :
<<
(tm-define (kbd-return)
 (:mode inside-foo-session?)
 ... stuff ...)
>>

, the function (inside-foo-session?) being a function that
returns #t if the current cursor position is inside a foo
session (to do this, you must test that the "prog-language"
environment variable is equal to "foo" [use (get-env "prog-language")
for fetching the variable, then test the result against "foo"],
if the markup for the foo sessions looks like that (as it should
be) :
[[
<with|prog-language|foo|...
 <session|
    <input|foo] |...>
    <output|...>
    .....>>
]]).

Note that above, I used (define-public), which is the strongest
redefinition command (this is the one you must use in a Scheme
session : unfortunately, the (tm-define) seems not to be working
correctly in Scheme sessions) ; the (tm-define) allows you for
contextual definitions from inside the code of a plugin (this
is what you are for).

Once you have been able to correctly hook the (kbd-return)
event (namely, to restrict the hooking only to the scope
of a session for the "foo" plugin), you are in a situation
where the default processing of "enter" is not performed
anymore when you are in a session for the plugin "foo".

What remains to be done is to use the position of the
TeXmacs cursor [the function (cursor-path) gives you
this] to "manually" read the content C of the current
<input|Prompt|C> markup where the cursor is [the functions
you can use to do this are (for example) (path->tree)
and (tree->stree)].

Then, as soon as you have been able to decode the
input, you can do your processing, generate the
output, and then, again, you must do "manually"
the insertion of a new line, and positioning the
cursor in the session [cf. probably functions (path-assign)
and (go-to)].

As far as I can remember, the very last version
of TeXmacs ships with a documentation of these
Scheme functions (cursor-path), (path->tree),
the stuff for how to do the contextual overloading,
etc. All these thing are what you need to redefine
events and for processing the document tree in
the Scheme language. These functions are powerful,
so use them !

This being said, perhaps that a simpler solution
to your problem exists, but the one sketched here
is the one that goes back to the primitive level
and gives you a maximal control over your implementation.

And thanks to the contextual overloading system, it
is probably not as much a hack as the one described
in my previous mail.

But it is more work...

But if it worked, it would permit me to do what I want. Thanks for
trying. Unless you can patch it to work, the solutions I have in mind
now are:

- Make two plugins "foo" and "bar" instead of one. Each launches a
  process tm_foo and tm_bar, respectively. tm_foo and tm_bar
  communicate directly between themselves. tm_foo is the "main"
  plugin and when it needs to query the current state of TeXmacs
  (cursor position, ...), it issues
    DATA_BEGIN command:(plugin-eval "bar" "default" (get-cursor-position)) 
DATA_END
  tm_bar gets the information and passes it on to tm_foo.

  This idea was suggested by Bas Spitters.

- Suggestion by Joris: There is already a complete preprocessing
  system available. Use it!

  It first sight, it seems like I'll have to use the complete
  (:serializer ,routine) option: the plugin-input-converters rules
  seem not to be able to rewrite plain text. The documentation
  doesn't say much about the :serializer option. In particular, is
  there a way to call the default serializer? So that I can do
  something like:

   (display*
      "cursor-pos: " (get-cursor-position) "\n"
      "user-command: " (default-serializer input))

If you can do it using the default serializer / default mechanism
for sessions, it is better. There is probably a way to redefine
the serializer in order to go into a Scheme routine that allows
you to freely pre/post process the data in and out of a CLI
plugin (if not, this would clearly be a missing feature).


Best, Henri





reply via email to

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