« first day (1046 days earlier)      last day (1353 days later) » 

1:09 AM
@Zanna I think Readline may be telling the terminal to treat particular characters specially, which the terminal then does.
 
what I really meant was, I want to learn about this readline thing in general
(I did not mean that you should tell me about it though)
 
Oh. Well, I'm interested in specifically how an application can affect the meaning of control characters.
Like, if nothing is done to treat the form-feed character specially, then entering it as Ctrl+L has the same effect as entering it as Ctrl+V Ctrl+L.
In both cases, an application just sees the form feed character.
But if something is done to treat it specially, then entering it as Ctrl+L gets the special treatment and Ctrl+V Ctrl+L (as before) uses it literally.
Suppose I run:
stty kill j
After that, typing j in that terminal erases what I've typed on the current line.
But I can still run the command echo joy by typing Ctrl+V before the j.
So the behavior here is provided by the terminal, and programs (including through libraries like Readline) can configure the terminal to give special behavior to particular characters.
What I'm not clear on, pun intended, is how one tells a terminal to treat any character as meaning the terminal (rather than the current line or the most recent character) should be cleared.
@Zanna As for GNU Readline, it's a library for reading input from a terminal, which provides interactive editing, history, tab completion, and stuff. Programs in many different languages (including Crystal) can use this library.
@Zanna For all I know, that code might be considered heinous by experienced Crystal programmers. :)
But thanks!
 
1:28 AM
hahaha
 
@EliahKagan To clarify, stty is not specific to Readline or Bash, and j gets the special behavior even in child processes that are not shells. (stty affects its controlling terminal, not any shell.)
@EliahKagan Interactive bash shells use Readline, which provides interactive editing and tab completion, and which is why ~/.inputrc affects the behavior of Bash. In contrast, for example, Dash doesn't use Readline nor anything else providing similar functionality, and pressing the left arrow key while typing a command in Dash doesn't move the cursor to the left.
Many other shells, like Zsh, provide similar functionality but do not use GNU Readline.
@Zanna (I did not take this to mean that I shouldn't say anything about it.)
@Zanna Which part?
Although both Char and String support \u escape sequences, including the \u{ } form to specify one character, String supports \u{ } with multiple hexadecimal code points inside the braces and separated by whitespace.
$ ./ord <<<'Hello, world!'
 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21
$ crystal eval 'puts "\u{48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21}"'
Hello, world!
@EliahKagan Did you get to interpolation? IMO it gets more interesting from that point on.
 
2:10 AM
@EliahKagan haha of course I did not mean that you shouldn't :)
@EliahKagan only saw it
 
2:32 AM
Looking here
must try these things
 
3:02 AM
I'm pleased to see that interpolation allows nesting:
icr(0.35.1) > "#{"#{"#{"#{"#{"#{"x"}"}"}"}"}"}"
 => "x"
 
3:18 AM
@Zanna One way to try out printf, sprintf, or % is to write a program that outputs a (properly aligned) multiplication table.
To do this, it is helpful (though not strictly necessary) to use loops. One way to loop through (for example) the numbers 1 through 12 is:
1.to(12).each do |n|
  puts n  # replace with whatever
end
Sorry, the .each is not needed there. (You can have it, but there is no good reason to use it.)
1.to(12) do |n|
  puts n  # replace with whatever
end
 
 
2 hours later…
5:13 AM
(Also, technically, that might not be considered a loop, since it's really a method call that passes a block to an iterator.)
 
 
5 hours later…
10:22 AM
Unsuccessfully writing to standard output throws an exception, in Crystal:
$ crystal eval 'puts "Hello, world!"' >/dev/full
Unhandled exception: Error writing file: No space left on device (IO::Error)
  from ../../../../usr/share/crystal/src/io/evented.cr:82:13 in 'unbuffered_write'
  from ../../../../usr/share/crystal/src/io/buffered.cr:217:5 in 'flush'
  from ../../../../usr/share/crystal/src/io/buffered.cr:178:7 in 'write_byte'
  from ../../../../usr/share/crystal/src/char.cr:775:9 in 'to_s'
  from ../../../../usr/share/crystal/src/io.cr:174:5 in '<<'
  from ../../../../usr/share/crystal/src/io.cr:188:5 in 'print'
This isn't uncommon. But for some reason it surprised me.
I think this offers some insight:
$ crystal eval 'print "Hello, world!"' >/dev/full
That does not throw an exception (and it prints no text to standard error and exits indicating success).
But:
$ crystal eval 'print "Hello, world!\n"' >/dev/full
Unhandled exception: Error writing file: No space left on device (IO::Error)
  from ../../../../usr/share/crystal/src/io/evented.cr:82:13 in 'unbuffered_write'
  from ../../../../usr/share/crystal/src/io/buffered.cr:144:9 in 'write'
  from ../../../../usr/share/crystal/src/io.cr:470:7 in 'write_utf8'
  from ../../../../usr/share/crystal/src/string.cr:4789:5 in 'to_s'
  from ../../../../usr/share/crystal/src/io.cr:174:5 in '<<'
  from ../../../../usr/share/crystal/src/io.cr:188:5 in 'print'
It seems that standard output is line buffered, so printing a newline flushes the buffer, and it is when the buffer is flushed that the attempt to actually write the file is made, which fails. puts, as well as print with a newline character, prints a newline. print without a newline character doesn't (though it would still cause the buffer to be flushed one or more times if the string passed to it were big enough).
Without a newline, the buffer is flushed during normal program termination when the file descriptor is closed, but that's after the method call to print has successfully completed.
That's what I think is happening, anyway.
...I don't this explanation is entirely correct.
Standard output is only typically line buffered by default when it is a terminal. Otherwise it's usually fully buffered. That's in C. But I don't expect Crystal to be different.
Looking at the stack traces, it looks like puts in Crystal may flush the buffer always. I'm not sure what's going on with print. ...To the documentation!
According to the documentation, print always flushes the buffer.
So it should've flushed it in crystal eval 'print "Hello, world!"' >/dev/full too.
 
11:30 AM
@EliahKagan I mean, it keeps that special behavior in that terminal, even when interacting with subsequent foreground processes that are not whatever shell (if any) stty was run from, such as non-shell child processes.
 
 
5 hours later…
4:58 PM
@EliahKagan that x looks very cosy
 
5:10 PM
@EliahKagan oooh
 
 
4 hours later…
9:06 PM
@Zanna It's no surprise that it supports nesting, since it uses the same syntax as string interpolation in Ruby, which does:
[1] pry(main)> "#{"#{"#{"#{"#{"#{"x"}"}"}"}"}"}"
=> "x"
But I'm accustomed to Python, where nesting is not allowed because the syntax for string interpolation is different from that of ordinary expressions:
>>> f'{"x"}'
'x'
>>> f'{'x'}'
  File "<stdin>", line 1
    f'{'x'}'
        ^
SyntaxError: invalid syntax
>>> f'{"{'x'}"}'
  File "<stdin>", line 1
    f'{"{'x'}"}'
          ^
SyntaxError: invalid syntax
When I say string interpolation in Python has different syntax from expressions in general, I mean things like:
>>> f'{12.345:3.2f}'
'12.35'
>>> f'{"abc":5}de'
'abc  de'
 
9:27 PM
@Zanna If you're not sure how to make the multiplication table program in Crystal, you could write it as a shell script first (using the printf command), then figure out how to get it to work with loops (or whatever you decided to use) in Crystal.
 

« first day (1046 days earlier)      last day (1353 days later) »