workroom 0.1.0 → 1.1.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: 709e14f9e8836400b840ad9772320ad6ddc9f2fbb163c800a0ba932b5d26ebe1
4
- data.tar.gz: 6334a7e2daa13faaf34e3d7931bfe1082ec752b456f88531b255d429515c99da
3
+ metadata.gz: ba934ec40dd2fd562407526db171825603588166a1cdcbd757115815f2ef463a
4
+ data.tar.gz: f2b210d1f30f5efa1e8d00c9c0f06dc555439fae28e1decd1e40365fd58b84d5
5
5
  SHA512:
6
- metadata.gz: 07ec6e20dfc896dec2a75cd11fe402b31c9dad2619ca323ac5b191ef23aa8cef681c742d41254356e62edef460aa5377c1e37d20c461d1e9f14caf15dec14658
7
- data.tar.gz: 8915fa7afb229916379e8c0343550734b25300f87d6a64d3b495b4509afe1112e976e3138720920c1881dbac02366aee68dee7bed4e8f26d6c27ed95d6d49e40
6
+ metadata.gz: e26cfda013486738f9b16ee329048185be9b4dfc16d391b30ee36427c673b594e21327626c55de188dd619e12eeca11c5087dc2c54a94b592a3db0610acc67fc
7
+ data.tar.gz: '02567952050efaf0862f589097a5808d37c2bb48733cf20c06d57381f92491c7bcc1170b4f36895b461d79849bb4cfcd5cd2f60b2450761c756c3761aad59264'
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Workroom
2
2
 
