bug-apl
[Top][All Lists]
Advanced

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

Re: [Bug-apl] Yet another editor thingy.


From: Chris Moller
Subject: Re: [Bug-apl] Yet another editor thingy.
Date: Thu, 2 Aug 2018 13:12:56 -0400
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1

I agree with you.  I'm not all that pleased with it either, mostly because I don't understand why it works--it was something suggested by someone on StackOverflow. 

Whatever is going on seems to be the result of the EINTR out of the fgetc()--I'll try to look more closely at that.  I'll also try your save-state suggestion.  It seems to be a highly intermittent thing, which, in combination with fork()/exec()/terminate, possibly suggests a race condition somewhere.

--Chris


On 02/08/18 11:40, Juergen Sauermann wrote:
Hi Chris,

I am not entirely happy with your patch, in particular because I cannot
judge which other effects it may have
and which problem it actually solves.

What I can see is that:

You disable automatic flushing when you are waiting for an input
character and get a ^C interrupt or so,

What I do not understand is:

1. according to https://en.cppreference.com/w/cpp/io/manip/unitbuf, the
unitbuf bit
changes only the timing of the output but not the output itself. So it
buys you some
time but is not guaranteed to do that. My concern is that you may
introduce some
unpredictable behaviour into the main input loop of the GNU interpreter.

2. Wouldn't it be cleaner if you save the state of CIN and CERR when you
enter your editor
and restore it when leaving it? Right now the state of CIN and CERR
seems to change after
hitting ^C for the first time.

/// Jürgen


On 08/02/2018 03:14 PM, Chris Moller wrote:
I thought I'd fixed the echo blocking!

Actually, what seems to be happening is that APL is still running--you
can enter an APL _expression_, press enter, and the result will show up
on your screen--but keystroke echoing is somehow inhibited.

There was a patch for this Jürgenput in for me that showed up in SVN
1060, but that seems to be not quite right.  That patch was an
alternative to a slightly clumsier patch I'd tried earlier, somaybe
reverting to the original patch would help:


Index: LineInput.cc
===================================================================
--- LineInput.cc        (revision 1060)
+++ LineInput.cc        (working copy)
@@ -968,9 +968,10 @@
       {
         if (errno == EINTR)
            {
-             clearerr(stdin);
-             CIN.unsetf(ios_base::unitbuf);
-             goto again;
+            clearerr (stdin);
+            CIN.unsetf( std::ios_base::unitbuf );
+            CERR.unsetf( std::ios_base::unitbuf );
+            return UNI_ASCII_CR;
            }
 
        if (got_WINCH)

If you could give that a try and let me know if it fixes things in
your environment, I'd appreciate it.


Thanks,

Chris



On 02/08/18 07:12, Hans-Peter Sorge wrote:
Hello Chris,

thank you for this master piece. The line editing in GNU APL is a bit
cumbersome.

But the apl session gets blocked during editing (edif2).

Currently I have no clue, how to analyze it.

Thank you again.

Hans-Peter


Am 30.07.2018 um 20:52 schrieb Chris Moller:
Thanks, Jürgen.

And for anyone interested, my editor interface native function is
available at https://github.com/ChrisMoller/edif.git

Basically, what it does is allow users to invoke external editors
from within APL sessions, i.e., while running APL, you can edit
functions using vi, emacs, gvim, nano, and probably other editors
(those are the ones I've tested) and when the function is saved it
will fixed in APL.  Two versions are included, libedif and libedif2,
the former, which I usually ⎕fx as 'edif', runs in the APL process
and defaults to opening the function in vi.  libedif2, which I
usually ⎕fx as 'edif2', spawns separate processes for the editors
(defaulting to emacs) it opens, allowing the user to go on using APL
while the editor is open--including testing saved functions
real-time without having to close the editor--and allowing any
number of edit windows to be open simultaneously on different
functions. 

Feedback welcome, and here's the README:





edif is a GNU APL native function that allows the use of external
editors
from within an APL session.

Usage:

    edif 'function_name'
    or
    edif2 'function_name'

Both of these will open an editor, typically vi or emacs, containing the
present definition of the specified function, or, if the function
doesn't
exist, a boilerplate function header consisting of the function name.
After saving the edited definition and exiting the editor, the function
will appear in the APL workspace..  (In the case of a new function, the
boilerplate name can be edited as necessary:

    fubar

can be edited to

    z←x fubar y

and the right thing will be fixed in APL.  (Even existing functions
can be
modified this way.))

The two versions of the function differ in that the first version, edif,
suspends the current APL session until the editor is closed, while the
second version, edif2, opens the editor in a separate process, in a
separate window, while the APL session remains active.  This allows
functions to be edited and tested concurrently without having to go
into and out of the editor.  edif2 also allows multiple editor windows
to be open simultaneously on different functions.

Both versions have a dyadic form:

    'editor' edif 'function_name'
    or
    'editor' edif2 'function_name'

where 'editor' is the editor to be invoked.  For example:

    'vi' edif 'fubar'

would open function fubar using the vi editor.

    'emacs' edif2 'fu'
    'emacs' edif2 'bar'

would open functions fu and bar in separate emacs windows.

edif will look for the environment variable EDIF and will use the string
specified by that variable as the command line to invoke the chosen
editor.
For example:

   export EDIF="nano"

will cause edif to default to using the nano editor.  Similarly, the
EDIF2
variable affects the default edif2 editor.

edif has been tested with emacs, vi, and nano; edif2 with emacs and
gvim.
The default editor for edif is vi; the default for edif2 is

   "emacs --geometry=40x20  -background '#ffffcc' -font 'DejaVu Sans
Mono-10'"

The dyadic form is a one-shot thing--edif doesn't remember editors
specified this way and the monadic form will go back to using the
default or environment-specified editor.

edif may be included in the workspace with:

    'libedif.so' ⎕fx 'edif'
   
and edif2 with:

    'libedif2.so' ⎕fx 'edif2'

Of course, you can use any function names you like and, as long as
you use
different names, both versions can be used at the same time.

So far as I can tell, edif doesn't interfere with Elias Mårtenson's
emacs APL mode, but I haven't thoroughly tested that.

By the way, "edif" is short for "editor interface."



Implimentation note:

edif and edif2 work by storing an editable version of the specified
function in:

/var/run/user/<uid>/<pid>/<name>.apl 

where <uid> is the user's userid, <pid> is the process id of the APL
session, and <name> is the function name.  This allows multiple users
each to have multiple simultaneous APL sessions with workspaces with
identical names.  No locking is done by edif and I've no idea if APL
itself has any protection against a writable workspace being open in
multiple simultaneous sessions, but it opens up the possibility that
you can hose the workspace.  So while, as far as edif is concerned
you can have multiple simultaneous sessions aimed at the same lib0
workspace, you probably shouldn't do it.

Also, I've no idea if Windows or any Linux distribution other than
Fedora has a /var directory, so using this directory may be
non-portable.



On 30/07/18 10:52, Juergen Sauermann wrote:
Hi Chris,

thanks, done in *SVN 1060*.

/// Jürgen


On 07/30/2018 03:59 PM, Chris Moller wrote:
Here's an even simpler, more direct, patch:

    Index: LineInput.cc
    ===================================================================
    --- LineInput.cc        (revision 1054)
    +++ LineInput.cc        (working copy)
    @@ -966,6 +966,11 @@
     const int b0 = fgetc(stdin);
        if (b0 == EOF)
           {
    +       if (errno == EINTR) {
    +         clearerr (stdin);
    +         CIN.unsetf( std::ios_base::unitbuf );
    +         goto again;
    +       }
            if (got_WINCH)
               {
                 got_WINCH = false;



          

        

      





reply via email to

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