devlogs 0.1.4 → 0.2.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: b99f8b324427d042c22df13670cd362387c29d2392d3c5ac5b4dc3933e7a6350
4
- data.tar.gz: 10e884ccc05ab8f967ef1b12eb8b28bb728d0642510e9279c76f2c696929cbb8
3
+ metadata.gz: 0ee70029616eb23078cfe60734052a855642617338f776543da002c18986cfad
4
+ data.tar.gz: 8169a90b74e0524f6b9b0ebdb786ff0fb1df38e8d59c7d6bbdbbce7936d037d5
5
5
  SHA512:
6
- metadata.gz: 41736e5c49fae07395e3da06f9aba779a48d14b5ded23ba0a062ff9de1a176050fee2208a959417846e9029166c4deb59eb93114dc93c67e3c7c55415b0be550
7
- data.tar.gz: e9854ed3e849a7208a8c9e3c82410973945c99a9a2e488a9f153f8612bcb80ed5f3a66f6a45f2d8cfe4945bb66b6abad3738b2df339a429bf5b7d9e7d31945cb
6
+ metadata.gz: 3aba32f26e6905b876ad6e0777a86d29abfe1ea0642180fe1320ee82b20cc3a8efd2e22088d3b469149f920fa12808166ee7572b1f2207337afbf146bbac38cc
7
+ data.tar.gz: 9fa406dae78b034c22c9db6f992e00a0255c920bb569f68fb4c5a20a295df8bcab8fad4f7f58f1d8a4f0870e05025f0d7b7c135bd50feea06e5b31ccf5b62fcf
data/.gitignore CHANGED
@@ -10,3 +10,4 @@ __devlog
10
10
  *.gem
11
11
  __devlogs
12
12
  mirror
13
+ _devlogs
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- devlogs (0.1.4)
4
+ devlogs (0.2.0)
5
5
  rsync (~> 1.0, >= 1.0.9)
6
6
  thor (~> 1.2.1)
7
7
  tty-prompt (~> 0.23.1)
data/README.md CHANGED
@@ -1,6 +1,4 @@
1
1
  # devlogs
2
- ![Version](https://img.shields.io/badge/version-0.1.0-green)
3
-
4
2
  Project based session logging for solo-developers with the option to mirror changes to another directory.
5
3
 
6
4
  https://stacktrace.one/blog/avoid-project-management-solo-dev/
@@ -25,12 +23,12 @@ Or install it yourself as:
25
23
 
26
24
  ## Usage
27
25
  ### Initialize
28
- Inside your project initialize the `__devlogs` repository:
26
+ Inside your project initialize the `_devlogs` repository:
29
27
  ```bash
30
28
  $ devlogs init
31
29
  ```
32
30
 
33
- Follow the prompts to setup the project configuration located in `__devlogs/.devlogs.config`.
31
+ Follow the prompts to setup the project configuration located in `_devlogs/.devlogs.config`.
34
32
 
35
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.
36
34
 
@@ -38,7 +36,7 @@ Example:
38
36
 
39
37
  ```
40
38
  myproject
41
- __devlogs
39
+ _devlogs
42
40
  >> content
43
41
  ```
44
42
 
@@ -68,6 +66,15 @@ Your editor will pop up and you can fill in cliff notes.
68
66
 
69
67
  Save and if you set a mirror it will sync over!
70
68
 
69
+ ### Retrieve previous entry
70
+ You can use the `last` command to retrieve the most recent entry
71
+
72
+ ```bash
73
+ devlogs last
74
+ ```
75
+
76
+ The `--open` command will cause the entry to be opened in a new default editor.
77
+
71
78
  ## Development
72
79
 
73
80
  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/exe/devlogs CHANGED
@@ -3,4 +3,4 @@
3
3
 
4
4
  require "devlogs"
5
5
 
6
- Devlogs::App.start(ARGV)
6
+ Devlogs::CLI.start(ARGV)
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "version"
4
+ require_relative "repository"
5
+ require_relative "editor"
6
+ require "thor"
7
+
8
+ module Devlogs
9
+ #
10
+ # The CLI devlogs CLI
11
+ #
12
+ class CLI < Thor
13
+ package_name "devlogs"
14
+
15
+ # Returns exit with non zero status when an exception occurs
16
+ def self.exit_on_failure?
17
+ true
18
+ end
19
+
20
+ #
21
+ # Returns version of the cli
22
+ #
23
+ desc "version", "Prints the current version"
24
+ def version
25
+ puts Devlogs::VERSION
26
+ end
27
+
28
+ #
29
+ # Initializes a +devlogs+ repository with a configuration
30
+ #
31
+ desc "init", "Initialize a developer logs for project"
32
+ method_options force: :boolean, alias: :string
33
+ def init
34
+ puts "Creating devlogs repository"
35
+
36
+ Repository::Initialize.run(
37
+ { force: options.force? },
38
+ File.join(".", "_devlogs")
39
+ )
40
+
41
+ puts "Created devlogs"
42
+ end
43
+
44
+ #
45
+ # Retrieves the most recent entry from the repository
46
+ #
47
+ desc "last", "Retrieves the last entry in the repository"
48
+ method_options open: :boolean, alias: :string
49
+ def last
50
+ puts "Reading last entry"
51
+ last_entry = repo.ls.first
52
+
53
+ if options.open?
54
+ Editor.open(last_entry)
55
+ else
56
+ puts File.read(last_entry)
57
+ end
58
+ end
59
+ #
60
+ # Creates a devlogs entry in the repository and syncs changes
61
+ # to the mirrored directory if set
62
+ #
63
+ desc "entry", "Create a new devlogs entry" # [4]
64
+ def entry
65
+ puts "Creating new entry..."
66
+ repo.create
67
+
68
+ repo.sync
69
+ end
70
+
71
+ private
72
+
73
+ # Helper method for repository loading
74
+ #
75
+ def repo
76
+ @repo ||= Repository.load
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Wrapper for terminal editor
4
+ class Editor
5
+ def initialize
6
+ @program = ENV["EDITOR"]
7
+ end
8
+
9
+ # Opens the file contained at the path
10
+ def open(path)
11
+ command = "#{@program} #{path}"
12
+
13
+ system command
14
+ end
15
+
16
+ class << self
17
+ # Opens the file at +path+ using system editor
18
+ def open(path)
19
+ session = new
20
+
21
+ session.open(path)
22
+ end
23
+ end
24
+ end
@@ -5,6 +5,8 @@ require "tty-prompt"
5
5
  require "yaml"
6
6
  require "rsync"
7
7
  require "pry"
8
+ require "time"
9
+ require_relative "editor"
8
10
 
9
11
  # Repostiroy is an accessor object for the devlogs directory
10
12
  class Repository
@@ -13,20 +15,22 @@ class Repository
13
15
  # TODO: should be part of configuration
14
16
  DEFAULT_LOG_SUFFIX = "devlogs.md"
15
17
  DEFAULT_DIRECTORY_PATH = "."
16
- DEFAULT_DIRECTORY_NAME = "__devlogs"
18
+ DEFAULT_DIRECTORY_NAME = "_devlogs"
17
19
 
18
20
  # Example: 11-22-2022_1343
19
21
  DEFAULT_TIME_FORMAT_FILE_PREFIX = "%m-%d-%Y__%kh%Mm"
20
22
  DEFAULT_TIME_FORMAT_TEXT_ENTRY = "%m-%d-%Y %k:%M"
21
23
 
22
- # Initializes a __devlogs repository with the supplied configuration
24
+ VALID_DIRECTION = %i[asc desc].freeze
25
+
26
+ # Initializes a _devlogs repository with the supplied configuration
23
27
  # @param repo_config [Repository::Config]
24
28
  #
25
29
  def initialize(repo_config)
26
30
  @config = repo_config
27
31
  end
28
32
 
29
- # Creates a new __devlogs entry for recording session completion
33
+ # Creates a new _devlogs entry for recording session completion
30
34
  #
31
35
  # @returns nil
32
36
  def create
@@ -42,6 +46,7 @@ class Repository
42
46
  File.open(entry_file_path, "w") do |f|
43
47
  f.write <<~ENDOFFILE
44
48
  # #{time.strftime(DEFAULT_TIME_FORMAT_TEXT_ENTRY)}
49
+ Tags: #dev, #log
45
50
 
46
51
  What did you do today?
47
52
 
@@ -49,9 +54,7 @@ class Repository
49
54
  end
50
55
  end
51
56
 
52
- editor_program = ENV["EDITOR"]
53
-
54
- system("#{editor_program} #{entry_file_path}")
57
+ Editor.open(entry_file_path)
55
58
 
56
59
  puts "Writing entry to #{entry_file_path}.."
57
60
  end
@@ -66,9 +69,8 @@ class Repository
66
69
 
67
70
  # Use trailing slash to avoid sub-directory
68
71
  # See rsync manual page
69
- path = @config.path[-1] == "/" ? @config.path : @config.path + "/"
70
72
 
71
- Rsync.run("-av", path, @config.mirror.path) do |result|
73
+ Rsync.run("-av", @config.path(with_trailing: true), @config.mirror.path) do |result|
72
74
  if result.success?
73
75
  puts "Mirror sync complete."
74
76
  result.changes.each do |change|
@@ -81,6 +83,25 @@ class Repository
81
83
  end
82
84
  end
83
85
 
86
+ # Lists the files in the repository
87
+ def ls(direction = :desc)
88
+ raise ArgumentError, "Must be one of: " + VALID_DIRECTION unless VALID_DIRECTION.include?(direction.to_sym)
89
+
90
+ Dir.glob(File.join(@config.path, "*_#{DEFAULT_LOG_SUFFIX}")).sort_by do |fpath|
91
+ # The date is joined by two underscores to the suffix
92
+ date, = File.basename(fpath).split("__")
93
+
94
+ time_ms = Time.strptime(date, "%m-%d-%Y").to_i
95
+
96
+ # Descending
97
+ if direction == :asc
98
+ time_ms
99
+ else
100
+ -time_ms
101
+ end
102
+ end
103
+ end
104
+
84
105
  class << self
85
106
  # Loads a repository from the provided path
86
107
  #
@@ -104,15 +125,16 @@ class Repository
104
125
  # Config is a configuration data object for storing Repository configuration
105
126
  # in memory for access.
106
127
  class Config
107
- attr_reader :name, :description, :mirror, :path
128
+ attr_reader :name, :description, :mirror, :path_value
108
129
 
130
+ # Configuration associated with the Mirror
109
131
  MirrorConfig = Struct.new(:use_mirror, :path, keyword_init: true)
110
132
 
111
133
  def initialize(name, desc, mirror, p)
112
134
  @name = name
113
135
  @description = desc
114
136
  @mirror = MirrorConfig.new(mirror)
115
- @path = p
137
+ @path_value = p
116
138
  end
117
139
 
118
140
  # Returns whether or not the devlogs repository is configured to mirror
@@ -122,6 +144,14 @@ class Repository
122
144
  @mirror.use_mirror
123
145
  end
124
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
154
+
125
155
  # Utility method to build a configuration from a Hash
126
156
  #
127
157
  # @returns [Repository::Config]
@@ -146,7 +176,11 @@ class Repository
146
176
 
147
177
  FileUtils.mkdir_p(path)
148
178
  config_file = File.join(path, CONFIG_FILE)
149
- info_file_name = "#{results[:name].gsub(/ /, "_")}_devlogs.info"
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"
150
184
  info_file = File.join(path, info_file_name)
151
185
 
152
186
  # Create config file
@@ -154,10 +188,20 @@ class Repository
154
188
  f.write results.to_yaml
155
189
  end
156
190
 
191
+ # Create the info file
157
192
  File.open(info_file, "w") do |f|
158
193
  f.puts "# #{results[:name]}"
159
194
  f.puts (results[:desc]).to_s
160
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
161
205
  end
162
206
 
163
207
  # Creates an interactive prompt for user input
@@ -181,6 +225,10 @@ class Repository
181
225
  key(:use_mirror).ask("Do you want to mirror these logs?", convert: :boolean)
182
226
  key(:path).ask("Path to mirror directory: ")
183
227
  end
228
+
229
+ key(:gitignore).ask("Do you want to gitignore the devlogs repository?") do |q|
230
+ q.required true
231
+ end
184
232
  end
185
233
  end
186
234
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Devlogs
4
- VERSION = "0.1.4"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/devlogs.rb CHANGED
@@ -1,56 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "devlogs/version"
4
- require_relative "devlogs/repository"
5
-
6
- require "thor"
7
-
8
- module Devlogs
9
- #
10
- # The CLI devlogs App
11
- #
12
- class App < Thor
13
- package_name "devlogs"
14
-
15
- # Returns exit with non zero status when an exception occurs
16
- def self.exit_on_failure?
17
- true
18
- end
19
-
20
- #
21
- # Initializes a +devlogs+ repository with a configuration
22
- #
23
- desc "init", "Initialize a developer logs for project"
24
- method_options force: :boolean, alias: :string
25
- def init
26
- puts "Creating devlogs repository"
27
-
28
- Repository::Initialize.run(
29
- { force: options.force? },
30
- File.join(".", "__devlogs")
31
- )
32
-
33
- puts "Created devlogs"
34
- end
35
-
36
- #
37
- # Creates a devlogs entry in the repository and syncs changes
38
- # to the mirrored directory if set
39
- #
40
- desc "entry", "Create a new devlogs entry" # [4]
41
- def entry
42
- puts "Creating new entry..."
43
- repo.create
44
-
45
- repo.sync
46
- end
47
-
48
- private
49
-
50
- # Helper method for repository loading
51
- #
52
- def repo
53
- @repo ||= Repository.load
54
- end
55
- end
56
- end
3
+ 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.1.4
4
+ version: 0.2.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-19 00:00:00.000000000 Z
11
+ date: 2022-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rsync
@@ -94,6 +94,8 @@ files:
94
94
  - docs/mirroring.png
95
95
  - exe/devlogs
96
96
  - lib/devlogs.rb
97
+ - lib/devlogs/cli.rb
98
+ - lib/devlogs/editor.rb
97
99
  - lib/devlogs/repository.rb
98
100
  - lib/devlogs/version.rb
99
101
  homepage: http://github.com/aquaflamingo/devlogs
@@ -118,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
118
120
  - !ruby/object:Gem::Version
119
121
  version: '0'
120
122
  requirements: []
121
- rubygems_version: 3.2.3
123
+ rubygems_version: 3.3.7
122
124
  signing_key:
123
125
  specification_version: 4
124
126
  summary: A command line utility to create and manage project management with a logs