3
- Create and manage local development workrooms using [JJ](https://martinvonz.github.io/jj/) workspaces or git worktrees.
3
+ Create and manage local development workrooms using [Git](https://git-scm.com/) worktrees or [Jujutsu](https://martinvonz.github.io/jj/) workspaces.
4
4
 
5
- A workroom is an isolated copy of your project created as a sibling directory, allowing you to work on multiple branches or features simultaneously without stashing or switching contexts.
5
+ A workroom is an isolated copy of your project, allowing you to work on multiple branches or features simultaneously without stashing or switching contexts. Workrooms are created under a centralized directory (`~/workrooms` by default, configurable via `workrooms_dir` in `~/.config/workroom/config.json`).
6
6
 
7
7
  ## Installation
8
8
 
@@ -23,17 +23,29 @@ gem install workroom
23
23
  ## Requirements
24
24
 
25
25
  - Ruby >= 3.1
26
- - [JJ (Jujutsu)](https://martinvonz.github.io/jj/) or Git
26
+ - [JJ (Jujutsu)](https://martinvonz.github.io/jj/) or [Git](https://git-scm.com/)
27
27
 
28
28
  ## Usage
29
29
 
30
30
  ### Create a workroom
31
31
 
32
32
  ```bash
33
- workroom create my-feature
33
+ workroom create
34
34
  ```
35
35
 
36
- This creates a new workroom at `../my-feature` relative to your project root. Workroom automatically detects whether you're using JJ or Git and uses the appropriate mechanism (JJ workspace or git worktree).
36
+ A random friendly name (e.g. `swift-meadow`) is auto-generated. Workroom automatically detects whether you're using JJ or Git and uses the appropriate mechanism (JJ workspace or git worktree).
37
+
38
+ Alias: `workroom c`
39
+
40
+ ### List workrooms
41
+
42
+ ```bash
43
+ workroom list
44
+ ```
45
+
46
+ Lists all workrooms for the current project. When run from outside a known project, lists all workrooms grouped by parent project. When run from inside a workroom, shows the parent project path.
47
+
48
+ Aliases: `workroom ls`, `workroom l`
37
49
 
38
50
  ### Delete a workroom
39
51
 
@@ -43,14 +55,25 @@ workroom delete my-feature
43
55
 
44
56
  Removes the workspace/worktree and cleans up the directory. You'll be prompted for confirmation before deletion.
45
57
 
58
+ When run without a name, an interactive multi-select menu is shown, allowing you to pick one or more workrooms to delete:
59
+
60
+ ```bash
61
+ workroom delete
62
+ ```
63
+
64
+ To skip the confirmation prompt (useful for scripting), pass `--confirm` with the workroom name:
65
+
66
+ ```bash
67
+ workroom delete my-feature --confirm my-feature
68
+ ```
69
+
70
+ Alias: `workroom d`
71
+
46
72
  ### Options
47
73
 
48
74
  - `-v`, `--verbose` - Print detailed output
49
75
  - `-p`, `--pretend` - Run through the command without making changes (dry run)
50
-
51
- ### Naming rules
52
-
53
- Workroom names must be alphanumeric (dashes and underscores allowed) and must not start or end with a dash or underscore.
76
+ - `--confirm NAME` - Skip delete confirmation when NAME matches the workroom being deleted
54
77
 
55
78
  ## Setup and teardown scripts
56
79
 
@@ -62,7 +85,13 @@ Place an executable script at `scripts/workroom_setup` in your project. It will
62
85
 
63
86
  ### Teardown script
64
87
 
65
- Place an executable script at `scripts/workroom_teardown` in your project. It will run after a workroom is deleted.
88
+ Place an executable script at `scripts/workroom_teardown` in your project. It will run inside the workroom directory before it is deleted.
89
+
90
+ ### Environment variables
91
+
92
+ The following environment variables are available to setup and teardown scripts:
93
+
94
+ - `WORKROOM_PARENT_DIR` - The absolute path to the parent project directory. Since scripts run inside the workroom directory, this lets you reference files in the original project root.
66
95
 
67
96
  ## Rails integration
68
97
 
data/bin/workroom CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'bundler'
5
- Bundler.require
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '/../lib'))
5
+ require 'workroom'
6
6
 
7
7
  Workroom::Commands.start
@@ -2,6 +2,8 @@
2
2
 
3
3
  require 'open3'
4
4
  require 'thor'
5
+ require 'tty-prompt'
6
+ require 'pathname'
5
7
 
6
8
  module Workroom
7
9
  class Commands < Thor
@@ -19,15 +21,19 @@ module Workroom
19
21
  true
20
22
  end
21
23
 
22
- desc 'create NAME', 'Create a new workroom'
24
+ map 'c' => :create
25
+ map 'd' => :delete
26
+ map %w[ls l] => :list
27
+
28
+ desc 'create|c', 'Create a new workroom'
23
29
  long_desc <<-DESC, wrap: false
24
- Create a new workroom with the given NAME at the same level as your main project directory,
25
- using JJ workspaces if available, otherwise falling back to git worktrees.
30
+ Create a new workroom at the same level as your main project directory, using JJ workspaces
31
+ if available, otherwise falling back to git worktrees. A random friendly name is
32
+ auto-generated.
26
33
  DESC
27
- def create(name)
28
- @name = name
34
+ def create
29
35
  check_not_in_workroom!
30
- validate_name!
36
+ @name = generate_unique_name
31
37
 
32
38
  if !options[:pretend]
33
39
  if workroom_exists?
@@ -36,26 +42,76 @@ module Workroom
36
42
  end
37
43
 
38
44
  if workroom_path.exist?
39
- raise_error DirExistsError, "Workroom directory '#{workroom_path}' already exists!"
45
+ raise_error DirExistsError,
46
+ "Workroom directory '#{display_path(workroom_path)}' already exists!"
40
47
  end
41
48
  end
42
49
 
43
50
  create_workroom
51
+ update_config(:add)
44
52
  run_setup_script
45
53
 
46
54
  say
47
- say "Workroom '#{name}' created successfully at #{workroom_path}.", :green
55
+ say "Workroom '#{name}' created successfully at #{display_path(workroom_path)}.", :green
48
56
 
49
- return if !@setup_result
57
+ if @setup_result
58
+ say 'Setup script output:', :blue
59
+ say @setup_result
60
+ end
50
61
 
51
- say 'Setup script output:', :blue
52
- say @setup_result
62
+ say
53
63
  end
54
64
 
55
- desc 'delete NAME', 'Delete an existing workroom'
56
- def delete(name)
57
- @name = name
65
+ desc 'list|l|ls', 'List all workrooms for the current project'
66
+ def list
67
+ project_path, project = config.find_current_project
68
+
69
+ # Inside a workroom
70
+ if project && Pathname.pwd.to_s != project_path
71
+ say 'You are already in a workroom.', :yellow
72
+ say "Parent project is at #{display_path(project_path)}"
73
+ return
74
+ end
75
+
76
+ # Inside a parent project
77
+ if project
78
+ workrooms = project['workrooms']
79
+ if !workrooms || workrooms.empty?
80
+ say 'No workrooms found for this project.'
81
+ return
82
+ end
83
+
84
+ list_workrooms(workrooms, project['vcs'])
85
+ return
86
+ end
87
+
88
+ # Neither — list all workrooms grouped by parent
89
+ if config.projects_with_workrooms.empty?
90
+ say 'No workrooms found.'
91
+ return
92
+ end
93
+
94
+ config.projects_with_workrooms.each do |path, proj|
95
+ say "#{display_path(path)}:"
96
+ inside path do
97
+ list_workrooms(proj['workrooms'], proj['vcs'])
98
+ end
99
+ say
100
+ end
101
+ end
102
+
103
+ desc 'delete|d [NAME]', 'Delete an existing workroom'
104
+ method_option :confirm, type: :string,
105
+ desc: 'Skip confirmation if value matches the workroom name'
106
+ def delete(name = nil)
58
107
  check_not_in_workroom!
108
+
109
+ if !name
110
+ interactive_delete
111
+ return
112
+ end
113
+
114
+ @name = name
59
115
  validate_name!
60
116
 
61
117
  if !options[:pretend]
@@ -64,30 +120,19 @@ module Workroom
64
120
  raise_error exception, "#{vcs_label} '#{name}' does not exist!"
65
121
  end
66
122
 
67
- if !yes?("Are you sure you want to delete workroom '#{name}'?")
123
+ if options[:confirm]
124
+ if options[:confirm] != name
125
+ raise_error ArgumentError,
126
+ "--confirm value '#{options[:confirm]}' does not match " \
127
+ "workroom name '#{name}'."
128
+ end
129
+ elsif !yes?("Are you sure you want to delete workroom '#{name}'?")
68
130
  say_error "Aborting. Workroom '#{name}' was not deleted.", :yellow
69
131
  return
70
132
  end
71
133
  end
72
134
 
73
- delete_workroom
74
- cleanup_directory if jj?
75
- run_teardown_script
76
-
77
- say
78
- say "Workroom '#{name}' deleted successfully.", :green
79
-
80
- if !jj?
81
- say
82
- say "Note: Git branch '#{name}' was not deleted."
83
- say " Delete manually with `git branch -D #{name}` if needed."
84
- end
85
-
86
- return if !@teardown_result
87
-
88
- say
89
- say 'Teardown script output:', :blue
90
- say @teardown_result
135
+ delete_by_name(name)
91
136
  end
92
137
 
93
138
  private
@@ -95,13 +140,14 @@ module Workroom
95
140
  def run_setup_script
96
141
  return if !setup_script.exist?
97
142
 
143
+ parent_dir = Pathname.pwd.to_s
98
144
  inside workroom_path do
99
- run_user_script :setup, setup_script_to_run.to_s
145
+ run_user_script :setup, setup_script_to_run.to_s, parent_dir
100
146
  end
101
147
  end
102
148
 
103
149
  def setup_script
104
- @setup_script ||= workroom_path.join('scripts', 'workroom_setup')
150
+ @setup_script ||= Pathname.pwd.join('scripts', 'workroom_setup')
105
151
  end
106
152
 
107
153
  def setup_script_to_run
@@ -111,7 +157,10 @@ module Workroom
111
157
  def run_teardown_script
112
158
  return if !teardown_script.exist?
113
159
 
114
- run_user_script :teardown, teardown_script_to_run.to_s
160
+ parent_dir = Pathname.pwd.to_s
161
+ inside workroom_path do
162
+ run_user_script :teardown, teardown_script_to_run.to_s, parent_dir
163
+ end
115
164
  end
116
165
 
117
166
  def teardown_script
@@ -122,7 +171,7 @@ module Workroom
122
171
  teardown_script
123
172
  end
124
173
 
125
- def run_user_script(type, command)
174
+ def run_user_script(type, command, parent_dir)
126
175
  return if behavior != :invoke
127
176
 
128
177
  destination = relative_to_original_destination_root(destination_root, false)
@@ -131,7 +180,7 @@ module Workroom
131
180
 
132
181
  return if options[:pretend]
133
182
 
134
- result, status = Open3.capture2e(command)
183
+ result, status = Open3.capture2e({ 'WORKROOM_PARENT_DIR' => parent_dir }, command)
135
184
 
136
185
  instance_variable_set :"@#{type}_result", result
137
186
 
@@ -147,8 +196,20 @@ module Workroom
147
196
  raise exception_class, message
148
197
  end
149
198
 
199
+ def config
200
+ @config ||= Config.new
201
+ end
202
+
203
+ def workrooms_dir
204
+ @workrooms_dir ||= config.workrooms_dir
205
+ end
206
+
207
+ def vcs_name
208
+ "workroom/#{name}"
209
+ end
210
+
150
211
  def workroom_path
151
- @workroom_path ||= Pathname.pwd.join("../#{name}")
212
+ @workroom_path ||= workrooms_dir.join(name)
152
213
  end
153
214
 
154
215
  def jj?
@@ -163,9 +224,9 @@ module Workroom
163
224
  say_status :repo, 'Detected Git'
164
225
  :git
165
226
  else
166
- say_status :repo, 'No supported VCS detected', :red
227
+ say_status :repo, 'No supported VCS detected in this directory.', :red
167
228
  raise_error UnsupportedVCSError, <<~_
168
- No supported VCS detected. Workroom requires either Jujutsu or Git to manage workspaces.
229
+ No supported VCS detected in this directory. Workroom requires either Git or Jujutsu to manage workspaces.
169
230
  _
170
231
  end
171
232
  end
@@ -179,7 +240,7 @@ module Workroom
179
240
  end
180
241
 
181
242
  def jj_workspace_exists?
182
- jj_workspaces.include?(name)
243
+ jj_workspaces.include?(vcs_name)
183
244
  end
184
245
 
185
246
  def git_worktree_exists?
@@ -230,22 +291,106 @@ module Workroom
230
291
  def check_not_in_workroom!
231
292
  return if !Pathname.pwd.join('.Workroom').exist?
232
293
 
233
- say_status :create, name, :red
234
294
  raise_error InWorkroomError, <<~_
235
295
  Looks like you are already in a workroom. Run this command from the root of your main development directory, not from within an existing workroom.
236
296
  _
237
297
  end
238
298
 
299
+ def interactive_delete
300
+ _, project = config.find_current_project
301
+
302
+ if !project || !project['workrooms'] || project['workrooms'].empty?
303
+ say 'No workrooms found for this project.'
304
+ return
305
+ end
306
+
307
+ workrooms = project['workrooms']
308
+ prompt = TTY::Prompt.new
309
+ selected = prompt.multi_select(
310
+ 'Select workrooms to delete:',
311
+ workrooms.keys
312
+ )
313
+
314
+ if selected.empty?
315
+ say_error 'Aborting. No workrooms were selected.', :yellow
316
+ return
317
+ end
318
+
319
+ names_list = selected.map { |n| "'#{n}'" }.join(', ')
320
+ if !yes?("Are you sure you want to delete #{selected.size} workroom(s): #{names_list}?")
321
+ say_error 'Aborting. No workrooms were deleted.', :yellow
322
+ return
323
+ end
324
+
325
+ selected.each { |n| delete_by_name(n) }
326
+ end
327
+
328
+ def delete_by_name(selected_name)
329
+ @name = selected_name
330
+ @workroom_path = nil
331
+
332
+ run_teardown_script
333
+ delete_workroom
334
+ cleanup_directory if jj?
335
+ update_config(:remove)
336
+
337
+ say "Workroom '#{name}' deleted successfully.", :green
338
+
339
+ if !jj?
340
+ say
341
+ say "Note: Git branch '#{vcs_name}' was not deleted."
342
+ say " Delete manually with `git branch -D #{vcs_name}` if needed."
343
+ end
344
+
345
+ return if !@teardown_result
346
+
347
+ say
348
+ say 'Teardown script output:', :blue
349
+ say @teardown_result
350
+ say
351
+ end
352
+
353
+ def generate_unique_name
354
+ generator = NameGenerator.new
355
+ last_name = nil
356
+
357
+ 5.times do
358
+ last_name = generator.generate
359
+ if !workroom_exists_for?(last_name) && !workroom_path_for(last_name).exist?
360
+ return last_name
361
+ end
362
+ end
363
+
364
+ loop do
365
+ candidate = "#{last_name}-#{rand(10..99)}"
366
+ if !workroom_exists_for?(candidate) && !workroom_path_for(candidate).exist?
367
+ return candidate
368
+ end
369
+ end
370
+ end
371
+
372
+ def workroom_exists_for?(candidate)
373
+ @name = candidate
374
+ @workroom_path = nil
375
+ workroom_exists?
376
+ end
377
+
378
+ def workroom_path_for(candidate)
379
+ workrooms_dir.join(candidate)
380
+ end
381
+
239
382
  def create_workroom
383
+ FileUtils.mkdir_p(workrooms_dir) if !workrooms_dir.exist?
384
+
240
385
  if testing?
241
386
  FileUtils.copy('./', workroom_path)
242
387
  return
243
388
  end
244
389
 
245
390
  if jj?
246
- run "jj workspace add #{workroom_path}"
391
+ run "jj workspace add #{workroom_path} --name #{vcs_name}"
247
392
  else
248
- run "git worktree add -b #{name} #{workroom_path}"
393
+ run "git worktree add -b #{vcs_name} #{workroom_path}"
249
394
  end
250
395
  end
251
396
 
@@ -256,7 +401,7 @@ module Workroom
256
401
  end
257
402
 
258
403
  if jj?
259
- run "jj workspace forget #{name}"
404
+ run "jj workspace forget #{vcs_name}"
260
405
  else
261
406
  run "git worktree remove #{workroom_path} --force"
262
407
  end
@@ -268,6 +413,16 @@ module Workroom
268
413
  remove_dir(workroom_path, verbose:)
269
414
  end
270
415
 
416
+ def update_config(action)
417
+ return if options[:pretend]
418
+
419
+ if action == :add
420
+ config.add_workroom Pathname.pwd.to_s, name, workroom_path.to_s, vcs
421
+ else
422
+ config.remove_workroom Pathname.pwd.to_s, name
423
+ end
424
+ end
425
+
271
426
  def run(command, config = {})
272
427
  if !config[:force] && testing?
273
428
  raise TestError, "Command execution blocked during testing: `#{command}`"
@@ -290,5 +445,33 @@ module Workroom
290
445
  def testing?
291
446
  ENV['WORKROOM_TEST'] == '1'
292
447
  end
448
+
449
+ def display_path(path)
450
+ path.to_s.sub(/\A#{Regexp.escape(Dir.home)}/, '~')
451
+ end
452
+
453
+ def list_workrooms(workrooms, vcs)
454
+ rows = workrooms.map do |name, info|
455
+ warnings = workroom_warnings(name, info, vcs)
456
+ row = [shell.set_color(name, :bold), shell.set_color(display_path(info['path']), :black)]
457
+ row << shell.set_color("[#{warnings.join(', ')}]", :yellow) if warnings.any?
458
+ row
459
+ end
460
+ print_table rows, indent: 2
461
+ end
462
+
463
+ def workroom_warnings(name, info, stored_vcs)
464
+ warnings = []
465
+ warnings << 'directory not found' if !Dir.exist?(info['path'])
466
+ if !testing?
467
+ vcs_missing = if stored_vcs == 'jj'
468
+ !jj_workspaces.include?("workroom/#{name}")
469
+ elsif stored_vcs == 'git'
470
+ git_worktrees.none? { |path| File.basename(path) == name }
471
+ end
472
+ warnings << "#{stored_vcs} workspace not found" if vcs_missing
473
+ end
474
+ warnings
475
+ end
293
476
  end
294
477
  end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'fileutils'
5
+ module Workroom
6
+ class Config
7
+ CONFIG_DIR = File.expand_path('~/.config/workroom')
8
+ DEFAULT_WORKROOMS_DIR = '~/workrooms'
9
+
10
+ def config_path
11
+ @config_path ||= File.join(CONFIG_DIR, 'config.json')
12
+ end
13
+
14
+ def read
15
+ return {} if !File.exist?(config_path)
16
+
17
+ JSON.parse(File.read(config_path))
18
+ end
19
+
20
+ def write(data)
21
+ dir = File.dirname(config_path)
22
+ FileUtils.mkdir_p(dir)
23
+ File.write(config_path, JSON.pretty_generate(data))
24
+ end
25
+
26
+ def add_workroom(parent_path, name, workroom_path, vcs)
27
+ update do |data|
28
+ data[parent_path] ||= { 'vcs' => vcs.to_s, 'workrooms' => {} }
29
+ data[parent_path]['vcs'] = vcs.to_s
30
+ data[parent_path]['workrooms'][name] = { 'path' => workroom_path }
31
+ end
32
+ end
33
+
34
+ def remove_workroom(parent_path, name)
35
+ update do |data|
36
+ return if !data[parent_path]
37
+
38
+ data[parent_path]['workrooms'].delete(name)
39
+ data.delete(parent_path) if data[parent_path]['workrooms'].empty?
40
+ end
41
+ end
42
+
43
+ # Find the project for the current directory. If pwd is a project in the config, return it
44
+ # directly. Otherwise, check if pwd is a workroom path under any project.
45
+ def find_current_project
46
+ data = read
47
+ pwd = Pathname.pwd.to_s
48
+ return [pwd, data[pwd]] if data.key?(pwd)
49
+
50
+ data.each do |project_path, project|
51
+ workrooms = project['workrooms'] || {}
52
+ return [project_path, project] if workrooms.any? { |_, info| info['path'] == pwd }
53
+ end
54
+
55
+ [pwd, nil]
56
+ end
57
+
58
+ def projects_with_workrooms
59
+ @projects_with_workrooms ||= read.select { |_, p| p['workrooms']&.any? }
60
+ end
61
+
62
+ def workrooms_dir
63
+ Pathname.new(File.expand_path(read['workrooms_dir'] || DEFAULT_WORKROOMS_DIR))
64
+ end
65
+
66
+ def workrooms_dir=(path)
67
+ update { |data| data['workrooms_dir'] = path }
68
+ end
69
+
70
+ private
71
+
72
+ def update
73
+ data = read
74
+ yield data
75
+ write data
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Workroom
4
+ class NameGenerator
5
+ ADJECTIVES = %w[
6
+ agile amber apt azure bold brave bright brisk calm cedar clear cold cool
7
+ coral crisp cyan damp dark dawn deep deft dry dusk dusty easy even fair
8
+ fast firm flat fond free fresh full glad gold good gray green hale happy
9
+ hazy high idle jade keen kind lark last lean left light lime long lost
10
+ loud lush mild mint misty mossy neat nice noble north novel oak odd opal
11
+ open pale peak pine pink plum proud pure quick quiet rapid rare red rich
12
+ ripe rosy ruby safe sage salt sharp shy silk slim slow smart snowy soft
13
+ solid south stark steel still stout sunny sure swift tall tame teal thin
14
+ tidy trim true vivid warm west wide wild wise young
15
+ ].freeze
16
+
17
+ NOUNS = %w[
18
+ acre arch aspen badge bank bark basin bay beach bear birch blade blaze
19
+ bloom bolt bone bow brace brass breeze brick bridge brook brush canopy
20
+ cape cave cedar chain chime cliff cloud clover colt coop coral core
21
+ cove crane creek crest crow curve dale dawn deer delta dew dock dove
22
+ drake drift dune dusk eagle edge elm ember fawn feather fern field finch
23
+ fjord flame flask flint float flora flute fog font forge fox frost gate
24
+ glade glen globe gorge grain grove gulf gust hare haven hawk hazel
25
+ heath hedge heron hill hollow horn inlet isle ivy jade jewel knoll
26
+ lake larch lark latch laurel leaf ledge light lilac lily linen lodge
27
+ loft lynx maple marsh meadow mesa mint mirror mist moon moss mound
28
+ nest north oak opal orbit orion otter palm pass path peak pearl
29
+ pebble perch petal pine pixel plume pond pool porch prism quail
30
+ quarry quartz rail rain raven reef ridge river robin rock root rose
31
+ ruby sage sand scope seal seed shade shell shore silk sky slate
32
+ slope smoke snow south spark spire spoke spring spruce star stem
33
+ stone stork storm strand surf swift tern thyme tide timber tower
34
+ trail tree vale vault vine vista wand ward wave west wheat willow
35
+ wind wing wolf wren yard
36
+ ].freeze
37
+
38
+ def generate
39
+ "#{ADJECTIVES.sample}-#{NOUNS.sample}"
40
+ end
41
+ end
42
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Workroom
4
- VERSION = '0.1.0'
4
+ VERSION = '1.1.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: workroom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Moss
@@ -23,6 +23,20 @@ dependencies:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
25
  version: '1.5'
26
+ - !ruby/object:Gem::Dependency
27
+ name: tty-prompt
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '0.23'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.23'
26
40
  - !ruby/object:Gem::Dependency
27
41
  name: zeitwerk
28
42
  requirement: !ruby/object:Gem::Requirement
@@ -51,7 +65,9 @@ files:
51
65
  - bin/workroom
52
66
  - lib/workroom.rb
53
67
  - lib/workroom/commands.rb
68
+ - lib/workroom/config.rb
54
69
  - lib/workroom/engine.rb
70
+ - lib/workroom/name_generator.rb
55
71
  - lib/workroom/version.rb
56
72
  homepage: https://github.com/joelmoss/workroom
57
73
  licenses: