devlogs 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ee70029616eb23078cfe60734052a855642617338f776543da002c18986cfad
4
- data.tar.gz: 8169a90b74e0524f6b9b0ebdb786ff0fb1df38e8d59c7d6bbdbbce7936d037d5
3
+ metadata.gz: 9df7671be5997a9e311b6a8c10863732b95fb3e6bdb89a7f5ba8476d3cec4653
4
+ data.tar.gz: af3731bb2c7134cea231b17a7c940d313d13f21c0721c720029e1084d706f0a4
5
5
  SHA512:
6
- metadata.gz: 3aba32f26e6905b876ad6e0777a86d29abfe1ea0642180fe1320ee82b20cc3a8efd2e22088d3b469149f920fa12808166ee7572b1f2207337afbf146bbac38cc
7
- data.tar.gz: 9fa406dae78b034c22c9db6f992e00a0255c920bb569f68fb4c5a20a295df8bcab8fad4f7f58f1d8a4f0870e05025f0d7b7c135bd50feea06e5b31ccf5b62fcf
6
+ metadata.gz: ffe4be66ace5c88074c0ce3e8a20e0f82a53162e59776be3bfdbf1d72c038d4d73365ca65bf91047b4730a64efeb548f3e1b7f8a8704a0f9554bc427ed0daa39
7
+ data.tar.gz: 9f3326e754283f25d307c598aa8824c53aa5686c112ebb9c9301ee7dc424710c572cac02275f72cf204e5e00677c92c03bd7e3f4ee157e7d585c9a3bcd2fc6c9
data/.gitignore CHANGED
@@ -10,4 +10,4 @@ __devlog
10
10
  *.gem
11
11
  __devlogs
12
12
  mirror
13
- _devlogs
13
+ .devlogs
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- devlogs (0.2.0)
4
+ devlogs (1.0.0)
5
5
  rsync (~> 1.0, >= 1.0.9)
6
6
  thor (~> 1.2.1)
7
7
  tty-prompt (~> 0.23.1)
data/Makefile ADDED
@@ -0,0 +1,16 @@
1
+ PROJECT=devlogs
2
+
3
+ console:
4
+ @bundle exec bin/console
5
+
6
+ setup:
7
+ @bundle exec bin/setup
8
+
9
+ install:
10
+ @bundle exec rake install
11
+
12
+ release:
13
+ @bundle exec rake release
14
+
15
+ release.gh:
16
+ @gh release create
data/README.md CHANGED
@@ -23,12 +23,12 @@ Or install it yourself as:
23
23
 
24
24
  ## Usage
25
25
  ### Initialize
26
- Inside your project initialize the `_devlogs` repository:
26
+ Inside your project initialize the `.devlogs` repository:
27
27
  ```bash
28
28
  $ devlogs init
29
29
  ```
30
30
 
31
- Follow the prompts to setup the project configuration located in `_devlogs/.devlogs.config`.
31
+ Follow the prompts to setup the project configuration located in the _default_ `.devlogs/.devlogs.config`. (You can optionally set where you want to initialize the repository via --dirpath)
32
32
 
33
33
  You can setup a mirror directory path in the configuration stage to sync changes to another directory on your machine, for example to Obsidian.md.
34
34
 
@@ -36,7 +36,7 @@ Example:
36
36
 
37
37
  ```
38
38
  myproject
39
- _devlogs
39
+ .devlogs
40
40
  >> content
41
41
  ```
42
42
 
@@ -48,10 +48,10 @@ obsidianvault
48
48
  ```
49
49
 
50
50
  ### Creating entries
51
- Once you are done for the day or session run the `entry` command:
51
+ Once you are done for the day or session run the `new` command:
52
52
 
53
53
  ```bash
54
- devlogs entry
54
+ devlogs new
55
55
  ```
56
56
 
57
57
  Your editor will pop up and you can fill in cliff notes.
@@ -73,8 +73,6 @@ You can use the `last` command to retrieve the most recent entry
73
73
  devlogs last
74
74
  ```
