Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rebased on development #51

Merged
merged 16 commits into from
Dec 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.test
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DSU_ENV=test
43 changes: 43 additions & 0 deletions .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby

name: Ruby

on:
push:
branches: ["main"]
pull_request:
branches: ["main"]

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
# Use `rbenv install -l` and only use the latest stable
# version of ruby.
ruby-version: ["3.0.1", "3.0.6", "3.1.4", "3.2.2"]

steps:
- uses: actions/checkout@v3
- name: Set timezone
run: sudo timedatectl set-timezone 'America/New_York'
- name: Run a command
run: date
- name: Set up Ruby
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
# change this to (see https://github.com/ruby/setup-ruby#versioning):
# uses: ruby/setup-ruby@v1
uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0
with:
ruby-version: ${{ matrix.ruby-version }}
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- name: Run tests
run: bundle exec rake
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## [2.2.0.rc.1] 2023-12-23

Enhancements

- Added `dsu browse` command to interactively page through DSU entries.
- Added "light" theme for terminals with light backgrounds, see `dsu theme list` or `dsu theme show light` for more information.

Changes

- Refactors to use activesupport Time#in_time_zone, including tests.
- Various code refactors to support the aforementioned change.

## [2.1.4] 2023-12-19

Changes
Expand Down Expand Up @@ -33,7 +45,6 @@ Bug fixes

- Fix bug that did not included I18n locale files in yanked version 2.1.0.


## [2.1.0] 2023-12-16

Enhancements
Expand Down Expand Up @@ -215,6 +226,7 @@ Changes
- `dsu config info` now displays the default configuration being used if no configuration file is being used.

Bug fixes

- Fix bug that fails to load/use configuration file options when a config file exists.

## [0.1.0.alpha.1] 2023-05-06
Expand Down
3 changes: 2 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
dsu (2.1.4)
dsu (2.2.0.rc.1)
activemodel (>= 7.0.8, < 8.0)
activesupport (>= 7.0.8, < 8.0)
colorize (>= 0.8.1, < 1.0)
Expand Down Expand Up @@ -122,6 +122,7 @@ GEM
PLATFORMS
x86_64-darwin-19
x86_64-darwin-21
x86_64-linux

DEPENDENCIES
dotenv (~> 2.8, >= 2.8.1)
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ After installation (`gem install dsu`), the first thing you may want to do is ru
#=>
Commands:
dsu add|a [OPTIONS] DESCRIPTION # Adds a DSU entry...
dsu browse|b SUBCOMMAND # Browse DSU entries...
dsu config|c SUBCOMMAND # Manage configuration...
dsu delete|d SUBCOMMAND # Delete DSU entries...
dsu edit|e SUBCOMMAND # Edit DSU entries...
Expand Down Expand Up @@ -176,6 +177,18 @@ This can be accomplished MUCH easier by using the `yesterday` mnemonic. This wil
`$ dsu list dates --from yesterday --to -6`
`$ dsu l dd -f y -t -6`

## Browsing DSU Entries
You can browse DSU entries for the current week, month and year using any of the following commands. `dsu browse` somewhat similar to `dsu list` with added `week`, `month` and `year` convenience SUBCOMMANDs. `dsu browse` also pipes the output to the terminal, so you can conveniently scroll through the listed entries using your keyboard or mouse:

**NOTE:** Keyboard and/or mouse behavior while browsing (scrolling), is operating system dependent; `dsu browse` pipes its output to the terminal using `less` on nix systems, and `more` on Windows systems.

- `$ dsu browse week`
- `$ dsu b w` # Equivalent to the above, only using shortcuts
- `$ dsu browse month`
- `$ dsu b m` # Equivalent to the above, only using shortcuts
- `$ dsu browse year`
- `$ dsu b y` # Equivalent to the above, only using shortcuts

## Editing DSU Entries

