February 25, 2016
On 2/25/16 2:12 PM, Steven Schveighoffer wrote:
> I believe you could use std.algorithm.copy, but probably need to do it
> with retro as well.
>

Heh, or of course use memmove :)

-Steve
February 25, 2016
On Thursday, 25 February 2016 at 19:21:31 UTC, Steven Schveighoffer wrote:
> On 2/25/16 2:12 PM, Steven Schveighoffer wrote:
>> I believe you could use std.algorithm.copy, but probably need to do it
>> with retro as well.
>>
>
> Heh, or of course use memmove :)
>
> -Steve

I got the history list working this morning but probably not very efficient. You can see:
---- cut ----
debug = 0;
import std.stdio;
import std.string;

void main() {
    string line;
    string[] history;
    char cmd = '/',
         sep = ';',
         dot = '.',
         bak = '\\';

    line = readln().chomp;
    foreach(int i; 0..100) history ~= "";
    debug(1) { stderr.writeln(history); }

    while(!stdin.eof) {
        string[] emit = line.split(sep);
        foreach(string e; emit) {

            /* how to do proper prefix and/or leading word? */
            if(e[0] == cmd) { /* ... */ }
            else if(e[0] == dot) { /* ... */ }
            else if(e[0] == bak) { /* ... */ }
            else writeln(e);
        }

        if(line != "" && line != history[0]) {
            string[] x = [line];
            foreach(string i; history[0..99]) x ~= i;
            history = x;
        }
        debug(1) { stderr.writeln(history); }

        line = readln().chomp;
    }
}
---- cut ----

Is there a good way to pick out matching prefixes of a string? Picking out the first word without disrupting whitespace after the second word would be nice =)

How do you read chars without waiting for a newline? That would be needed to respond to the ANSI esapes for arrow keys...
February 25, 2016
On 2/25/16 4:39 PM, asdf wrote:

>          if(line != "" && line != history[0]) {
>              string[] x = [line];
>              foreach(string i; history[0..99]) x ~= i;
>              history = x;
>          }

ugh!

history = line ~ history[0 .. $ - 1];

What you may want to consider is making history backwards referenced. That is, history[0] is the oldest line.

Then you could do:
history = history[1 .. $];
history ~= line;

> Is there a good way to pick out matching prefixes of a string? Picking
> out the first word without disrupting whitespace after the second word
> would be nice =)
>
> How do you read chars without waiting for a newline? That would be
> needed to respond to the ANSI esapes for arrow keys...

If you are only getting characters after a newline, then you aren't interacting directly with the terminal (which requires some terminal access library). The terminal is letting the user edit the line, then when he hits return, it sends the whole line to your program. You won't get arrow key codes.

-Steve

February 26, 2016
On Friday, 26 February 2016 at 00:40:40 UTC, Steven Schveighoffer wrote:
> ugh!
>
> history = line ~ history[0 .. $ - 1];

That works alot better =)

Trying to uncook the terminal failed however. It can't recognize struct tag-declarations I think:


/*
   copy-paste code from:
   http://tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html
*/

import core.sys.linux.termios;

// struct termios oldterm;
// struct termios newterm;
termios.termios oldterm;
termios.termios newterm;

void uncook_term() {
    tcgetattr(stdin.fileno, &oldterm);
    newterm = oldterm;

    newterm.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
    newterm.c_iflag = IGNPAR;
    newterm.c_oflag = 0;
    newterm.c_lflag = 0;
    tcflush(stdin.fileno, TCIFLUSH);
    tcsetattr(stdin.fileno, TCSANOW, &newterm);
}

void restore_term() {
    tcsetattr(stdin.fileno, TCSANOW, &oldterm);
}

void main() {
    uncook_term();

    char ch = read();
    while(ch != 'q' && !stdin.eof) {
        write(ch);
        ch = read();
    }

    restore_term();
}



February 26, 2016
On 02/26/2016 12:47 AM, asdf wrote:

> Trying to uncook the terminal failed however. It can't recognize struct
> tag-declarations I think:

The following compiles and seems to work. I've marked my changes with // Ali:

/*
   copy-paste code from:
   http://tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html
*/

import std.stdio;    // Ali
import core.sys.linux.termios;

// struct termios oldterm;
// struct termios newterm;
termios oldterm;    // Ali
termios newterm;    // Ali

void uncook_term() {
    tcgetattr(stdin.fileno, &oldterm);
    newterm = oldterm;

    newterm.c_cflag = /*BAUDRATE | Ali */ CRTSCTS | CS8 | CLOCAL | CREAD;
    newterm.c_iflag = IGNPAR;
    newterm.c_oflag = 0;
    newterm.c_lflag = 0;
    tcflush(stdin.fileno, TCIFLUSH);
    tcsetattr(stdin.fileno, TCSANOW, &newterm);
}

void restore_term() {
    tcsetattr(stdin.fileno, TCSANOW, &oldterm);
}

void main() {
    uncook_term();

    int ch = fgetc(core.stdc.stdio.stdin); //read();  Ali
    while(ch != 'q' && !stdin.eof) {
        write(ch);
        ch = fgetc(core.stdc.stdio.stdin); //read(); Ali
    }

    restore_term();
}

Ali
February 26, 2016
On 02/26/2016 01:01 AM, Ali Çehreli wrote:
> On 02/26/2016 12:47 AM, asdf wrote:
>
>> Trying to uncook the terminal failed however. It can't recognize struct
>> tag-declarations I think:

I've just found the following code among my collection of D snippets, which uses a different method and supports Ctrl-D:

import std.stdio : writef, writeln;
import core.stdc.stdio;
import core.sys.posix.termios;

/* The declaration of cfmakeraw, which is missing from standard D modules. */
extern(C) void cfmakeraw(termios *termios_p);

void main()
{
    /* Saving the existing state of tty. */
    termios oldState;
    tcgetattr(1, &oldState);

    /* Ensuring that it will be restored upon exit. */
    scope (exit) tcsetattr(1, TCSADRAIN, &oldState);

    /* Make a new state and set it to raw mode. */
    termios  newState;
    tcgetattr(1, &newState);
    cfmakeraw(&newState);

    /* Use the new state in this terminal. */
    tcsetattr(1, TCSADRAIN, &newState);

    /*
     * We are ready to read characters in this raw mode...
     */

    /* This is Ctrl-D, the EOF character under Linux. */
    enum endOfFile = '\4';

    for (char c; c != endOfFile; ) {
        c = cast(char)fgetc(stdin);
        writef("%02x ", c);
    }

    writeln();
}

Ali

1 2
Next ›   Last »