75
75
 
76
- The `--open` command will cause the entry to be opened in a new default editor.
77
-
78
76
  ## Development
79
77
 
80
78
  After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/lib/devlogs/cli.rb CHANGED
@@ -3,6 +3,9 @@
3
3
  require_relative "version"
4
4
  require_relative "repository"
5
5
  require_relative "editor"
6
+ require_relative "pager"
7
+ require_relative "prompt_utils"
8
+ require_relative "repository/initializer"
6
9
  require "thor"
7
10
 
8
11
  module Devlogs
@@ -10,6 +13,8 @@ module Devlogs
10
13
  # The CLI devlogs CLI
11
14
  #
12
15
  class CLI < Thor
16
+ include PromptUtils
17
+
13
18
  package_name "devlogs"
14
19
 
15
20
  # Returns exit with non zero status when an exception occurs
@@ -29,16 +34,19 @@ module Devlogs
29
34
  # Initializes a +devlogs+ repository with a configuration
30
35
  #
31
36
  desc "init", "Initialize a developer logs for project"
32
- method_options force: :boolean, alias: :string
37
+ method_options force: :boolean
38
+ method_options dirpath: :string
33
39
  def init
34
40
  puts "Creating devlogs repository"
35
41
 
36
- Repository::Initialize.run(
37
- { force: options.force? },
38
- File.join(".", "_devlogs")
42
+ Repository::Initializer.run(
43
+ {
44
+ force: options.force?,
45
+ dirpath: options.dirpath,
46
+ },
39
47
  )
40
48
 
41
- puts "Created devlogs"
49
+ puts "Created devlogs repository"
42
50
  end
43
51
 
44
52
  #
@@ -60,19 +68,42 @@ module Devlogs
60
68
  # Creates a devlogs entry in the repository and syncs changes
61
69
  # to the mirrored directory if set
62
70
  #
63
- desc "entry", "Create a new devlogs entry" # [4]
64
- def entry
71
+ desc "new", "Create a new devlogs entry" # [4]
72
+ def new
65
73
  puts "Creating new entry..."
66
74
  repo.create
67
75
 
68
76
  repo.sync
69
77
  end
70
78
 
79
+ #
80
+ # Lists repository logs
81
+ #
82
+ desc "ls", "Lists the repository logs and allows you to select"
83
+ def ls
84
+ entries = repo.ls
85
+
86
+ if entries.size < 1
87
+ puts "No logs present in this repository"
88
+ exit 0
89
+ end
90
+
91
+ # Use the file names as visible keys for the prompt
92
+ entry_names = entries.map { |e| File.basename(e) }
93
+
94
+ # Build the TTY:Prompt
95
+ result = build_select_prompt(data: entry_names, text: "Select a log entry...")
96
+
97
+ # Open in paging program
98
+ Pager.open(entries[result])
99
+ end
100
+
71
101
  private
72
102
 
73
103
  # Helper method for repository loading
74
104
  #
75
105
  def repo
106
+ # FIXME: Need to add in path specification here
76
107
  @repo ||= Repository.load
77
108
  end
78
109
  end
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "./executable.rb"
4
+
3
5
  # Wrapper for terminal editor
4
- class Editor
6
+ class Editor < Executable
5
7
  def initialize
6
8
  @program = ENV["EDITOR"]
7
9
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Executable
4
+ def initialize
5
+ raise NotImplementedError, "Abstract class"
6
+ end
7
+
8
+ # Opens the file contained at the path
9
+ def open(path)
10
+ command = "#{@program} #{path}"
11
+
12
+ system command
13
+ end
14
+
15
+ class << self
16
+ # Opens the file at +path+ using system editor
17
+ def open(path)
18
+ session = new
19
+
20
+ session.open(path)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Devlogs
4
+ def self.lib_root
5
+ File.join(File.dirname(__dir__), "devlogs")
6
+ end
7
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "erb"
4
+
5
+ #
6
+ # LogTemplate is a class that represents the rendered log template
7
+ #
8
+ class LogTemplate
9
+ attr_reader :time
10
+
11
+ TIME_FORMAT_TEXT_ENTRY = "%m-%d-%Y %k:%M"
12
+
13
+ def initialize(template_file_path)
14
+ @time = Time.new.strftime(TIME_FORMAT_TEXT_ENTRY)
15
+ @template_file_path = template_file_path
16
+ end
17
+
18
+ #
19
+ # Runs the ERB rendering using the provided template file template_file_path
20
+ #
21
+ # @returns [String]
22
+ #
23
+ def render
24
+ erb = ERB.new(File.read(@template_file_path))
25
+ erb.result(get_binding)
26
+ end
27
+
28
+ # rubocop:disable
29
+ #
30
+ # For ERB
31
+ #
32
+ def get_binding
33
+ binding
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Wrapper for terminal reader
4
+ require_relative "./executable.rb"
5
+
6
+ # Wrapper for terminal pager
7
+ class Pager < Executable
8
+ def initialize
9
+ @program = ENV["PAGER"]
10
+ end
11
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tty-prompt"
4
+
5
+ #
6
+ # Utility module for tty-prompt library
7
+ #
8
+ module PromptUtils
9
+ #
10
+ # Builds a basic select prompt using the provided data
11
+ #
12
+ # @param data [Array<String>]
13
+ #
14
+ # @returns String
15
+ #
16
+ def build_select_prompt(data:, text:)
17
+ ttyprompt = TTY::Prompt.new
18
+
19
+ ttyprompt.select(text) do |menu|
20
+ data.each_with_index do |d, index|
21
+ menu.choice d, index
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The repository's configuration values located in the yml file
4
+ class Repository
5
+ class Config
6
+ # FIXME: Need to figure out file path
7
+ attr_reader :name, :description, :mirror, :file_path, :template_file_path
8
+
9
+ # Configuration associated with the Mirror
10
+ MirrorConfig = Struct.new(:use_mirror, :path, keyword_init: true)
11
+
12
+ def initialize(path, opts = {})
13
+ @file_path = path
14
+ @template_file_path = opts[:template_file_path]
15
+ @name = opts[:name]
16
+ @description = opts[:description]
17
+ @mirror = MirrorConfig.new(opts[:mirror])
18
+ end
19
+
20
+ # Returns whether or not the devlogs repository is configured to mirror
21
+ #
22
+ # @returns [Boolean]
23
+ def mirror?
24
+ @mirror.use_mirror
25
+ end
26
+
27
+ # Ensures no weird double trailing slash path values
28
+ def path(with_trailing: false)
29
+ if with_trailing
30
+ @file_path[-1] == "/" ? @path_value : @path_value + "/"
31
+ else
32
+ @file_path
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+ require "rsync"
5
+
6
+ require_relative "config"
7
+
8
+ # A per repository configuration storage directory
9
+ class Repository
10
+ class ConfigStore
11
+ attr_reader :dir, :values
12
+
13
+ CONFIG_FILE = ".devlogs.config.yml"
14
+
15
+ # TODO: should be part of configuration
16
+ TEMPLATE_FILE = ".log_template.erb.md"
17
+ DEFAULT_DIRECTORY_PATH = "."
18
+ DEFAULT_DIRECTORY_NAME = ".devlogs"
19
+
20
+ def initialize(dir: File.join(DEFAULT_DIRECTORY_PATH, DEFAULT_DIRECTORY_NAME))
21
+ @dir = dir
22
+ end
23
+
24
+ def values
25
+ @values ||= load_values_from_config_file
26
+ end
27
+
28
+ def file_path
29
+ File.join(@dir, CONFIG_FILE)
30
+ end
31
+
32
+ def template_file_path
33
+ File.join(@dir, TEMPLATE_FILE)
34
+ end
35
+
36
+ class << self
37
+ def load_from(path = File.join(DEFAULT_DIRECTORY_PATH, DEFAULT_DIRECTORY_NAME))
38
+ exists = File.exist?(path)
39
+
40
+ raise "no repository found #{path}" unless exists
41
+
42
+ new(dir: path)
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def load_values_from_config_file
49
+ yml = YAML.load_file(File.join(file_path))
50
+
51
+ Repository::Config.new(file_path, yml)
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "config_store"
4
+
5
+ # Initialize is an execution object which initializes a Repository on the
6
+ # filesystem
7
+ class Repository
8
+ class Initializer
9
+ INFO_FILE_SUFFIX = "devlogs.info.md"
10
+ LOG_TEMPLATE_FILE_NAME = "__log_template.erb.md"
11
+
12
+ # Creates a new devlogs repository at the provided path
13
+ def self.run(opts = {})
14
+ new_config = if opts[:dirpath]
15
+ Repository::ConfigStore.new(dir: opts[:dirpath])
16
+ else
17
+ Repository::ConfigStore.new
18
+ end
19
+
20
+ exists = File.exist?(new_config.file_path)
21
+
22
+ if exists && !opts[:force]
23
+ puts "Log repository already exists in #{new_config.file_path}. Aborting..."
24
+ raise RuntimeError
25
+ end
26
+
27
+ results = prompt_for_info
28
+
29
+ # Create the new_config directory
30
+ FileUtils.mkdir_p(new_config.dir)
31
+
32
+ # Create new_config file
33
+ File.open(new_config.file_path, "w") do |f|
34
+ f.write results.to_yaml
35
+ end
36
+
37
+ # Replace spaces in project name with underscores
38
+ sanitized_project_name = results[:name].gsub(/ /, "_").downcase
39
+
40
+ # Create the info file
41
+ info_file_name = "#{sanitized_project_name}.devlogs.info.md"
42
+ info_file = File.join(new_config.dir, info_file_name)
43
+
44
+ File.open(info_file, "w") do |f|
45
+ f.puts "# #{results[:name]}"
46
+ f.puts (results[:desc]).to_s
47
+ end
48
+
49
+ # Copy the default template file inside the gem into the repository
50
+ default_template_path = get_template_path
51
+
52
+ new_config_template_file_path = File.join(new_config.dir, Repository::ConfigStore::TEMPLATE_FILE)
53
+
54
+ FileUtils.cp(default_template_path, new_config_template_file_path)
55
+ end
56
+
57
+ # Creates an interactive prompt for user input
58
+ #
59
+ # @returns [Hash]
60
+ def self.prompt_for_info
61
+ prompt = TTY::Prompt.new
62
+
63
+ prompt.collect do |_p|
64
+ # Project name
65
+ key(:name).ask("What is the project name?") do |q|
66
+ q.required true
67
+ end
68
+
69
+ # Project description
70
+ key(:desc).ask("What is the project description?") do |q|
71
+ q.required true
72
+ end
73
+
74
+ key(:mirror) do
75
+ key(:use_mirror).ask("Do you want to mirror these logs?", convert: :boolean)
76
+ key(:path).ask("Path to mirror directory: ")
77
+ end
78
+ end
79
+ end
80
+
81
+ # Gets the template file path embedded in the gem from the library root
82
+ def self.get_template_path
83
+ File.join(Devlogs.lib_root, "templates", LOG_TEMPLATE_FILE_NAME)
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rsync"
4
+
5
+ # FIXME: Create module
6
+ class Repository
7
+ #
8
+ # SyncManager is an abstraction class for managing any necessity to sync
9
+ # files on the file system using Rsync.
10
+ #
11
+ class SyncManager
12
+ #
13
+ # @param config_store [Repository::ConfigStore]
14
+ #
15
+ def initialize(config_store)
16
+ @config_store = config_store
17
+ end
18
+
19
+ # Run rsync with -a to copy directories recursively
20
+
21
+ # Use trailing slash to avoid sub-directory
22
+ # See rsync manual page
23
+ #
24
+ # @throws Error if sync fails
25
+ def run
26
+ dest_path = @config_store.values.mirror.path
27
+ src_path = config_store_path_with_trailing
28
+
29
+ runner.run("-av", src_path, dest_path) do |result|
30
+ if result.success?
31
+ puts "Mirror sync complete."
32
+ result.changes.each do |change|
33
+ puts "#{change.filename} (#{change.summary})"
34
+ end
35
+ else
36
+ raise "Failed to sync: #{result.error}"
37
+ end
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ #
44
+ # Utility method for getting access to the runner program
45
+ # @returns [Rsync]
46
+ #
47
+ def runner
48
+ @runner ||= Rsync
49
+ end
50
+
51
+ # Depending on the runner (Rsync) program,
52
+ # you may need a trailing slash on the directory path
53
+ #
54
+ # @returns [String]
55
+ def config_store_path_with_trailing
56
+ @config_store.dir[-1] == "/" ? @config_store.dir : @config_store.dir + "/"
57
+ end
58
+ end
59
+ end
@@ -2,55 +2,50 @@
2
2
 
3
3
  require "fileutils"
4
4
  require "tty-prompt"
5
- require "yaml"
6
- require "rsync"
7
5
  require "pry"
8
6
  require "time"
7
+
8
+ require_relative "repository/config_store"
9
9
  require_relative "editor"
10
+ require_relative "repository/sync_manager"
11
+ require_relative "log_template"
10
12
 
11
13
  # Repostiroy is an accessor object for the devlogs directory
12
14
  class Repository
13
- CONFIG_FILE = ".devlogs.config.yml"
14
-
15
- # TODO: should be part of configuration
16
- DEFAULT_LOG_SUFFIX = "devlogs.md"
17
- DEFAULT_DIRECTORY_PATH = "."
18
- DEFAULT_DIRECTORY_NAME = "_devlogs"
19
-
20
15
  # Example: 11-22-2022_1343
21
- DEFAULT_TIME_FORMAT_FILE_PREFIX = "%m-%d-%Y__%kh%Mm"
22
- DEFAULT_TIME_FORMAT_TEXT_ENTRY = "%m-%d-%Y %k:%M"
16
+ TIME_FORMAT_FILE_PREFIX = "%m-%d-%Y__%kh%Mm"
17
+
18
+ LOG_FILE_SUFFIX = "log.md"
19
+ ISSUE_FILE_PREFIX = "iss"
23
20
 
24
21
  VALID_DIRECTION = %i[asc desc].freeze
25
22
 
26
- # Initializes a _devlogs repository with the supplied configuration
27
- # @param repo_config [Repository::Config]
23
+ # Initializes a .devlogs repository with the supplied configuration
28
24
  #
29
- def initialize(repo_config)
30
- @config = repo_config
25
+ def initialize(repo_config_store)
26
+ @config_store = repo_config_store
27
+ @repo_config = @config_store.values
31
28
  end
32
29
 
33
- # Creates a new _devlogs entry for recording session completion
30
+ # Creates a new .devlogs entry for recording session completion
34
31
  #
35
32
  # @returns nil
36
33
  def create
37
34
  time = Time.new
38
- prefix = time.strftime(DEFAULT_TIME_FORMAT_FILE_PREFIX)
35
+ time_prefix = time.strftime(TIME_FORMAT_FILE_PREFIX)
36
+
37
+ entry_file_name = "#{time_prefix}_#{LOG_FILE_SUFFIX}"
39
38
 
40
- entry_file_name = "#{prefix}_#{DEFAULT_LOG_SUFFIX}"
39
+ # FIXME: Need to figure out file path
40
+ entry_file_path = File.join(@config_store.dir, entry_file_name)
41
41
 
42
- entry_file_path = File.join(@config.path, entry_file_name)
42
+ # FIXME: Need to figure out file path
43
+ template = LogTemplate.new(@config_store.template_file_path)
43
44
 
44
45
  unless File.exist?(entry_file_path)
45
46
  # Add default boiler plate if the file does not exist yet
46
47
  File.open(entry_file_path, "w") do |f|
47
- f.write <<~ENDOFFILE
48
- # #{time.strftime(DEFAULT_TIME_FORMAT_TEXT_ENTRY)}
49
- Tags: #dev, #log
50
-
51
- What did you do today?
52
-
53
- ENDOFFILE
48
+ f.write template.render
54
49
  end
55
50
  end
56
51
 
@@ -64,30 +59,14 @@ class Repository
64
59
  #
65
60
  # @returns nil
66
61
  def sync
67
- if @config.mirror?
68
- # Run rsync with -a to copy directories recursively
69
-
70
- # Use trailing slash to avoid sub-directory
71
- # See rsync manual page
72
-
73
- Rsync.run("-av", @config.path(with_trailing: true), @config.mirror.path) do |result|
74
- if result.success?
75
- puts "Mirror sync complete."
76
- result.changes.each do |change|
77
- puts "#{change.filename} (#{change.summary})"
78
- end
79
- else
80
- raise "Failed to sync: #{result.error}"
81
- end
82
- end
83
- end
62
+ sync_manager.run if @repo_config.mirror?
84
63
  end
85
64
 
86
65
  # Lists the files in the repository
87
66
  def ls(direction = :desc)
88
67
  raise ArgumentError, "Must be one of: " + VALID_DIRECTION unless VALID_DIRECTION.include?(direction.to_sym)
89
68
 
90
- Dir.glob(File.join(@config.path, "*_#{DEFAULT_LOG_SUFFIX}")).sort_by do |fpath|
69
+ Dir.glob(File.join(@config_store.dir, "*_#{LOG_FILE_SUFFIX}")).sort_by do |fpath|
91
70
  # The date is joined by two underscores to the suffix
92
71
  date, = File.basename(fpath).split("__")
93
72
 
@@ -107,129 +86,16 @@ class Repository
107
86
  #
108
87
  # @returns [Repository]
109
88
  #
110
- def load(path = File.join(DEFAULT_DIRECTORY_PATH, DEFAULT_DIRECTORY_NAME))
111
- exists = File.exist?(path)
112
-
113
- raise "no repository found #{path}" unless exists
114
-
115
- cfg = YAML.load_file(File.join(path, CONFIG_FILE))
116
-
117
- cfg[:path] = path
89
+ def load(path = File.join(Repository::ConfigStore::DEFAULT_DIRECTORY_PATH, Repository::ConfigStore::DEFAULT_DIRECTORY_NAME))
90
+ store = Repository::ConfigStore.load_from(path)
118
91
 
119
- repo_config = Config.hydrate(cfg)
120
-
121
- new(repo_config)
92
+ new(store)
122
93
  end
123
94
  end
124
95
 
125
- # Config is a configuration data object for storing Repository configuration
126
- # in memory for access.
127
- class Config
128
- attr_reader :name, :description, :mirror, :path_value
129
-
130
- # Configuration associated with the Mirror
131
- MirrorConfig = Struct.new(:use_mirror, :path, keyword_init: true)
132
-
133
- def initialize(name, desc, mirror, p)
134
- @name = name
135
- @description = desc
136
- @mirror = MirrorConfig.new(mirror)
137
- @path_value = p
138
- end
139
-
140
- # Returns whether or not the devlogs repository is configured to mirror
141
- #
142
- # @returns [Boolean]
143
- def mirror?
144
- @mirror.use_mirror
145
- end
146
-
147
- def path(with_trailing: false)
148
- if with_trailing
149
- @path_value[-1] == "/" ? @path_value : @path_value + "/"
150
- else
151
- @path_value
152
- end
153
- end
96
+ private
154
97
 
155
- # Utility method to build a configuration from a Hash
156
- #
157
- # @returns [Repository::Config]
158
- def self.hydrate(cfg)
159
- new(cfg[:name], cfg[:description], cfg[:mirror], cfg[:path])
160
- end
161
- end
162
-
163
- # Initialize is an execution object which initializes a Repository on the
164
- # filesystem
165
- class Initialize
166
- # Creates a new devlogs repository at the provided path
167
- def self.run(opts = {}, path = File.join(DEFAULT_DIRECTORY_PATH, DEFAULT_DIRECTORY_NAME))
168
- exists = File.exist?(path)
169
-
170
- if exists && !opts[:force]
171
- puts "Log repository already exists in #{path}. Aborting..."
172
- raise RuntimeError
173
- end
174
-
175
- results = prompt_for_info
176
-
177
- FileUtils.mkdir_p(path)
178
- config_file = File.join(path, CONFIG_FILE)
179
-
180
- # Replace spaces in project name with underscores
181
- sanitized_project_name = results[:name].gsub(/ /, "_").downcase
182
-
183
- info_file_name = "#{sanitized_project_name}_devlogs.info.md"
184
- info_file = File.join(path, info_file_name)
185
-
186
- # Create config file
187
- File.open(config_file, "w") do |f|
188
- f.write results.to_yaml
189
- end
190
-
191
- # Create the info file
192
- File.open(info_file, "w") do |f|
193
- f.puts "# #{results[:name]}"
194
- f.puts (results[:desc]).to_s
195
- end
196
-
197
- # Git ignore if specified
198
- if results[:gitignore]
199
- gitignore = File.join(path, ".gitignore")
200
-
201
- File.open(gitignore, "a") do |f|
202
- f.puts DEFAULT_DIRECTORY_NAME
203
- end
204
- end
205
- end
206
-
207
- # Creates an interactive prompt for user input
208
- #
209
- # @returns [Hash]
210
- def self.prompt_for_info
211
- prompt = TTY::Prompt.new
212
-
213
- prompt.collect do |_p|
214
- # Project name
215
- key(:name).ask("What is the project name?") do |q|
216
- q.required true
217
- end
218
-
219
- # Project description
220
- key(:desc).ask("What is the project description?") do |q|
221
- q.required true
222
- end
223
-
224
- key(:mirror) do
225
- key(:use_mirror).ask("Do you want to mirror these logs?", convert: :boolean)
226
- key(:path).ask("Path to mirror directory: ")
227
- end
228
-
229
- key(:gitignore).ask("Do you want to gitignore the devlogs repository?") do |q|
230
- q.required true
231
- end
232
- end
233
- end
98
+ def sync_manager
99
+ @sync_manager ||= Repository::SyncManager.new(@config_store)
234
100
  end
235
101
  end
@@ -0,0 +1,5 @@
1
+ # LOG: <%= @time %>
2
+ Tags: #dev, #log
3
+
4
+ What did you do today?
5
+
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Devlogs
4
- VERSION = "0.2.0"
4
+ VERSION = "1.0.0"
5
5
  end
data/lib/devlogs.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "devlogs/gem"
3
4
  require_relative "devlogs/cli"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devlogs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - aquaflamingo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-04-27 00:00:00.000000000 Z
11
+ date: 2022-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rsync
@@ -86,6 +86,7 @@ files:
86
86
  - Gemfile
87
87
  - Gemfile.lock
88
88
  - LICENSE.txt
89
+ - Makefile
89
90
  - README.md
90
91
  - Rakefile
91
92
  - bin/console
@@ -96,7 +97,17 @@ files:
96
97
  - lib/devlogs.rb
97
98
  - lib/devlogs/cli.rb
98
99
  - lib/devlogs/editor.rb
100
+ - lib/devlogs/executable.rb
101
+ - lib/devlogs/gem.rb
102
+ - lib/devlogs/log_template.rb
103
+ - lib/devlogs/pager.rb
104
+ - lib/devlogs/prompt_utils.rb
99
105
  - lib/devlogs/repository.rb
106
+ - lib/devlogs/repository/config.rb
107
+ - lib/devlogs/repository/config_store.rb
108
+ - lib/devlogs/repository/initializer.rb
109
+ - lib/devlogs/repository/sync_manager.rb
110
+ - lib/devlogs/templates/__log_template.erb.md
100
111
  - lib/devlogs/version.rb
101
112
  homepage: http://github.com/aquaflamingo/devlogs
102
113
  licenses: