lexdrill 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ee9e8bd1de6b7fc437375184394a0ce42d61d9648320e6a31e83bf575cfc885
4
- data.tar.gz: 27836a51638dbd08eb53a1d6f6808d94a0fb27c8e4b93cd831e96c2f5b0abe64
3
+ metadata.gz: 694f430036d22f39f5ee347a6220a8e977e726edb54db9f5c99d3f57bfcb8161
4
+ data.tar.gz: 9deb40864be7ded7ed8eb1aff88e25e20a412acf0a678526ff5d3f84f50ad69b
5
5
  SHA512:
6
- metadata.gz: cb860ea6fb40050205abbbdc2078d1a3e5b4f624629bb1b769a33c7bd1de3e22452d65265017cd0e7597bde5d934b04c568e96ab8f2643678392dfe86a8e2dc6
7
- data.tar.gz: edbe4b9f27ced36534b9f3816840feb9216728288077af785292b12015d765db0c96170a0f8f79dc9182926323b3404517abd237ff51b47747901fb4e93632a7
6
+ metadata.gz: 49b05b7ac7dda95a4fd9c34b9de6fbe29486e8a8e84285d8fbb0fe0a211785a9a7870551c3a80566725d4884dee317117c85781a313251c9094fa927a4ff857c
7
+ data.tar.gz: 201a4d5c23a232a4cbb1ca5b2d294e629a9984e1196133511d62262e3c8ae3c238386278735f91d184db4b7214578304861caa70b641c6f0b77988cc2f4ef00f
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # lexdrill
2
2
 
3
- lexdrill prints a vocabulary word or phrase on demand, tracking how often each one has been shown.
3
+ The `lexdrill` gem installs a `drill` command that prints a vocabulary word or
4
+ phrase on demand, tracking how often each one has been shown.
4
5
 
5
6
  ## Installation
6
7
 
@@ -8,7 +9,7 @@ lexdrill prints a vocabulary word or phrase on demand, tracking how often each o
8
9
  gem install lexdrill
