advent 0.1.4 → 0.1.6

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: 360b1871cc09fd664dd8562fd1a29afd9b2e8bbc7a83d9d711c7933a6c62b5ec
4
- data.tar.gz: 2f9cde07fa43650354a3f11c7cb869efa7c969d4254083ca807bd7a855fcf9d0
3
+ metadata.gz: a49571ac28572d7a91bcc6a26ecb7253b4f10690dfe2c529a86eca8d310b059b
4
+ data.tar.gz: 470af342600d4fac184e63837dd0f0cdfbd27d34268d34d4a191ef65ce59b960
5
5
  SHA512:
6
- metadata.gz: e27b9323e1ad7a07484fe9302dfd49b430bd4fc5433ef0e412e1af14f734bdd1c0a8c719803e108e4b7b3aec144ec942119bc6a07bc93381f4aae9ef634324b1
7
- data.tar.gz: b8e99258c57406a1cf945e868a1642d8ed8636c983fd960fd3f889bc6760c170bb346e3cdb0cc82e547f880dbd8c6f71898e941defdfd41b97a73974bc4cdec0
6
+ metadata.gz: e94342f2d83c40b0bd360478d7535583da1076517b218c045b44ead0d455e389c174e58c92321da978f63cecbd41abfff0904927552b1acaeb08853b74874a34
7
+ data.tar.gz: 5d2af6a890fc835148f7e1bc054ef49a3e69e641d7a93528ae184b8b39d48a8c69ce4cdf166c29750525750167278c8c84350d8c2d766df77c8d2a2b30f4e502
data/README.md CHANGED
@@ -16,15 +16,26 @@ If bundler is not being used to manage dependencies, install the gem by executin
16
16
 
17
17
  ## Usage
18
18
 
19
+ Initialise a new project somewhere:
20
+
21
+ ```bash
22
+ mkdir advent_of_code && cd advent_of_code
23
+
24
+ # create a blank advent.yml config file
25
+ advent init
26
+ ```
27
+
28
+ Configuration values and format are explained in the [Config](#config) section.
29
+
19
30
  Advent expects you to have a working directory resembling something like:
20
31
 
21
32
  $ tree
22
33
  .
23
34
  ├── 2015
24
- └── 2016
35
+ ├── 2016
36
+ └── advent.yml
25
37
 
26
- Some commands can be run from within a directory for a specific year, but it's
27
- better to run from the parent directory where possible.
38
+ You can run commands from anywhere under this directory.
28
39
 
29
40
  The typical flow for tackling a daily challenge would be:
30
41
 
@@ -40,6 +51,32 @@ A list of commands and help is available using `advent`:
40
51
 
41
52
  $ advent help
42
53
 
54
+ ## Config
55
+
56
+ The config file should be at the root of your working directory called
57
+ `advent.yml`. The default values if you don't provide an override are:
58
+
59
+ ```yaml
60
+ download_when_generating: true
61
+ remember_session: true
62
+ ```
63
+
64
+ ### Config explained
65
+
66
+ <dl>
67
+ <dt>download_when_generating</dt>
68
+ <dd>
69
+ When you run `advent generate` it will automatically download the input file to
70
+ go with it
71
+ </dd>
72
+
73
+ <dt>remember_session</dt>
74
+ <dd>
75
+ Save your session cookie in `.advent_session` when prompted so you don't need to
76
+ find it again
77
+ </dd>
78
+ </dl>
79
+
43
80
  ## Development
44
81
 
45
82
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Advent::CLI::Downloader
4
+ def initialize(command, year, day)
5
+ @command = command
6
+ @year = year
7
+ @day = day
8
+ end
9
+
10
+ def download
11
+ ask_for_session_cookie_if_needed
12
+ input = Advent::Input.new(Advent.root.join(@year), day: @day.to_i)
13
+
14
+ if input.download(Advent.session.value, @command.options.http_module)
15
+ @command.say "Input downloaded to #{input.file_path}.", :green
16
+ @command.say "\nUsing #load_input in your daily solution will load the input file for you."
17
+ else
18
+ @command.say_error "Something went wrong, maybe an old session cookie?", :red
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def ask_for_session_cookie_if_needed
25
+ return if Advent.session.exist?
26
+
27
+ session = @command.ask "What is your Advent of Code session cookie value?", echo: false
28
+ Advent.session.value = session
29
+
30
+ @command.say "\n\nThanks. Psst, we're going to save this for next time. It's in .advent_session if you need to update or delete it.\n\n"
31
+ end
32
+ end
@@ -18,7 +18,7 @@ class Advent::CLI::Solver
18
18
  load @path, Solutions
19
19
  solution = Solutions.const_get(solution_class_name).new
20
20
  else
21
- require @path
21
+ require @path.expand_path
22
22
  solution = Object.const_get(solution_class_name).new
23
23
  end
24
24
 
@@ -37,15 +37,11 @@ class Advent::CLI::Solver
37
37
 
38
38
  private
39
39
 
40
- def day
41
- @_day ||= @path.basename.to_s.match(/day([0-9]+)\.rb/)[1]
42
- end
43
-
44
- def solution_file_name
45
- "day#{day}.rb"
46
- end
47
-
48
40
  def solution_class_name
49
41
  "Day#{day}"
50
42
  end
43
+
44
+ def day
45
+ @_day ||= @path.basename.to_s.match(/day([0-9]+)\.rb/)[1]
46
+ end
51
47
  end
data/lib/advent/cli.rb CHANGED
@@ -8,15 +8,19 @@ require "thor"
8
8
  module Advent
9
9
  class CLI < Thor
10
10
  include Thor::Actions
11
+ EXCLUDED_ROOT_COMMANDS = %w[help init version]
11
12
 
12
- class_option :root_path, default: Dir.pwd, hide: true, check_default_type: false
13
13
  class_option :http_module, default: Net::HTTP, check_default_type: false
14
14
 
15
15
  def initialize(*args)
16
16
  super
17
17
 
18
- self.destination_root = root_path
19
18
  source_paths << File.expand_path("templates", __dir__)
19
+
20
+ # Don't try to load Advent.root if we're a command that doesn't need it
21
+ unless EXCLUDED_ROOT_COMMANDS.include? args.last[:current_command]&.name
22
+ self.destination_root = Advent.root
23
+ end
20
24
  end
21
25
 
22
26
  # @return [Boolean] defines whether an exit status is set if a command fails
@@ -24,44 +28,12 @@ module Advent
24
28
  true
25
29
  end
26
30
 
27
- no_commands do
28
- # @return [Boolean] whether the current root_path option is in a
29
- # directory that looks like a year (eg. 2015)
30
- def in_year_directory?
31
- dir = root_path.basename.to_s
32
- dir =~ /^20[0-9]{2}/
33
- end
34
- end
35
-
36
31
  desc "download YEAR DAY", "Download the input for YEAR and DAY"
37
- def download(year_or_day, day = nil)
38
- year, day = determine_year_and_day(year_or_day, day)
39
-
40
- if (error_message = validate(year, day))
41
- say_error error_message, :red
42
- return
43
- end
32
+ def download(year, day)
33
+ require "advent/cli/downloader"
44
34
 
45
- subpath = if in_year_directory?
46
- ""
47
- else
48
- "#{year}/"
49
- end
50
-
51
- unless Advent.session.exist?
52
- session = ask "What is your Advent of Code session cookie value?", echo: false
53
- Advent.session.value = session
54
-
55
- say "\n\nThanks. Psst, we're going to save this for next time. It's in .advent_session if you need to update or delete it.\n\n"
56
- end
57
-
58
- input = Advent::Input.new(root_path.join(subpath), day: day.to_i)
59
-
60
- if input.download(Advent.session.value, options.http_module)
61
- say "Input downloaded to #{input.file_path}.", :green
62
- say "\nUsing #load_input in your daily solution will load the input file for you."
63
- else
64
- say_error "Something went wrong, maybe an old session cookie?", :red
35
+ Dir.chdir Advent.root do
36
+ Downloader.new(self, year, day).download
65
37
  end
66
38
  end
67
39
 
@@ -69,29 +41,37 @@ module Advent
69
41
  # Generates a new solution file. If within a year directory, only the day
70
42
  # is used, otherwise both the year and day will be required to generate the
71
43
  # output.
72
- def generate(year_or_day, day = nil)
73
- year, day = determine_year_and_day(year_or_day, day)
44
+ def generate(year, day)
45
+ year = parse_number year
46
+ day = parse_number day
74
47
 
75
- if (error_message = validate(year, day))
76
- say_error error_message, :red
48
+ if (message = validate(year, day))
49
+ say_error message, :red
77
50
  return
78
51
  end
79
52
 
80
- subpath = if in_year_directory?
53
+ template "solution.rb.tt", "#{year}/day#{day}.rb", context: binding
54
+ template "solution_test.rb.tt", "#{year}/test/day#{day}_test.rb", context: binding
55
+
56
+ download year, day if Advent.config.download_when_generating
57
+ end
58
+
59
+ desc "init DIR", "Initialise a new advent project in DIR"
60
+ def init(dir = ".")
61
+ create_file Pathname.getwd.join(dir).join(Advent::Configuration::FILE_NAME) do
81
62
  ""
82
- else
83
- "#{year}/"
84
63
  end
85
-
86
- template "solution.rb.tt", "#{subpath}day#{day}.rb", context: binding
87
- template "solution_test.rb.tt", "#{subpath}test/day#{day}_test.rb", context: binding
88
64
  end
89
65
 
90
66
  desc "solve FILE", "Solve your solution"
91
67
  # Runs a solution file, outputting both :part1 and :part2 method return values.
92
68
  def solve(path)
93
69
  require "advent/cli/solver"
94
- Solver.new(self, root_path.join(path)).solve
70
+ file_path = Pathname.getwd.join(path)
71
+
72
+ Dir.chdir Advent.root do
73
+ Solver.new(self, file_path.relative_path_from(Advent.root)).solve
74
+ end
95
75
  end
96
76
 
97
77
  desc "version", "Prints the current version of the gem"
@@ -102,22 +82,6 @@ module Advent
102
82
 
103
83
  private
104
84
 
105
- def determine_year_and_day(year_or_day, day)
106
- if in_year_directory?
107
- [root_path.basename.to_s, parse_number(year_or_day)]
108
- else
109
- [year_or_day, parse_number(day)]
110
- end
111
- end
112
-
113
- def root_path
114
- @_root_path ||= if options.root_path.is_a?(Pathname)
115
- options.root_path
116
- else
117
- Pathname.new(options.root_path)
118
- end
119
- end
120
-
121
85
  def parse_number(str)
122
86
  if (m = str.match(/[0-9]+/))
123
87
  m[0]
@@ -0,0 +1,30 @@
1
+ require "psych"
2
+
3
+ module Advent
4
+ class Configuration
5
+ DEFAULTS = {
6
+ "download_when_generating" => true,
7
+ "remember_session" => true
8
+ }
9
+ FILE_NAME = "advent.yml"
10
+
11
+ attr_reader :download_when_generating, :remember_session
12
+
13
+ class << self
14
+ def from_file(file = FILE_NAME)
15
+ if RUBY_VERSION >= "3.1"
16
+ new Psych.safe_load_file(file)
17
+ else
18
+ new Psych.safe_load(File.read(file))
19
+ end
20
+ end
21
+ end
22
+
23
+ def initialize(conf)
24
+ config = DEFAULTS.merge(conf || {})
25
+
26
+ @download_when_generating = config.dig("download_when_generating")
27
+ @remember_session = config.dig("remember_session")
28
+ end
29
+ end
30
+ end
@@ -18,11 +18,22 @@ module Advent
18
18
  end
19
19
 
20
20
  def value=(val)
21
- File.write file_name, val
21
+ if save_to_disk?
22
+ File.write file_name, val
23
+ else
24
+ @_value = val
25
+ end
22
26
  end
23
27
 
24
28
  def value
25
- File.read file_name if exist?
29
+ return @_value unless save_to_disk?
30
+ return File.read(file_name) if exist?
31
+ end
32
+
33
+ private
34
+
35
+ def save_to_disk?
36
+ Advent.config.remember_session
26
37
  end
27
38
  end
28
39
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Advent
4
- VERSION = "0.1.4"
4
+ VERSION = "0.1.6"
5
5
  end
data/lib/advent.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "advent/configuration"
3
4
  require_relative "advent/input"
4
5
  require_relative "advent/session"
5
6
  require_relative "advent/solution"
@@ -10,8 +11,29 @@ module Advent
10
11
  class Error < StandardError; end
11
12
 
12
13
  class << self
14
+ def config
15
+ @_config ||= Configuration.from_file(root.join(Configuration::FILE_NAME))
16
+ end
17
+
18
+ def root
19
+ if (location = find_config_location)
20
+ location
21
+ else
22
+ raise Error, "Cannot find advent.yml config file in current or parent directories."
23
+ end
24
+ end
25
+
13
26
  def session
14
- @_session = Session.new
27
+ @_session ||= Session.new
28
+ end
29
+
30
+ private
31
+
32
+ def find_config_location
33
+ Pathname.new(Dir.pwd).ascend do |path|
34
+ return path if File.exist? path.join(Configuration::FILE_NAME)
35
+ return nil if path.to_s == "/"
36
+ end
15
37
  end
16
38
  end
17
39
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: advent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Grieve
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-23 00:00:00.000000000 Z
11
+ date: 2022-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -34,11 +34,12 @@ extra_rdoc_files: []
34
34
  files:
35
35
  - LICENSE.txt
36
36
  - README.md
37
- - Rakefile
38
37
  - exe/advent
39
38
  - lib/advent.rb
40
39
  - lib/advent/cli.rb
40
+ - lib/advent/cli/downloader.rb
41
41
  - lib/advent/cli/solver.rb
42
+ - lib/advent/configuration.rb
42
43
  - lib/advent/input.rb
43
44
  - lib/advent/session.rb
44
45
  - lib/advent/solution.rb
@@ -50,7 +51,13 @@ homepage: https://github.com/dnlgrv/advent-rb
50
51
  licenses:
51
52
  - MIT
52
53
  metadata: {}
53
- post_install_message:
54
+ post_install_message: |2+
55
+
56
+ advent v0.1.5 requires a config file in your working directory.
57
+
58
+ See https://github.com/dnlgrv/advent-rb/blob/main/README.md#usage or if you're
59
+ brave run `advent init` in your current directory.
60
+
54
61
  rdoc_options: []
55
62
  require_paths:
56
63
  - lib
@@ -70,3 +77,4 @@ signing_key:
70
77
  specification_version: 4
71
78
  summary: Have fun with the Advent of Code using Ruby.
72
79
  test_files: []
80
+ ...
data/Rakefile DELETED
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/gem_tasks"
4
- require "rake/testtask"
5
- require "standard/rake"
6
-
7
- Rake::TestTask.new(:test) do |t|
8
- t.libs << "test"
9
- t.libs << "lib"
10
- t.options = "-p"
11
- t.test_files = FileList["test/**/*_test.rb"]
12
- end
13
-
14
- task default: %i[test]