digitalmars.D.learn - how do you append arrays?
- asdf (17/17) Feb 25 2016 I'm trying to make a terminal input preprocessor with
- Nicholas Wilson (5/22) Feb 25 2016 In D the binary operator "~" is used to concatenate both strings
- asdf (4/8) Feb 25 2016 It worked! A link from someone else's question suggested `new
- cym13 (8/35) Feb 25 2016 Just a precision: "lhs ~= rhs" isn't exactly equivalent to "lhs
- asdf (3/15) Feb 25 2016 I tried both, the error this time is:
- Nicholas Wilson (10/27) Feb 25 2016 so you will have to make a copy and then move it
- ag0aep6g (3/6) Feb 25 2016 No, that's fine. `history[1..100]` gives you 99 elements starting at
- Nicholas Wilson (2/8) Feb 25 2016 Derp. You are correct, I was thinking about the first index.
- Steven Schveighoffer (6/23) Feb 25 2016 overlapping copies are not supported.
- Steven Schveighoffer (3/5) Feb 25 2016 Heh, or of course use memmove :)
- asdf (42/49) Feb 25 2016 I got the history list working this morning but probably not very
- Steven Schveighoffer (14/24) Feb 25 2016 ugh!
- asdf (36/38) Feb 26 2016 That works alot better =)
- =?UTF-8?Q?Ali_=c3=87ehreli?= (36/38) Feb 26 2016 The following compiles and seems to work. I've marked my changes with //...
- =?UTF-8?Q?Ali_=c3=87ehreli?= (34/37) Feb 26 2016 I've just found the following code among my collection of D snippets,
- Nicholas Wilson (4/21) Feb 25 2016 Also for this kind of thing you probably want to use a circular
I'm trying to make a terminal input preprocessor with alias/shortcuts and history. import std.stdio; void main() { string line; string[] history; line = readln(); foreach(int i; 0..100) history = history + [""]; // XXX while(!stdin.eof) { writeln(line); if(line != history[0]) { history[1..100] = history[0..99]; history[0] = line; } line = readln(); } }
Feb 25 2016
On Thursday, 25 February 2016 at 12:53:37 UTC, asdf wrote:I'm trying to make a terminal input preprocessor with alias/shortcuts and history. import std.stdio; void main() { string line; string[] history; line = readln(); foreach(int i; 0..100) history = history + [""]; // XXX while(!stdin.eof) { writeln(line); if(line != history[0]) { history[1..100] = history[0..99]; history[0] = line; } line = readln(); } }In D the binary operator "~" is used to concatenate both strings (arrays of characters) and arrays. (also the ~= operator is equivalent to lhs = lhs ~ rhs Nic
Feb 25 2016
On Thursday, 25 February 2016 at 12:58:54 UTC, Nicholas Wilson wrote:In D the binary operator "~" is used to concatenate both strings (arrays of characters) and arrays. (also the ~= operator is equivalent to lhs = lhs ~ rhs NicIt worked! A link from someone else's question suggested `new string[101]` also. Now on to other problems, it never ends...
Feb 25 2016
On Thursday, 25 February 2016 at 12:58:54 UTC, Nicholas Wilson wrote:On Thursday, 25 February 2016 at 12:53:37 UTC, asdf wrote:Just a precision: "lhs ~= rhs" isn't exactly equivalent to "lhs = lhs ~ rhs", those are two distinct operators that may deal with memory etc in different ways. For arrays doing "lhs = lhs ~ rhs" will first create (and allocate) the array corresponding to "lhs ~ rhs" and then assign this new array to lhs. On the other hand "lhs ~= rhs" realises in-place append.I'm trying to make a terminal input preprocessor with alias/shortcuts and history. import std.stdio; void main() { string line; string[] history; line = readln(); foreach(int i; 0..100) history = history + [""]; // XXX while(!stdin.eof) { writeln(line); if(line != history[0]) { history[1..100] = history[0..99]; history[0] = line; } line = readln(); } }In D the binary operator "~" is used to concatenate both strings (arrays of characters) and arrays. (also the ~= operator is equivalent to lhs = lhs ~ rhs Nic
Feb 25 2016
On Thursday, 25 February 2016 at 13:06:10 UTC, cym13 wrote:I tried both, the error this time is: object.Exception /data/data/com.termux/files/home/ldc/runtime/druntime/src/l c/arrayinit.d(151): overlapping array copyIn D the binary operator "~" is used to concatenate both strings (arrays of characters) and arrays. (also the ~= operator is equivalent to lhs = lhs ~ rhs NicJust a precision: "lhs ~= rhs" isn't exactly equivalent to "lhs = lhs ~ rhs", those are two distinct operators that may deal with memory etc in different ways. For arrays doing "lhs = lhs ~ rhs" will first create (and allocate) the array corresponding to "lhs ~ rhs" and then assign this new array to lhs. On the other hand "lhs ~= rhs" realises in-place append.
Feb 25 2016
On Thursday, 25 February 2016 at 13:24:09 UTC, asdf wrote:On Thursday, 25 February 2016 at 13:06:10 UTC, cym13 wrote:so you will have to make a copy and then move it Im assuming history[1..100] = history[0..99]; this is the line causing your problem. Note that D has zero based array indexing so assuming your array has 100 elements history[1..100] is going one past the end of the array. also using a circular buffer here will solve this problem. NicI tried both, the error this time is: object.Exception /data/data/com.termux/files/home/ldc/runtime/druntime/src/l c/arrayinit.d(151): overlapping array copyIn D the binary operator "~" is used to concatenate both strings (arrays of characters) and arrays. (also the ~= operator is equivalent to lhs = lhs ~ rhs NicJust a precision: "lhs ~= rhs" isn't exactly equivalent to "lhs = lhs ~ rhs", those are two distinct operators that may deal with memory etc in different ways. For arrays doing "lhs = lhs ~ rhs" will first create (and allocate) the array corresponding to "lhs ~ rhs" and then assign this new array to lhs. On the other hand "lhs ~= rhs" realises in-place append.
Feb 25 2016
On 25.02.2016 14:33, Nicholas Wilson wrote:Note that D has zero based array indexing so assuming your array has 100 elements history[1..100] is going one past the end of the array.No, that's fine. `history[1..100]` gives you 99 elements starting at index 1, i.e. all except the first one.
Feb 25 2016
On Thursday, 25 February 2016 at 13:38:56 UTC, ag0aep6g wrote:On 25.02.2016 14:33, Nicholas Wilson wrote:Derp. You are correct, I was thinking about the first index.Note that D has zero based array indexing so assuming your array has 100 elements history[1..100] is going one past the end of the array.No, that's fine. `history[1..100]` gives you 99 elements starting at index 1, i.e. all except the first one.
Feb 25 2016
On 2/25/16 8:24 AM, asdf wrote:On Thursday, 25 February 2016 at 13:06:10 UTC, cym13 wrote:overlapping copies are not supported. In this case especially, the copying has to be done backwards. I believe you could use std.algorithm.copy, but probably need to do it with retro as well. -SteveI tried both, the error this time is: object.Exception /data/data/com.termux/files/home/ldc/runtime/druntime/src/ldc/arrayinit.d(151): overlapping array copyIn D the binary operator "~" is used to concatenate both strings (arrays of characters) and arrays. (also the ~= operator is equivalent to lhs = lhs ~ rhs NicJust a precision: "lhs ~= rhs" isn't exactly equivalent to "lhs = lhs ~ rhs", those are two distinct operators that may deal with memory etc in different ways. For arrays doing "lhs = lhs ~ rhs" will first create (and allocate) the array corresponding to "lhs ~ rhs" and then assign this new array to lhs. On the other hand "lhs ~= rhs" realises in-place append.
Feb 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
Feb 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 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...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
Feb 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
Feb 25 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(); }
Feb 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
Feb 26 2016
On 02/26/2016 01:01 AM, Ali Çehreli wrote:On 02/26/2016 12:47 AM, asdf wrote: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(); } AliTrying to uncook the terminal failed however. It can't recognize struct tag-declarations I think:
Feb 26 2016
On Thursday, 25 February 2016 at 12:53:37 UTC, asdf wrote:I'm trying to make a terminal input preprocessor with alias/shortcuts and history. import std.stdio; void main() { string line; string[] history; line = readln(); foreach(int i; 0..100) history = history + [""]; // XXX while(!stdin.eof) { writeln(line); if(line != history[0]) { history[1..100] = history[0..99]; history[0] = line; } line = readln(); } }Also for this kind of thing you probably want to use a circular buffer. I'm sure there is an implementation of one somewhere. see std.range.cycle
Feb 25 2016