9
10
  ```
10
11
 
11
- ### `lexdrill: command not found` after install?
12
+ ### `drill: command not found` after install?
12
13
 
13
14
  This happens when the gem's executable directory isn't on your `PATH` — common with a
14
15
  plain system Ruby (no rbenv/rvm). Fix it in one step:
@@ -27,3 +28,82 @@ source ~/.zshrc
27
28
 
28
29
  Using an rbenv-managed Ruby? Run `rbenv rehash` instead. Using rvm? You shouldn't hit
29
30
  this — rvm keeps gem executable directories on `PATH` automatically.
31
+
32
+ ## Usage
33
+
34
+ Create a `.drill.txt` file — one word or phrase per line — in your home directory,
35
+ or in a specific project directory to give that project its own list:
36
+
37
+ ```
38
+ apple
39
+ banana
40
+ cherry
41
+ ```
42
+
43
+ Run `drill next` to print the current word and advance to the next one. Each
44
+ line is printed as `current/total:` followed by a tab and the word, in a
45
+ randomly-picked color, e.g.:
46
+
47
+ ```
48
+ 1/3: apple
49
+ 2/3: banana
50
+ 3/3: cherry
51
+ 1/3: apple
52
+ ```
53
+
54
+ ### Shell integration (one-time setup)
55
+
56
+ Add one line to your shell's rc file so the current word prints automatically
57
+ before each prompt. This is a **one-time step** — the line stays in your rc file
58
+ and takes effect in every new shell session from then on; you never need to run it
59
+ again by hand.
60
+
61
+ Add it near the **end** of the file, after anything that sets up your `PATH`
62
+ (rvm/rbenv init, Homebrew, etc.) — otherwise the shell may not know where
63
+ `drill` lives yet when this line runs. Guarding it with `command -v` also
64
+ means it never errors, even on a machine/session where `drill` isn't on
65
+ `PATH` for some reason.
66
+
67
+ **zsh** — add to `~/.zshrc`:
68
+ ```zsh
69
+ if command -v drill >/dev/null 2>&1; then
70
+ eval "$(drill hook zsh)"
71
+ fi
72
+ ```
73
+
74
+ **bash** — add to `~/.bashrc`:
75
+ ```bash
76
+ if command -v drill >/dev/null 2>&1; then
77
+ eval "$(drill hook bash)"
78
+ fi
79
+ ```
80
+
81
+ Then open a new shell (or `source ~/.zshrc` / `source ~/.bashrc`) to pick it up.
82
+
83
+ #### Hook not firing in new terminal windows/tabs (rvm users)?
84
+
85
+ Run `drill inspect` first — if it shows `Toggle: enabled` and a valid words
86
+ file, the tool itself is fine and the problem is that the hook function never
87
+ got registered in that session.
88
+
89
+ A common cause with rvm: rvm's installer sometimes puts its actual
90
+ PATH-loading line (`[[ -s "$HOME/.rvm/scripts/rvm" ]] && source
91
+ "$HOME/.rvm/scripts/rvm"`) in `~/.zlogin` (zsh) or `~/.bash_profile` (bash).
92
+ Those files only run for **login shells** — but many terminal emulators
93
+ (e.g. kitty) open new windows/tabs as **non-login** interactive shells, which
94
+ only source `~/.zshrc`/`~/.bashrc`. So rvm's gemset `bin/` directory (where
95
+ `drill` lives) never makes it onto `PATH` in those sessions, even though
96
+ everything looks correctly configured.
97
+
98
+ **Fix:** move that line into `~/.zshrc` / `~/.bashrc` (before the `drill`
99
+ hook block above, so it runs first) instead of relying on it only being in
100
+ `~/.zlogin` / `~/.bash_profile`. It's safe to leave it in both places.
101
+
102
+ ### Commands
103
+
104
+ | Command | What it does |
105
+ |---|---|
106
+ | `drill next` | Print the current word and advance |
107
+ | `drill start` / `drill stop` | Pause/resume the automatic per-prompt hook (doesn't affect manual `next`) |
108
+ | `drill inspect` | Show the active `.drill.txt`/`.drill.counter` paths, word count, counter value, and toggle state |
109
+ | `drill hook zsh\|bash` | Print the shell integration snippet (used above) |
data/lexdrill.gemspec CHANGED
@@ -23,6 +23,6 @@ Gem::Specification.new do |spec|
23
23
  Dir["lib/**/*.rb"] + Dir["bin/*"] + %w[README.md LICENSE.txt lexdrill.gemspec Gemfile]
24
24
  end
25
25
  spec.bindir = "bin"
26
- spec.executables = ["lexdrill"]
26
+ spec.executables = ["drill"]
27
27
  spec.require_paths = ["lib"]
28
28
  end
data/lib/lexdrill/cli.rb CHANGED
@@ -4,7 +4,11 @@ class Lexdrill::CLI
4
4
  COMMANDS = {
5
5
  print_version: %w[version --version -v],
6
6
  print_help: %w[help --help -h],
7
- run_next: %w[next]
7
+ run_next: %w[next],
8
+ run_hook: %w[hook],
9
+ run_start: %w[start],
10
+ run_stop: %w[stop],
11
+ run_inspect: %w[inspect]
8
12
  }.freeze
9
13
 
10
14
  def self.start(argv = ARGV)
@@ -34,12 +38,16 @@ class Lexdrill::CLI
34
38
 
35
39
  def print_help
36
40
  puts <<~HELP
37
- lexdrill #{Lexdrill::VERSION} — vocabulary drilling in your terminal
41
+ drill #{Lexdrill::VERSION} — vocabulary drilling in your terminal
38
42
 
39
43
  Usage:
40
- lexdrill version Print the gem version
41
- lexdrill help Show this help
42
- lexdrill next Print the current word and advance
44
+ drill version Print the gem version
45
+ drill help Show this help
46
+ drill next Print the current word and advance
47
+ drill hook <zsh|bash> Print the shell integration snippet
48
+ drill start Resume drilling (undoes stop)
49
+ drill stop Pause drilling everywhere until `start`
50
+ drill inspect Show the active config/counter/toggle state
43
51
  HELP
44
52
  0
45
53
  end
@@ -48,17 +56,52 @@ class Lexdrill::CLI
48
56
  word = Lexdrill::WordList.next
49
57
  return print_no_words(Lexdrill::WordList::PATH) unless word
50
58
 
51
- puts word
59
+ puts Lexdrill::Colorizer.paint(Lexdrill::LineFormatter.format(word))
52
60
  0
53
61
  end
54
62
 
55
63
  def print_no_words(path)
56
- warn "lexdrill: no words found in #{path}"
64
+ warn "drill: no words found in #{path}"
57
65
  1
58
66
  end
59
67
 
68
+ def run_hook
69
+ shell = argv[1]
70
+ return print_hook_usage unless shell
71
+
72
+ print_hook_snippet(shell)
73
+ end
74
+
75
+ def print_hook_usage
76
+ warn "usage: drill hook <zsh|bash>"
77
+ 1
78
+ end
79
+
80
+ def print_hook_snippet(shell)
81
+ puts Lexdrill::ShellSnippet.for(shell)
82
+ 0
83
+ rescue ArgumentError => error
84
+ warn "drill: #{error.message}"
85
+ 1
86
+ end
87
+
88
+ def run_start
89
+ Lexdrill::Toggle.start
90
+ 0
91
+ end
92
+
93
+ def run_stop
94
+ Lexdrill::Toggle.stop
95
+ 0
96
+ end
97
+
98
+ def run_inspect
99
+ puts Lexdrill::Inspector.report
100
+ 0
101
+ end
102
+
60
103
  def print_unknown_command(command)
61
- warn "lexdrill: unknown command #{command.inspect}"
104
+ warn "drill: unknown command #{command.inspect}"
62
105
  print_help
63
106
  1
64
107
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Wraps text in a randomly-picked ANSI color code from a fixed palette.
4
+ module Lexdrill::Colorizer
5
+ CODES = [31, 32, 33, 34, 35, 36, 91, 92, 93, 94, 95, 96].freeze
6
+
7
+ def self.paint(text)
8
+ "\e[#{CODES.sample}m#{text}\e[0m"
9
+ end
10
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Builds a human-readable snapshot of lexdrill's current config/state, for
4
+ # `drill inspect` — which files are active, how many words, the counter
5
+ # value, and whether drilling is currently stopped.
6
+ module Lexdrill::Inspector
7
+ def self.report
8
+ <<~REPORT
9
+ drill #{Lexdrill::VERSION}
10
+
11
+ Words file: #{Lexdrill::WordList::PATH} (#{words_summary})
12
+ Counter file: #{Lexdrill::WordList::COUNTER_PATH} (value: #{counter_value})
13
+ Toggle: #{toggle_summary}
14
+ LEXDRILL_PATH: #{ENV.fetch('LEXDRILL_PATH', '(not set)')}
15
+ REPORT
16
+ end
17
+
18
+ def self.words_summary
19
+ return "missing" unless File.exist?(Lexdrill::WordList::PATH)
20
+
21
+ "#{Lexdrill::WordList.words.size} word(s)"
22
+ end
23
+
24
+ def self.counter_value
25
+ Lexdrill::Counter.new(Lexdrill::WordList::COUNTER_PATH).value
26
+ end
27
+
28
+ def self.toggle_summary
29
+ return "enabled" if Lexdrill::Toggle.enabled?
30
+
31
+ "stopped (#{Lexdrill::Toggle::PATH})"
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Formats a shown word as "{line_number}/{total}:\t{word}". The just-advanced
4
+ # counter value equals the 1-based position of the word that was shown.
5
+ module Lexdrill::LineFormatter
6
+ def self.format(word)
7
+ total = Lexdrill::WordList.words.size
8
+ line_number = Lexdrill::Counter.new(Lexdrill::WordList::COUNTER_PATH).value
9
+ "#{line_number}/#{total}:\t#{word}"
10
+ end
11
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Generates the zsh/bash shell integration snippet for `drill hook`.
4
+ module Lexdrill::ShellSnippet
5
+ ZSH = <<~SNIPPET
6
+ drill_precmd() {
7
+ [[ -f "$HOME/.drill.disabled" ]] && return
8
+ command drill next 2>/dev/null
9
+ }
10
+ if [[ -z "${precmd_functions[(r)drill_precmd]}" ]]; then
11
+ precmd_functions+=(drill_precmd)
12
+ fi
13
+ SNIPPET
14
+
15
+ BASH = <<~SNIPPET
16
+ drill_precmd() {
17
+ [ -f "$HOME/.drill.disabled" ] && return
18
+ command drill next 2>/dev/null
19
+ }
20
+ case ";${PROMPT_COMMAND:-};" in
21
+ *";drill_precmd;"*) ;;
22
+ *) PROMPT_COMMAND="drill_precmd;${PROMPT_COMMAND}" ;;
23
+ esac
24
+ SNIPPET
25
+
26
+ def self.for(shell_name)
27
+ case shell_name.to_s
28
+ when "zsh" then ZSH
29
+ when "bash" then BASH
30
+ else
31
+ raise ArgumentError, "unsupported shell #{shell_name.inspect} (expected \"zsh\" or \"bash\")"
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+
5
+ # Global pause/resume switch for the shell hook, independent of which
6
+ # project's .drill.txt is active. Enabled by default; the marker file's
7
+ # presence means stopped.
8
+ module Lexdrill::Toggle
9
+ PATH = File.join(Dir.home, ".drill.disabled")
10
+
11
+ def self.enabled?
12
+ !File.exist?(PATH)
13
+ end
14
+
15
+ def self.start
16
+ FileUtils.rm_f(PATH)
17
+ end
18
+
19
+ def self.stop
20
+ File.write(PATH, "")
21
+ end
22
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lexdrill
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/lexdrill.rb CHANGED
@@ -4,4 +4,9 @@ require_relative "lexdrill/version"
4
4
  require_relative "lexdrill/config"
5
5
  require_relative "lexdrill/counter"
6
6
  require_relative "lexdrill/word_list"
7
+ require_relative "lexdrill/toggle"
8
+ require_relative "lexdrill/shell_snippet"
9
+ require_relative "lexdrill/inspector"
10
+ require_relative "lexdrill/colorizer"
11
+ require_relative "lexdrill/line_formatter"
7
12
  require_relative "lexdrill/cli"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lexdrill
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Siarhei Kisliak
@@ -15,19 +15,24 @@ description: lexdrill prints a vocabulary word or phrase on demand, tracking how
15
15
  email:
16
16
  - kislak7@gmail.com
17
17
  executables:
18
- - lexdrill
18
+ - drill
19
19
  extensions: []
20
20
  extra_rdoc_files: []
21
21
  files:
22
22
  - Gemfile
23
23
  - LICENSE.txt
24
24
  - README.md
25
- - bin/lexdrill
25
+ - bin/drill
26
26
  - lexdrill.gemspec
27
27
  - lib/lexdrill.rb
28
28
  - lib/lexdrill/cli.rb
29
+ - lib/lexdrill/colorizer.rb
29
30
  - lib/lexdrill/config.rb
30
31
  - lib/lexdrill/counter.rb
32
+ - lib/lexdrill/inspector.rb
33
+ - lib/lexdrill/line_formatter.rb
34
+ - lib/lexdrill/shell_snippet.rb
35
+ - lib/lexdrill/toggle.rb
31
36
  - lib/lexdrill/version.rb
32
37
  - lib/lexdrill/word_list.rb
33
38
  homepage: https://github.com/kislak/lexdrill
File without changes