You can edit DSU entry groups by date. `dsu` will allow you to edit a DSU entry group using the `dsu edit SUBCOMMAND` date (`n|today|t|tomorrow|y|yesterday|date DATE`) you specify. `dsu edit` will open your DSU entry group entries in your editor, where you'll be able to perform editing functions against one or all of the entries.
Expand Down
15 changes: 15 additions & 0 deletions dsu.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,25 @@ Gem::Specification.new do |spec|
View the dsu README.md here: https://github.com/gangelo/dsu
View the dsu CHANGELOG.md: https://github.com/gangelo/dsu/blob/main/CHANGELOG.md

Dsu now has a browse command! Try it out by running `dsu browse help`.

Dsu now has a "light" theme for light background terminals! Try it out by running `dsu theme use light`.

Dsu now has a delete command! Try it out by running `dsu delete help`.

Try a dsu theme by running `dsu theme list` and then `dsu theme use THEME_NAME` where THEME_NAME is the name of the theme you want to try.

:)

Merry CHRISTmas, New Years and Happy holidays from dsu!
*
/*\\
*/*|\\*
/*/|\\*\\
*/**|\\*\\*
*//*|*\\*\\*\\
|||
|||
|||
POST_INSTALL
end
23 changes: 17 additions & 6 deletions lib/dsu.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,22 @@
require file
end

if !(Dsu.env.test? || Dsu.env.development?) && Dsu::Migration::Service.run_migrations?
begin
Dsu::Migration::Service.new.call
rescue StandardError => e
puts I18n.t('errors.migration.error', message: e.message)
exit 1
unless Dsu.env.test? || Dsu.env.development?
if Dsu::Migration::Service.run_migrations?
begin
Dsu::Migration::Service.new.call
rescue StandardError => e
puts I18n.t('migrations.error.failed', message: e.message)
exit 1
end
end
# TODO: Hack. Integrate this into the migration service
# so that this runs only if the migration version changes.
theme_file = 'light.json'
destination_theme_file_path = File.join(Dsu::Support::Fileable.themes_folder, theme_file)
unless File.exist?(destination_theme_file_path)
source_theme_file_path = File.join(Dsu::Support::Fileable.seed_data_folder, 'themes', theme_file)
FileUtils.cp(source_theme_file_path, destination_theme_file_path)
puts I18n.t('migrations.information.theme_copied', from: source_theme_file_path, to: destination_theme_file_path)
end
end
5 changes: 5 additions & 0 deletions lib/dsu/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require 'fileutils'
require 'time'
require_relative 'base_cli'
require_relative 'subcommands/browse'
require_relative 'subcommands/config'
require_relative 'subcommands/delete'
require_relative 'subcommands/edit'
Expand All @@ -13,6 +14,7 @@ module Dsu
# The `dsu` command.
class CLI < BaseCLI
map I18n.t('commands.add.key_mappings') => :add
map I18n.t('commands.browse.key_mappings') => :browse
map I18n.t('commands.config.key_mappings') => :config
map I18n.t('commands.delete.key_mappings') => :delete
map I18n.t('commands.edit.key_mappings') => :edit
Expand Down Expand Up @@ -43,6 +45,9 @@ def add(description)
view_entry_group(time: time)
end

desc I18n.t('commands.browse.desc'), I18n.t('commands.browse.usage')
subcommand :browse, Subcommands::Browse

desc I18n.t('commands.list.desc'), I18n.t('commands.list.usage')
subcommand :list, Subcommands::List

Expand Down
15 changes: 14 additions & 1 deletion lib/dsu/models/entry_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,18 @@ def exist?(time:)
superclass.exist?(file_path: entries_path_for(time: time))
end

def entry_group_times(between: nil)
entry_files.filter_map do |file_path|
entry_file_name = File.basename(file_path)
next unless entry_file_name.match?(ENTRIES_FILE_NAME_REGEX)

time = File.basename(entry_file_name, '.*')
next if between && !Time.parse(time).between?(between.min, between.max)

time
end
end

def find(time:)
file_path = entries_path_for(time: time)
entry_group_hash = read!(file_path: file_path)
Expand Down Expand Up @@ -200,7 +212,8 @@ def entry_files
private

def ensure_local_time(time)
time.nil? ? Time.now : time.dup.localtime
time ||= Time.now
time.in_time_zone
end
end
end
Expand Down
100 changes: 100 additions & 0 deletions lib/dsu/services/entry_group/browse_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# frozen_string_literal: true

require_relative '../../models/entry_group'
require_relative '../../support/time_formatable'
require_relative '../../support/times_sortable'

module Dsu
module Services
module EntryGroup
# This service is responsible for returning an array of
# sorted entry group dates as Time objects. The Time objects
# returned, and the sort order are determined by the options
# passed in.
class BrowseService
include Support::TimeFormatable
include Support::TimesSortable

def initialize(time:, options: {})
raise ArgumentError, 'Argument time is nil' if time.nil?
raise ArgumentError, 'Argument options is nil' if options.nil?

@time = time
@options = options
end

def call
return [] if entry_group_times.empty?

times_sort(times: entry_group_times, entries_display_order: entries_display_order)
end

private

attr_reader :time, :options

def entry_group_times
@entry_group_times ||= (min_time.to_i..max_time.to_i).step(1.day).each_with_object([]) do |time_step, times|
time = Time.at(time_step)
next unless include_all? || entry_group_count(time).positive?

times << time
end
end

def entry_group_count(time)
entry_group = Models::EntryGroup.find_or_initialize(time: time)
entry_group.persisted? ? entry_group.entries.count : 0
end

def min_time
@min_time ||= if week?
time.beginning_of_week
elsif month?
time.beginning_of_month
elsif year?
time.beginning_of_year
end
end

def max_time
@max_time ||= if week?
time.end_of_week
elsif month?
time.end_of_month
elsif year?
time.end_of_year
end
end

def entries_display_order
options[:entries_display_order] || default_entries_display_order
end

def default_entries_display_order
:asc
end

def week?
options.fetch(:browse, default_browse) == :week
end

def month?
options[:browse] == :month
end

def year?
options[:browse] == :year
end

def default_browse
:week
end

def include_all?
options.fetch(:include_all, false)
end
end
end
end
end
48 changes: 48 additions & 0 deletions lib/dsu/subcommands/browse.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# frozen_string_literal: true

require 'io/console'

require_relative '../services/stdout_redirector_service'
require_relative '../support/command_options/dsu_times'
require_relative '../support/command_options/time_mnemonic'
require_relative '../support/entry_group_browsable'
require_relative '../support/time_formatable'
require_relative '../views/entry_group/shared/no_entries_to_display'
require_relative '../views/shared/error'
require_relative 'base_subcommand'

module Dsu
module Subcommands
class Browse < BaseSubcommand
include Support::EntryGroupBrowsable
include Support::CommandOptions::TimeMnemonic
include Support::TimeFormatable

# TODO: I18n.
map %w[w] => :week
map %w[m] => :month
map %w[y] => :year

class_option :include_all, default: nil, type: :boolean, aliases: '-a',
desc: I18n.t('options.include_all')

desc I18n.t('subcommands.browse.week.desc'), I18n.t('subcommands.browse.week.usage')
long_desc I18n.t('subcommands.browse.week.long_desc')
def week
browse_entry_groups time: Time.now, options: options.merge({ browse: :week })
end

desc I18n.t('subcommands.browse.month.desc'), I18n.t('subcommands.browse.month.usage')
long_desc I18n.t('subcommands.browse.month.long_desc')
def month
browse_entry_groups time: Time.now, options: options.merge({ browse: :month })
end

desc I18n.t('subcommands.browse.year.desc'), I18n.t('subcommands.browse.year.usage')
long_desc I18n.t('subcommands.browse.year.long_desc')
def year
browse_entry_groups time: Time.now, options: options.merge({ browse: :year })
end
end
end
end
1 change: 1 addition & 0 deletions lib/dsu/subcommands/delete.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Delete < BaseSubcommand
include Support::CommandOptions::TimeMnemonic
include Support::TimeFormatable

# TODO: I18n.
map %w[d] => :date
map %w[dd] => :dates
map %w[n] => :today
Expand Down
1 change: 1 addition & 0 deletions lib/dsu/subcommands/edit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
module Dsu
module Subcommands
class Edit < BaseSubcommand
# TODO: I18n.
map %w[d] => :date
map %w[n] => :today
map %w[t] => :tomorrow
Expand Down
Loading