devlogs 0.1.6 → 0.3.1

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: b7ac238f0667f25c6b370f32660aa2d089ebbfff0ecec9bffb012f9851188174
4
- data.tar.gz: 93aaabcee373c6511a479e6cf21b6803af0cfec922e4416fed2406a966307ced
3
+ metadata.gz: 2023b8563770781f9708368975e70b713ec937df3331461096841e4f0fbd03a3
4
+ data.tar.gz: b1e7b12bac7c07aede0fa9dc8e8daca29db668e256c7a73067bc1f56993cad58
5
5
  SHA512:
6
- metadata.gz: 5833adbd0231c8fe941364cec3dd6d83878999ed67b8ebf055dda56a12289a0e609ac8cb3e2868db2f4e570e52958622f7f25f997701baf130cf86e730a5daa1
7
- data.tar.gz: fe438af20e0f8ec3326bf56ee410f037ef81495e39218586ad70ff8ae7a50a056f2c409db0b4dc02914c47dfb7dca157a9c4082bf0926c6bf739f8f9800f26a3
6
+ metadata.gz: 88c3a1909b19c35619abcaabd5815843ccb334362f2a1d5a8be7efb9f82fc64be9c43f51a1b0c76be012ef043b4a1b66bc0a4643ca2cb248ccafb3ee8a4b9fb3
7
+ data.tar.gz: 925757b3d644479dc402f2c17a762a349a9eb8b5dda7a75ecb88ec71e9712933b1fd223d239164ce4a24b8e0864040ad51c1a5f78ccce42535b1599f3b5ebfd3
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.6)
4
+ devlogs (0.3.1)
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
@@ -1,6 +1,4 @@
1
1
  # devlogs
2
- ![Version](https://img.shields.io/badge/version-0.1.4-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/lib/devlogs/cli.rb CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  require_relative "version"
4
4
  require_relative "repository"
5
+ require_relative "editor"
6
+ require_relative "pager"
7
+ require_relative "prompt_utils"
5
8
  require "thor"
6
9
 
7
10
  module Devlogs
@@ -9,6 +12,8 @@ module Devlogs
9
12
  # The CLI devlogs CLI
10
13
  #
11
14
  class CLI < Thor
15
+ include PromptUtils
16
+
12
17
  package_name "devlogs"
13
18
 
14
19
  # Returns exit with non zero status when an exception occurs
@@ -34,12 +39,27 @@ module Devlogs
34
39
 
35
40
  Repository::Initialize.run(
36
41
  { force: options.force? },
37
- File.join(".", "__devlogs")
42
+ File.join(".", "_devlogs")
38
43
  )
39
44
 
40
45
  puts "Created devlogs"
41
46
  end
42
47
 
48
+ #
49
+ # Retrieves the most recent entry from the repository
50
+ #
51
+ desc "last", "Retrieves the last entry in the repository"
52
+ method_options open: :boolean, alias: :string
53
+ def last
54
+ puts "Reading last entry"
55
+ last_entry = repo.ls.first
56
+
57
+ if options.open?
58
+ Editor.open(last_entry)
59
+ else
60
+ puts File.read(last_entry)
61
+ end
62
+ end
43
63
  #
44
64
  # Creates a devlogs entry in the repository and syncs changes
45
65
  # to the mirrored directory if set
@@ -52,6 +72,23 @@ module Devlogs
52
72
  repo.sync
53
73
  end
54
74
 
75
+ #
76
+ # Lists repository logs
77
+ #
78
+ desc "ls", "Lists the repository logs and allows you to select"
79
+ def ls
80
+ entries = repo.ls
81
+
82
+ # Use the file names as visible keys for the prompt
83
+ entry_names = entries.map { |e| File.basename(e) }
84
+
85
+ # Build the TTY:Prompt
86
+ result = build_select_prompt(data: entry_names, text: "Select a log entry...")
87
+
88
+ # Open in paging program
89
+ Pager.open(entries[result])
90
+ end
91
+
55
92
  private
56
93
 
57
94
  # Helper method for repository loading
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./executable.rb"
4
+
5
+ # Wrapper for terminal editor
6
+ class Editor < Executable
7
+ def initialize
8
+ @program = ENV["EDITOR"]
9
+ end
10
+
11
+ # Opens the file contained at the path
12
+ def open(path)
13
+ command = "#{@program} #{path}"
14
+
15
+ system command
16
+ end
17
+
18
+ class << self
19
+ # Opens the file at +path+ using system editor
20
+ def open(path)
21
+ session = new
22
+
23
+ session.open(path)
24
+ end
25
+ end
26
+ 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,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
@@ -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
@@ -50,9 +54,7 @@ class Repository
50
54
  end
51
55
  end
52
56
 
53
- editor_program = ENV["EDITOR"]
54
-
55
- system("#{editor_program} #{entry_file_path}")
57
+ Editor.open(entry_file_path)
56
58
 
57
59
  puts "Writing entry to #{entry_file_path}.."
58
60
  end
@@ -67,9 +69,8 @@ class Repository
67
69
 
68
70
  # Use trailing slash to avoid sub-directory
69
71
  # See rsync manual page
70
- path = @config.path[-1] == "/" ? @config.path : @config.path + "/"
71
72
 
72
- Rsync.run("-av", path, @config.mirror.path) do |result|
73
+ Rsync.run("-av", @config.path(with_trailing: true), @config.mirror.path) do |result|
73
74
  if result.success?
74
75
  puts "Mirror sync complete."
75
76
  result.changes.each do |change|
@@ -82,6 +83,25 @@ class Repository
82
83
  end
83
84
  end
84
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
+
85
105
  class << self
86
106
  # Loads a repository from the provided path
87
107
  #
@@ -105,15 +125,16 @@ class Repository
105
125
  # Config is a configuration data object for storing Repository configuration
106
126
  # in memory for access.
107
127
  class Config
108
- attr_reader :name, :description, :mirror, :path
128
+ attr_reader :name, :description, :mirror, :path_value
109
129
 
130
+ # Configuration associated with the Mirror
110
131
  MirrorConfig = Struct.new(:use_mirror, :path, keyword_init: true)
111
132
 
112
133
  def initialize(name, desc, mirror, p)
113
134
  @name = name
114
135
  @description = desc
115
136
  @mirror = MirrorConfig.new(mirror)
116
- @path = p
137
+ @path_value = p
117
138
  end
118
139
 
119
140
  # Returns whether or not the devlogs repository is configured to mirror
@@ -123,6 +144,14 @@ class Repository
123
144
  @mirror.use_mirror
124
145
  end
125
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
+
126
155
  # Utility method to build a configuration from a Hash
127
156
  #
128
157
  # @returns [Repository::Config]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Devlogs
4
- VERSION = "0.1.6"
4
+ VERSION = "0.3.1"
5
5
  end
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.6
4
+ version: 0.3.1
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-21 00:00:00.000000000 Z
11
+ date: 2022-09-14 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
@@ -95,6 +96,10 @@ files:
95
96
  - exe/devlogs
96
97
  - lib/devlogs.rb
97
98
  - lib/devlogs/cli.rb
99
+ - lib/devlogs/editor.rb
100
+ - lib/devlogs/executable.rb
101
+ - lib/devlogs/pager.rb
102
+ - lib/devlogs/prompt_utils.rb
98
103
  - lib/devlogs/repository.rb
99
104
  - lib/devlogs/version.rb
100
105
  homepage: http://github.com/aquaflamingo/devlogs