Last active
June 21, 2017 09:12
-
-
Save JoshCheek/ed876305b320d847e6d0 to your computer and use it in GitHub Desktop.
A bunch of command-line progrmas for a blog
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'io/console' | |
height, width = $stdout.winsize | |
clear_screen = "\e[1;1H\e[2J" | |
bg_colour = "\e[40m" | |
tree_colour = "\e[42m" | |
base_height = 3 | |
# Go into raw mode so users can enter 1 character at a time | |
$stdin.raw! | |
at_exit { $stdin.cooked! } | |
# hide the cursor until program exig | |
print "\e[?25l" | |
at_exit { print "\e[?25h" } | |
print bg_colour, clear_screen | |
print height.times.map { |y| "\e[#{y+1};#{width/2}H\e[43m \e[48m" }.join | |
tree_height = height - 5 | |
[0.65, 0.4, 0.33].each_with_index do |girth, i| | |
segment_height = (tree_height*girth).to_i | |
ystart = height - segment_height - base_height - (height*i*girth).to_i | |
segment_height.times do |offset| | |
print "\e[#{ystart+offset};#{width/2-offset}H#{tree_colour}#{' '*2*offset}#{bg_colour}" | |
end | |
end | |
$stdin.getc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'io/console' | |
def parse(ansi) | |
ansi.lines.map { |line| line.chomp.chars } | |
end | |
santa = parse <<-COLOURS | |
000070111000000000000000303000 | |
000000011100000000000000030300 | |
000000111110000000000000300000 | |
011110077300000000000000337001 | |
111111117700666666000003333330 | |
011111111701000000660003330000 | |
004444444444400033336633300000 | |
000444444444000003336633300000 | |
000030000300030000300030000000 | |
033333333333300033003300000000 | |
COLOURS | |
gift = parse <<-GIFT | |
1221 | |
2222 | |
1221 | |
GIFT | |
grass = parse <<-GROUND | |
0000000 | |
0000000 | |
2222222 | |
2222222 | |
2222222 | |
GROUND | |
house = parse <<-GIFT | |
3000000 | |
4444444 | |
4343434 | |
4344444 | |
2222222 | |
GIFT | |
print "\e[?25l" | |
at_exit { print "\e[?25h" } | |
$stdin.raw! | |
at_exit { $stdin.cooked! } | |
print "\e[40m\e[1;1H\e[2J" | |
height, width = $stdout.winsize | |
ground = [false]*width | |
100.times { ground += [false]*rand(20) + [true] } | |
ground += [false]*width | |
time = delivered = missed = 0 | |
x = y = newx = newy = 3 | |
gifts = [] | |
ground_height = height - 5 | |
while missed < 20 | |
to_print = "\e[1;1H\e[33;1m CHUCK IT DOWN THE CHIMNEY, SANTA!!\e[22;39m" | |
gifts.each do |y, x| | |
gift.each.with_index { |row, i| to_print << "\e[#{y+i};#{x}H\e[40m#{' '*row.length}\e[49m" } | |
end | |
to_print << "\e[#{y};#{x}H#{santa.map.with_index { |line, i| "\e[#{y+i};#{x}H" << line.map { |char| "\e[40m " }.join }.join}" | |
x = newx | |
y = newy | |
gifts.select! do |gift| | |
gift[0] += 1 | |
if ground_height <= gift[0] | |
house_indexes = ground.map.with_index.select { |has_house, i| has_house }.map { |_, i| i } | |
if house_indexes.any? { |i| i == gift[1] || i-1 == gift[1] } | |
delivered += 1 | |
else | |
missed += 1 | |
end | |
false | |
else | |
gift[0] < height | |
end | |
end | |
ground.shift | |
to_print << "\e[#{ground_height};1H" | |
ground.map { |b| b ? house : grass }.transpose.map.with_index { |row, i| | |
to_print << row.flatten.take(width-1).map { |n| "\e[4#{n}m " }.join << "\e[49m\r\n" | |
} | |
to_print << "\e[#{y};#{x}H#{santa.map.with_index { |line, i| "\e[#{y+i};#{x}H" << line.map { |char| "\e[4#{char}m " }.join }.join}" | |
gifts.each { |y, x| | |
gift.each.with_index { |row, i| | |
to_print << "\e[#{y+i};#{x}H" << row.map { |n| "\e[4#{n}m " }.join << "\e[49m" | |
} | |
} | |
to_print << "\e[1;#{width-25}H\e[32mdelivered: #{delivered} \e[31mmissed: #{missed}\e[39m" | |
print to_print | |
begin | |
case $stdin.read_nonblock(100).to_s[-1] | |
when "q", "\x03" then break | |
when "h" then newx = x - 2 | |
when "j" then newy = y + 1 | |
when "k" then newy = y - 1 | |
when "l" then newx = x + 2 | |
when " " then gifts << [y, x] | |
end | |
rescue IO::EAGAINWaitReadable | |
end | |
sleep 0.02 | |
end | |
print "\e[#{height};#{width}H" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Go into raw mode so users can enter 1 character at a time | |
require 'io/console' | |
$stdin.raw! | |
at_exit { $stdin.cooked! } | |
# Clear the screen | |
print "\e[1;1H\e[2J" | |
# Split the screen into cartesian quadrants (ie 0,0 moves to the middle of the screen) | |
height, width = $stdout.winsize | |
width.times do |x| | |
# It looks fancy, but it's just the equation for a circle, modified to account for changing radius and centered in the middle of the screen | |
y = Math.sqrt(height**2-(2*x*height/width-height)**2).to_i/2 | |
# Prompt user to enter a colour, quit if they press control-c | |
print "\e[#{height};1HEnter one of: " + (0..7).map { |n| "\e[4#{n};9#{n==7?0:7}m #{n} \e[39;49m" }.join | |
colour = $stdin.getc until ["\x03", "0", "1", "2", "3", "4", "5", "6", "7"].include? colour | |
break if colour == "\x03" | |
# Print a vertical line of colour | |
print (height/2-y..height/2+y).map { |y| "\e[#{y+1};#{x+1}H\e[4#{colour}m \e[49m" }.join | |
end | |
print "\e[#{height+1};1H\r\n" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'io/console' | |
# Read a character at a time, reset at exit | |
$stdin.raw! | |
at_exit { $stdin.cooked! } | |
# Hide the cursor until exit | |
print "\e[?25l" | |
at_exit { print "\e[?25h" } | |
# Position on screen and in the text | |
height, width = $stdout.winsize | |
buffer = [] | |
buffer = File.read(ARGV[0]).chars if ARGV[0] | |
buffer_index = 0 # where we are in the input | |
inputs = [] | |
# Since we haven't talked about how to do arrow keys we'll make an emacs-like editor | |
loop do | |
# Clear the screen, print the display | |
print "\e[1;1H" + # move to topleft | |
"\e[2J" + # clear to botright | |
buffer.join[0, width*height] + # print the text we're editing | |
"\e[#{1+(buffer_index/width)};#{1+(buffer_index%width)}H" + # move to cursor position | |
"\e[46m" + # set bg to cursor color | |
(buffer[buffer_index]||' ') + # print char cursor is over with bg set | |
"\e[49m" # unset bg colour | |
# get and interpret the input based on which mode we're in | |
input = $stdin.getc | |
inputs << input | |
case inputs.last | |
when "\x03" then break # control-c | |
when "\x02" then buffer_index -= 1 # control-b | |
when "\x0E" then buffer_index += width # control-n | |
when "\x10" then buffer_index -= width # control-p | |
when "\x06" then buffer_index += 1 # control-f | |
when "\x08", "\x7F" # control-h, delete | |
unless buffer_index.zero? | |
buffer.delete_at buffer_index-1 | |
buffer_index -= 1 | |
end | |
else buffer << input | |
end | |
buffer_index = 0 if buffer_index < 0 | |
buffer_index = buffer.length if buffer.length < buffer_index | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# It doesn't deal with newlines well :) | |
require 'io/console' | |
# Read a character at a time, reset at exit | |
$stdin.raw! | |
at_exit { $stdin.cooked! } | |
# Hide the cursor until exit | |
print "\e[?25l" | |
at_exit { print "\e[?25h" } | |
# Position on screen and in the text | |
height, width = $stdout.winsize | |
buffer = [] | |
buffer = File.read(ARGV[0]).chars if ARGV[0] | |
buffer_index = 0 # where we are in the input | |
# Since we haven't talked about how to do arrow keys | |
# we'll make a vim-like editor, which uses hjkl in the navigation mode (called "normal" mode in vim) | |
mode = :navigation | |
cursor_colour = 6 | |
loop do | |
# Clear the screen, print the display | |
print "\e[1;1H" + # move to topleft | |
"\e[2J" + # clear to botright | |
buffer.join[0, width*height] + # print the text we're editing | |
"\e[#{1+(buffer_index/width)};#{1+(buffer_index%width)}H" + # move to cursor position | |
"\e[4#{cursor_colour}m" + # set bg to cursor color | |
(buffer[buffer_index]||' ') + # print char cursor is over with bg set | |
"\e[49m" # unset bg colour | |
# get and interpret the input based on which mode we're in | |
input = $stdin.getc | |
if mode == :navigation | |
case input | |
when "q", "\e", "\x03", "\x04" then break # escape, control-c, control-d end the program | |
when "h" then buffer_index -= 1 | |
when "j" then buffer_index += width | |
when "k" then buffer_index -= width | |
when "l" then buffer_index += 1 | |
when "i" then mode = :insert | |
when /\d/ then cursor_colour = input.to_i | |
when "x" then buffer.delete_at buffer_index | |
when "w" then File.write(ARGV[0]||"edited", buffer.join) | |
end | |
else | |
case input | |
when "\e", "\x03", "\x04" | |
mode = :navigation | |
when "\b", "\x7F" # these both delete left on mine | |
buffer.delete_at buffer_index-1 unless buffer_index.zero? | |
buffer_index -= 1 | |
else | |
buffer.insert buffer_index, input | |
buffer_index += 1 | |
end | |
end | |
buffer_index = 0 if buffer_index < 0 | |
buffer_index = buffer.length if buffer.length < buffer_index | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'io/console' | |
height, width = $stdout.winsize | |
# No cursor, input 1 char at a time | |
print "\e[?25l"; at_exit { print "\e[?25h" } | |
$stdin.raw!; at_exit { $stdin.cooked! } | |
# Load or create the new canvas | |
if ARGV[0] | |
canvas = File.read(ARGV[0]).lines.map { |line| line.chomp.chars.map(&:to_i) } | |
else | |
canvas = Array.new(height-1) { Array.new width-1, 0 } | |
end | |
# To save it once done (doing it this way so we have access to the canvas local var) | |
define_method :save do | |
filename = ARGV[0]||'image' | |
File.write filename, canvas.map(&:join).join("\n") | |
print "\r\nSaved in #{filename.inspect}" | |
end | |
# Promt whether to save, upon exit | |
at_exit do | |
print "\e[1;1HSAVE? " | |
save if $stdin.getc == 'y' | |
end | |
# Edit the canvas | |
x = y = 0 | |
loop do | |
# Draw each square the colour specified | |
image = canvas.map { |ns| ns.map { |n| "\e[4#{n}m " }.join }.join("\e[0m\r\n") | |
print "\e[2;1H#{image}\e[#{y+2};#{x+1}H\e[4#{canvas[y][x]}m#{canvas[y][x]}" | |
# Depending on what they press, we'll either quit, save, move, or colour the canvas | |
char = $stdin.getc | |
case char | |
when "\x03", "q" then break | |
when 's' then save | |
when 'h' then x -= 1 | |
when 'j' then y += 1 | |
when 'k' then y -= 1 | |
when 'l' then x += 1 | |
when /\d/ then canvas[y][x] = char.to_i | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'io/console' | |
print "\e[?25l" | |
at_exit { print "\e[?25h" } | |
height, width = $stdout.winsize | |
width.times { |x| puts "\e[1;#{x}H.\e[1;1H#{(100.0*x/(width-1)).to_i}%"; sleep 0.01 } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment