devlogs 0.1.4 → 0.2.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: 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