orbitalquark / textadept

Textadept is a fast, minimalist, and remarkably extensible cross-platform text editor for programmers.
https://orbitalquark.github.io/textadept
MIT License
636 stars 38 forks source link

textadept doesn't read from stdin #461

Closed Dialga closed 11 months ago

Dialga commented 11 months ago

If I run uname -a|textadept - which according to the help command - [0 args]: Read stdin into a new buffer should open a new buffer with the output of uname, currently this does not happen and instead the last file is reopened instead.

oOosys commented 11 months ago

I can confirm this observation ( v 12, GTK version ).

While I don't know why this does not work as described, I know a simple work-around to achieve the requested effect:

uname -a > tmp.txt ; textadept tmp.txt

orbitalquark commented 11 months ago

You're right @Dialga, this does not work in the Qt version right now. It does work in the Gtk version though. I will have to look into this. Thanks for the report.

orbitalquark commented 11 months ago

At this time you need to pass the -n or --nosession command line argument for no session functionality. For example:

uname -a | textadept -n -

I'll work on a fix for this workaround.

Incidentally, I was wrong about Gtk. It worked for how I invoked my Gtk version, which is always with the -n argument when I'm doing testing.

Dialga commented 11 months ago

Could you also report which commit broke this feature, or has it never worked in the first place?

orbitalquark commented 11 months ago

I'm not sure it has ever worked without -n :(

Dialga commented 11 months ago

Also, wouldn't it be better just to automatically detect if text is being piped into textadept without passing -? I'm using leafpad as a fallback atm and it just works using uname -a|leafpad.

oOosys commented 11 months ago

I confirm that uname -a | textadept -n - works as expected for Textadept 12 GTK-version on Linux Mint 21.2 Xfce and that l3afpad takes the input as described without the need of explicit command line parameter.

orbitalquark commented 11 months ago

Fixed via https://github.com/orbitalquark/textadept/commit/f861c0a7c67ebf28856c2ca67b0cc5eecbf4212e

I'm not sure I can auto-detect stdin being piped because Lua doesn't support testing if stdin has anything to read without blocking and with a timeout (i.e. io.read(0) blocks indefinitely).

oOosys commented 11 months ago

To my current insight the auto-detection need to be done at the level of the introductory C-code. At least this is how it is done in leafpad, l3afpad and mousepad. They seem to re-use C-code coming with gedit for this purpose. In other words the auto-detected input need to be entirely read and then passed to Lua. In my eyes the best fix would be to perform the entire processing of the command line parameter along with reading the stdin within the C-code. Currently there is an "unhealthy" splitting of this task implemented, where two of the options are handled in C-code and the other ones at the Lua level. This split is the reason why I have failed to find out how the other command line parameter are handled in order to provide an idea for the patch. I suppose that handling of all command line parameter and the input from stdin already at the C-code level would make things more straightforward and maybe even result in less code along with the side-effect of automated detection if there is input available on stdin. Here the relevant code parts copy/pasted from source code of leafpad-0.8.17:

    istdin_data = gedit_utils_get_stdin();
    if (stdin_data) {
        gchar *str;
        GtkTextIter iter;

        str = g_convert(stdin_data, -1, "UTF-8",
            get_default_charset(), NULL, NULL, NULL);
        g_free(stdin_data);

//      gtk_text_buffer_set_text(buffer, "", 0);
        gtk_text_buffer_get_start_iter(pub->mw->buffer, &iter);
        gtk_text_buffer_insert(pub->mw->buffer, &iter, str, strlen(str));
        gtk_text_buffer_get_start_iter(pub->mw->buffer, &iter);
        gtk_text_buffer_place_cursor(pub->mw->buffer, &iter);
        gtk_text_buffer_set_modified(pub->mw->buffer, FALSE);
        gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(pub->mw->view), &iter, 0, FALSE, 0, 0);
        g_free(str);
    }

and

// imported from gedit
#ifdef G_OS_UNIX
gchar *gedit_utils_get_stdin (void)
{
    GString * file_contents;
    gchar *tmp_buf = NULL;
    guint buffer_length;
//  GnomeVFSResult  res;
    fd_set rfds;
    struct timeval tv;

    FD_ZERO (&rfds);
    FD_SET (0, &rfds);

    // wait for 1/4 of a second
    tv.tv_sec = 0;
    tv.tv_usec = STDIN_DELAY_MICROSECONDS;

    if (select (1, &rfds, NULL, NULL, &tv) != 1)
        return NULL;

    tmp_buf = g_new0 (gchar, GEDIT_STDIN_BUFSIZE + 1);
    g_return_val_if_fail (tmp_buf != NULL, FALSE);

    file_contents = g_string_new (NULL);

    while (feof (stdin) == 0)
    {
        buffer_length = fread (tmp_buf, 1, GEDIT_STDIN_BUFSIZE, stdin);
        tmp_buf [buffer_length] = '\0';
        g_string_append (file_contents, tmp_buf);

        if (ferror (stdin) != 0)
        {
//          res = gnome_vfs_result_from_errno (); 

            g_free (tmp_buf);
            g_string_free (file_contents, TRUE);
            return NULL;
        }
    }

    fclose (stdin);

    return g_string_free (file_contents, FALSE);
}

The code of leafpad seems not to be really clean and straightforward code - this is my impression - maybe the reason is that I don't understand all of it (for example I can't see what the code waits for 1/4 second). Anyway the detection works OK and the code can be re-used in Textadept for the same purpose.