From b9c6b52198a75667792dcf07280e09fe696baf28 Mon Sep 17 00:00:00 2001 From: Agatha Rose Date: Sun, 5 Jul 2020 12:06:59 +0300 Subject: [PATCH] Initial commit --- .editorconfig | 9 +++++++++ .gitignore | 5 +++++ layouts/en_us.txt | 5 +++++ shard.yml | 13 +++++++++++++ src/keyboard.cr | 42 ++++++++++++++++++++++++++++++++++++++++ src/keysmash-analyzer.cr | 22 +++++++++++++++++++++ 6 files changed, 96 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 layouts/en_us.txt create mode 100644 shard.yml create mode 100644 src/keyboard.cr create mode 100644 src/keysmash-analyzer.cr diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..163eb75 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*.cr] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0bb75ea --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/docs/ +/lib/ +/bin/ +/.shards/ +*.dwarf diff --git a/layouts/en_us.txt b/layouts/en_us.txt new file mode 100644 index 0000000..022e2a4 --- /dev/null +++ b/layouts/en_us.txt @@ -0,0 +1,5 @@ +[`~] [1!][2@][3#][4$][5%][6^][7&][8*][9(][0)][-_][=+] |<-| +|tab| [q][w][e][r][t][y][u][i][o][p][\[{][\]}][\\|] +|caps| [a][s][d][f][g][h][j][k][l][;:]['"] |enter| +|shift| [z][x][c][v][b][n][m][,<][.>][/?] |shift| +|ctrl| |sys| |alt| [ ] |alt| |fn| |ctrl| diff --git a/shard.yml b/shard.yml new file mode 100644 index 0000000..50a025c --- /dev/null +++ b/shard.yml @@ -0,0 +1,13 @@ +name: keysmash-analyzer +version: 0.1.0 + +authors: + - Agatha Rose + +targets: + keysmash-analyzer: + main: src/keysmash-analyzer.cr + +crystal: 0.35.1 + +license: MIT diff --git a/src/keyboard.cr b/src/keyboard.cr new file mode 100644 index 0000000..f669230 --- /dev/null +++ b/src/keyboard.cr @@ -0,0 +1,42 @@ +class Keyboard + property layout + property raw_layout : String + # path to layout file + setter name : String + + def initialize(@name) + # character and frequency + @layout = {} of Char => Int32 + @raw_layout = File.read(name) + i = 0 + c = @raw_layout.chars + # iterates over characters in layout + while i < c.size + # outputs a hashmap of characters inside [] in the layout and sets each to 0 uses + if c[i] == '[' + until c[i+1] == ']' + # character escape + if c[i+1] == '\\' + i += 1 + end + @layout[c[i += 1]] = 0 + end + end + i += 1 + end + end + + def to_s(io : IO) + # remove character escapes + formatted = @raw_layout.gsub(/\\(\S)/, &.[1]) + # defines heatmap colors + colors = %i(default light_yellow yellow light_red red) + # add a keypress heatmap + max = @layout.to_a.sort_by { |k, v| v }.reverse.to_h.values[0] + formatted = formatted.gsub(/\[(.{1,2})\]/) {|m| + # calculate proportion of key usage to colors + m.colorize.fore(:white).back(colors[((@layout[m.chars[1]] * (colors.size - 1)) / max).to_i]) + } + io << formatted + end +end diff --git a/src/keysmash-analyzer.cr b/src/keysmash-analyzer.cr new file mode 100644 index 0000000..9b845eb --- /dev/null +++ b/src/keysmash-analyzer.cr @@ -0,0 +1,22 @@ +require "./keyboard.cr" +require "colorize" + +module KeysmashAnalyzer + VERSION = "0.1.0" + # uses ANSI escape codes to suggest default layout + print "Please enter path to a layout: \x1b[s#{"layouts/en_us.txt".colorize(:dark_gray)}\x1b[u" + input = gets + # fall back to en_us.txt if no input is provided + input = "layouts/en_us.txt" if input.nil? || input.blank? + keyboard = Keyboard.new input + print "Please keysmash into your terminal: " + keysmash = gets + exit if keysmash.nil? + keysmash = keysmash.downcase + # set usage frequency for each char + keysmash.chars.each do |c| + keyboard.layout[c] += 1 + end + # print the heatmap + puts keyboard +end