flycal-cli 0.4.0 → 0.5.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 +4 -4
- data/README.md +52 -7
- data/config/defaults.yml +2 -1
- data/lib/flycal_cli/cli.rb +210 -58
- data/lib/flycal_cli/config.rb +41 -1
- data/lib/flycal_cli/version.rb +1 -1
- data/locales/en.json +24 -2
- data/locales/it.json +24 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 980bab82020402b0031c0fc3d84a240626a8a26145cc8a86973390777b21db12
|
|
4
|
+
data.tar.gz: b26c8bc3fec6e7f68a291d4e6124fc41680c15e5204a1217d6331d5c097cdf91
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bce52224114636c4a330ebcdd6740409add46791789544e42cd04380d080056d5b9dddabe8ad0a4a395448958c23631702c05864b3617d3e4ee9fe9eda616b3b
|
|
7
|
+
data.tar.gz: fa998fbf3213fabd004a58e4d709fd05f28eee1951b9efef4c7c9ccc17fcf903af73d8e9cf7e0345569b774c8369f6422cdf4f018cd7ca1dc92e5126f0730aa8
|
data/README.md
CHANGED
|
@@ -54,7 +54,7 @@ Connect to your Google account. Opens a browser for OAuth authentication when no
|
|
|
54
54
|
flycal login
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
If already connected, the command reports the current status and suggests running `flycal
|
|
57
|
+
If already connected, the command reports the current status and suggests running `flycal config` to set the default calendar.
|
|
58
58
|
|
|
59
59
|
### logout
|
|
60
60
|
|
|
@@ -64,14 +64,55 @@ Disconnect from your Google account and remove stored tokens.
|
|
|
64
64
|
flycal logout
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
### update
|
|
68
|
+
|
|
69
|
+
Update `flycal-cli` to the latest published gem version.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
flycal update
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### version
|
|
76
|
+
|
|
77
|
+
Show the current installed `flycal-cli` version.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
flycal version
|
|
81
|
+
flycal --version
|
|
82
|
+
flycal -v
|
|
83
|
+
```
|
|
84
|
+
|
|
67
85
|
### calendars
|
|
68
86
|
|
|
69
|
-
List available calendars
|
|
87
|
+
List available calendars with name and ID.
|
|
70
88
|
|
|
71
89
|
```bash
|
|
72
90
|
flycal calendars
|
|
73
91
|
```
|
|
74
92
|
|
|
93
|
+
Example output:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
Work user@example.com
|
|
97
|
+
Personal user@gmail.com
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### config
|
|
101
|
+
|
|
102
|
+
Interactive configuration menu.
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
flycal config
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Options:
|
|
109
|
+
|
|
110
|
+
- `calendar_default` — choose the default calendar and save it to `~/.flycal/config.yml`
|
|
111
|
+
- `exclude_calendars` — multi-select one or more calendars whose events block free slots (default selection includes the current default calendar)
|
|
112
|
+
- `edit config` — open `~/.flycal/config.yml` with `$EDITOR` (or `vi`)
|
|
113
|
+
|
|
114
|
+
Press Ctrl+C during configuration to cancel without error (`config cancelled...`).
|
|
115
|
+
|
|
75
116
|
The default calendar is used by the search command when no calendar is specified.
|
|
76
117
|
|
|
77
118
|
### search
|
|
@@ -90,7 +131,7 @@ flycal search -i 2months -d placeholder
|
|
|
90
131
|
- `--from` / `-f` — Start date/time. Default: midnight of current day. Format: `2025-01-01` or `2025-01-01T09:00`
|
|
91
132
|
- `--to` / `-t` — End date/time. Default: 23:59 of the 30th day from today. Format: same as `--from`
|
|
92
133
|
- `--in` / `-i` — Duration from `--from`, overrides `--to`. Format: `30days`, `48hours`, `2months`, `1year` (no space). With space use quotes: `--in "30 days"`
|
|
93
|
-
- `--calendar` / `-c` — Calendar name or ID. Default: calendar set via `flycal
|
|
134
|
+
- `--calendar` / `-c` — Calendar name or ID. Default: calendar set via `flycal config`
|
|
94
135
|
- `--description` / `-d` — Filter events by text. Matches events where the string appears in title or description (case-insensitive, contains)
|
|
95
136
|
|
|
96
137
|
**Time range behavior:**
|
|
@@ -124,24 +165,28 @@ flycal slots --in "48 hours" --duration 1hour -c Work
|
|
|
124
165
|
|
|
125
166
|
- `--duration` — Minimum slot length. Examples: `1h`, `1 hour`, `30 minutes`, `90min`
|
|
126
167
|
- `--in` / `-i` — Search window from now. Examples: `3 days`, `1 week`, `48 hours` (use quotes when the value contains a space)
|
|
127
|
-
- `--calendar` / `-c` — Calendar name or ID
|
|
168
|
+
- `--calendar` / `-c` — Calendar name or ID used as fallback when `exclude_calendars` is not configured
|
|
128
169
|
|
|
129
170
|
Slot search windows are configured in `~/.flycal/config.yml`:
|
|
130
171
|
|
|
131
172
|
```yaml
|
|
132
173
|
slots:
|
|
174
|
+
exclude_calendars:
|
|
175
|
+
- user@example.com
|
|
176
|
+
- user@gmail.com
|
|
133
177
|
workhours:
|
|
134
178
|
- 9:30-13:00
|
|
135
179
|
- 14:00-18:30
|
|
136
|
-
|
|
180
|
+
weekdays_only: true
|
|
137
181
|
locale: en
|
|
138
182
|
```
|
|
139
183
|
|
|
140
184
|
Missing keys are filled from `config/defaults.yml` in the gem and saved to your `config.yml` on first read.
|
|
141
185
|
|
|
186
|
+
- `exclude_calendars` lists calendars whose events block free slots; if empty or not set, events from `calendar_default` are used
|
|
142
187
|
- `workhours` accepts one or more ranges (`H-H`, `HH:MM-HH:MM`, mixed)
|
|
143
|
-
- `
|
|
144
|
-
- `
|
|
188
|
+
- `weekdays_only: true` limits slots to Monday-Friday
|
|
189
|
+
- `weekdays_only: false` includes weekends
|
|
145
190
|
- `locale` supports `en` and `it` (default is `en`)
|
|
146
191
|
|
|
147
192
|
**Output example:**
|
data/config/defaults.yml
CHANGED
data/lib/flycal_cli/cli.rb
CHANGED
|
@@ -23,7 +23,7 @@ module FlycalCli
|
|
|
23
23
|
apply_locale_override
|
|
24
24
|
if Auth.logged_in?
|
|
25
25
|
puts "✓ You are already connected to your Google account."
|
|
26
|
-
puts "\nRun 'flycal
|
|
26
|
+
puts "\nRun 'flycal config' to set the default calendar."
|
|
27
27
|
return
|
|
28
28
|
end
|
|
29
29
|
|
|
@@ -41,7 +41,7 @@ module FlycalCli
|
|
|
41
41
|
begin
|
|
42
42
|
Auth.login
|
|
43
43
|
puts "\n✓ Authentication completed successfully!"
|
|
44
|
-
puts "\nRun 'flycal
|
|
44
|
+
puts "\nRun 'flycal config' to set the default calendar."
|
|
45
45
|
rescue FlycalCli::Error => e
|
|
46
46
|
puts "Error: #{e.message}"
|
|
47
47
|
exit 1
|
|
@@ -60,49 +60,51 @@ module FlycalCli
|
|
|
60
60
|
puts "✓ Disconnected successfully."
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
desc "calendars", "List available calendars
|
|
63
|
+
desc "calendars", "List available calendars"
|
|
64
64
|
def calendars
|
|
65
65
|
apply_locale_override
|
|
66
66
|
unless Auth.logged_in?
|
|
67
|
-
puts "
|
|
67
|
+
puts Locale.t("errors.not_connected")
|
|
68
68
|
exit 1
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
spinner = TTY::Spinner.new("Loading calendars... ", format: :dots)
|
|
75
|
-
spinner.auto_spin
|
|
76
|
-
calendars = service.list_calendars
|
|
77
|
-
spinner.stop("✓")
|
|
71
|
+
calendars = load_calendars
|
|
72
|
+
return if calendars.nil?
|
|
78
73
|
|
|
79
|
-
|
|
80
|
-
puts "No calendars found."
|
|
81
|
-
return
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# Build selection list (display => calendar_id)
|
|
85
|
-
default_id = Config.calendar_default
|
|
86
|
-
choices = calendars.to_h do |cal|
|
|
87
|
-
primary = cal.primary ? " (primary)" : ""
|
|
88
|
-
default = (cal.id == default_id) ? " [default]" : ""
|
|
74
|
+
calendars.each do |cal|
|
|
89
75
|
summary = cal.summary || cal.id
|
|
90
|
-
|
|
91
|
-
[label, cal.id]
|
|
76
|
+
puts "#{summary} #{cal.id}"
|
|
92
77
|
end
|
|
78
|
+
end
|
|
93
79
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
80
|
+
desc "config", "Configure flycal settings"
|
|
81
|
+
def config
|
|
82
|
+
apply_locale_override
|
|
83
|
+
unless Auth.logged_in?
|
|
84
|
+
puts Locale.t("errors.not_connected")
|
|
85
|
+
exit 1
|
|
86
|
+
end
|
|
101
87
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
88
|
+
with_config_interrupt_handling do
|
|
89
|
+
prompt = TTY::Prompt.new
|
|
90
|
+
choice = prompt.select(
|
|
91
|
+
Locale.t("config.prompt"),
|
|
92
|
+
{
|
|
93
|
+
Locale.t("config.options.calendar_default") => :calendar_default,
|
|
94
|
+
Locale.t("config.options.exclude_calendars") => :exclude_calendars,
|
|
95
|
+
Locale.t("config.options.edit_config") => :edit_config
|
|
96
|
+
},
|
|
97
|
+
per_page: 10
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
case choice
|
|
101
|
+
when :calendar_default
|
|
102
|
+
config_calendar_default
|
|
103
|
+
when :exclude_calendars
|
|
104
|
+
config_exclude_calendars
|
|
105
|
+
when :edit_config
|
|
106
|
+
config_edit
|
|
107
|
+
end
|
|
106
108
|
end
|
|
107
109
|
end
|
|
108
110
|
|
|
@@ -198,7 +200,7 @@ module FlycalCli
|
|
|
198
200
|
time_max = DurationParser.add_to_time(options[:in], time_min)
|
|
199
201
|
slot_cfg = Config.slots_config
|
|
200
202
|
workhours = parse_workhours(slot_cfg["workhours"])
|
|
201
|
-
weekdays_only = !!slot_cfg["
|
|
203
|
+
weekdays_only = !!slot_cfg["weekdays_only"]
|
|
202
204
|
rescue FlycalCli::Error => e
|
|
203
205
|
puts "Error: #{e.message}"
|
|
204
206
|
exit 1
|
|
@@ -212,17 +214,22 @@ module FlycalCli
|
|
|
212
214
|
creds = Auth.credentials
|
|
213
215
|
service = CalendarService.new(creds)
|
|
214
216
|
|
|
215
|
-
|
|
216
|
-
if
|
|
217
|
+
exclude_calendar_ids = resolve_slots_exclude_calendar_ids(service, slot_cfg, options[:calendar])
|
|
218
|
+
if exclude_calendar_ids.empty?
|
|
217
219
|
puts Locale.t("slots.no_calendar")
|
|
218
220
|
exit 1
|
|
219
221
|
end
|
|
220
222
|
|
|
221
|
-
events =
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
223
|
+
events = exclude_calendar_ids.flat_map do |calendar_id|
|
|
224
|
+
service.list_events(
|
|
225
|
+
calendar_id,
|
|
226
|
+
time_min: time_min,
|
|
227
|
+
time_max: time_max
|
|
228
|
+
)
|
|
229
|
+
rescue Google::Apis::Errors::Error => e
|
|
230
|
+
warn Locale.t("errors.calendar_fetch", calendar: calendar_id, message: e.message)
|
|
231
|
+
[]
|
|
232
|
+
end
|
|
226
233
|
|
|
227
234
|
finder = SlotFinder.new(
|
|
228
235
|
events: events,
|
|
@@ -237,6 +244,23 @@ module FlycalCli
|
|
|
237
244
|
puts output.empty? ? Locale.t("slots.no_available") : output
|
|
238
245
|
end
|
|
239
246
|
|
|
247
|
+
desc "update", "Update flycal-cli to the latest gem version"
|
|
248
|
+
def update
|
|
249
|
+
apply_locale_override
|
|
250
|
+
puts "Updating flycal-cli..."
|
|
251
|
+
success = system("gem", "update", "flycal-cli")
|
|
252
|
+
return if success
|
|
253
|
+
|
|
254
|
+
puts "Error: failed to update flycal-cli."
|
|
255
|
+
exit 1
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
desc "version", "Show current flycal-cli version"
|
|
259
|
+
def version
|
|
260
|
+
apply_locale_override
|
|
261
|
+
puts "flycal #{FlycalCli::VERSION}"
|
|
262
|
+
end
|
|
263
|
+
|
|
240
264
|
default_task :help
|
|
241
265
|
|
|
242
266
|
private
|
|
@@ -247,10 +271,154 @@ module FlycalCli
|
|
|
247
271
|
"\e[1m#{str}\e[0m"
|
|
248
272
|
end
|
|
249
273
|
|
|
274
|
+
def bold_underline(str)
|
|
275
|
+
"\e[1;4m#{str}\e[0m"
|
|
276
|
+
end
|
|
277
|
+
|
|
250
278
|
def apply_locale_override
|
|
251
279
|
Locale.override!(options[:locale])
|
|
252
280
|
end
|
|
253
281
|
|
|
282
|
+
def with_config_interrupt_handling
|
|
283
|
+
yield
|
|
284
|
+
rescue Interrupt
|
|
285
|
+
puts "\nconfig cancelled..."
|
|
286
|
+
exit 0
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def load_calendars
|
|
290
|
+
creds = Auth.credentials
|
|
291
|
+
service = CalendarService.new(creds)
|
|
292
|
+
|
|
293
|
+
spinner = TTY::Spinner.new("#{Locale.t('common.loading_calendars')} ", format: :dots)
|
|
294
|
+
spinner.auto_spin
|
|
295
|
+
calendars = service.list_calendars
|
|
296
|
+
spinner.stop("✓")
|
|
297
|
+
|
|
298
|
+
if calendars.empty?
|
|
299
|
+
puts Locale.t("errors.no_calendars")
|
|
300
|
+
return nil
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
calendars
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def calendar_choices(calendars, highlight_ids: [])
|
|
307
|
+
highlights = Array(highlight_ids).compact
|
|
308
|
+
calendars.to_h do |cal|
|
|
309
|
+
primary = cal.primary ? " (primary)" : ""
|
|
310
|
+
summary = cal.summary || cal.id
|
|
311
|
+
label = "#{summary}#{primary}"
|
|
312
|
+
label = bold_underline(label) if highlights.include?(cal.id)
|
|
313
|
+
[label, cal.id]
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def choice_labels_for_ids(choices, calendar_ids)
|
|
318
|
+
ids = Array(calendar_ids).compact
|
|
319
|
+
choices.select { |_label, id| ids.include?(id) }.keys
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def config_calendar_default
|
|
323
|
+
calendars = load_calendars
|
|
324
|
+
return if calendars.nil?
|
|
325
|
+
|
|
326
|
+
prompt = TTY::Prompt.new
|
|
327
|
+
default_id = Config.calendar_default
|
|
328
|
+
selected_id = prompt.select(
|
|
329
|
+
Locale.t("config.calendar_default.prompt"),
|
|
330
|
+
calendar_choices(calendars, highlight_ids: [default_id]),
|
|
331
|
+
per_page: 15,
|
|
332
|
+
filter: true
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
calendar = calendars.find { |c| c.id == selected_id }
|
|
336
|
+
return unless calendar
|
|
337
|
+
|
|
338
|
+
Config.calendar_default = calendar.id
|
|
339
|
+
puts Locale.t("config.calendar_default.saved", name: calendar.summary || calendar.id)
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def config_exclude_calendars
|
|
343
|
+
calendars = load_calendars
|
|
344
|
+
return if calendars.nil?
|
|
345
|
+
|
|
346
|
+
prompt = TTY::Prompt.new
|
|
347
|
+
default_id = Config.calendar_default
|
|
348
|
+
configured = Config.exclude_calendars
|
|
349
|
+
current_ids = resolve_calendar_refs(calendars, configured)
|
|
350
|
+
preselected_ids = current_ids.empty? && default_id ? [default_id] : current_ids
|
|
351
|
+
choices = calendar_choices(calendars, highlight_ids: current_ids)
|
|
352
|
+
preselected_labels = choice_labels_for_ids(choices, preselected_ids)
|
|
353
|
+
|
|
354
|
+
selected_ids = prompt.multi_select(
|
|
355
|
+
Locale.t("config.exclude_calendars.prompt"),
|
|
356
|
+
choices,
|
|
357
|
+
default: preselected_labels,
|
|
358
|
+
min: 1,
|
|
359
|
+
per_page: 15,
|
|
360
|
+
filter: true
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
Config.exclude_calendars = selected_ids
|
|
364
|
+
names = selected_ids.map do |id|
|
|
365
|
+
calendars.find { |c| c.id == id }&.summary || id
|
|
366
|
+
end
|
|
367
|
+
puts Locale.t("config.exclude_calendars.saved", names: names.join(", "))
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
def config_edit
|
|
371
|
+
editor = ENV["EDITOR"].to_s.strip
|
|
372
|
+
editor = "vi" if editor.empty?
|
|
373
|
+
|
|
374
|
+
success = system(editor, Config.config_file)
|
|
375
|
+
puts Locale.t("config.edit.failed", editor: editor) unless success
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
def resolve_calendar_refs(calendars, refs)
|
|
379
|
+
Array(refs).filter_map do |ref|
|
|
380
|
+
resolve_calendar_ref(calendars, ref)
|
|
381
|
+
end.uniq
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def resolve_calendar_ref(calendars, ref)
|
|
385
|
+
ref = ref.to_s.strip
|
|
386
|
+
return nil if ref.empty?
|
|
387
|
+
|
|
388
|
+
exact = calendars.find { |cal| cal.id == ref }
|
|
389
|
+
return exact.id if exact
|
|
390
|
+
|
|
391
|
+
matches = calendars.select do |cal|
|
|
392
|
+
cal.id == ref ||
|
|
393
|
+
(cal.summary && cal.summary.downcase.include?(ref.downcase))
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
matches.first&.id
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
def resolve_slots_exclude_calendar_ids(service, slot_cfg, calendar_override)
|
|
400
|
+
configured = slot_cfg["exclude_calendars"]
|
|
401
|
+
calendars = service.list_calendars
|
|
402
|
+
|
|
403
|
+
refs = if configured.nil? || (configured.is_a?(Array) && configured.empty?)
|
|
404
|
+
fallback = calendar_override || Config.calendar_default
|
|
405
|
+
fallback ? [fallback] : []
|
|
406
|
+
else
|
|
407
|
+
configured
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
ids = resolve_calendar_refs(calendars, refs)
|
|
411
|
+
return ids unless ids.empty?
|
|
412
|
+
|
|
413
|
+
fallback = calendar_override || Config.calendar_default
|
|
414
|
+
if fallback
|
|
415
|
+
resolve_calendar_refs(calendars, [fallback])
|
|
416
|
+
else
|
|
417
|
+
primary = calendars.find(&:primary)
|
|
418
|
+
primary ? [primary.id] : calendars.first(1).map(&:id)
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
|
|
254
422
|
def parse_datetime(str, end_of_day: false)
|
|
255
423
|
return nil if str.nil? || str.empty?
|
|
256
424
|
|
|
@@ -354,22 +522,6 @@ module FlycalCli
|
|
|
354
522
|
matches.map(&:id)
|
|
355
523
|
end
|
|
356
524
|
|
|
357
|
-
def resolve_single_calendar_id(service, calendar_name)
|
|
358
|
-
if calendar_name && !calendar_name.empty?
|
|
359
|
-
ids = resolve_calendar_ids(service, calendar_name)
|
|
360
|
-
return ids.first
|
|
361
|
-
end
|
|
362
|
-
|
|
363
|
-
default_id = Config.calendar_default
|
|
364
|
-
return default_id if default_id
|
|
365
|
-
|
|
366
|
-
calendars = service.list_calendars
|
|
367
|
-
primary = calendars.find(&:primary)
|
|
368
|
-
return primary.id if primary
|
|
369
|
-
|
|
370
|
-
calendars.first&.id
|
|
371
|
-
end
|
|
372
|
-
|
|
373
525
|
def print_events(service, events)
|
|
374
526
|
# Use calendar list for names (avoids extra API calls)
|
|
375
527
|
calendar_list = service.list_calendars
|
data/lib/flycal_cli/config.rb
CHANGED
|
@@ -20,7 +20,8 @@ module FlycalCli
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
merged, changed = merge_missing_defaults(user_data, default_values)
|
|
23
|
-
|
|
23
|
+
merged, migrated = normalize_slots_keys(merged)
|
|
24
|
+
save(merged) if changed || migrated || !File.exist?(CONFIG_FILE)
|
|
24
25
|
|
|
25
26
|
merged
|
|
26
27
|
end
|
|
@@ -64,6 +65,45 @@ module FlycalCli
|
|
|
64
65
|
load.fetch("slots", {})
|
|
65
66
|
end
|
|
66
67
|
|
|
68
|
+
def exclude_calendars
|
|
69
|
+
Array(slots_config["exclude_calendars"]).map(&:to_s).reject(&:empty?)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def exclude_calendars=(calendar_ids)
|
|
73
|
+
data = load
|
|
74
|
+
data["slots"] ||= {}
|
|
75
|
+
data["slots"]["exclude_calendars"] = Array(calendar_ids).map(&:to_s)
|
|
76
|
+
save(data)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def normalize_slots_keys(data)
|
|
80
|
+
slots = data["slots"]
|
|
81
|
+
return [data, false] unless slots.is_a?(Hash)
|
|
82
|
+
|
|
83
|
+
changed = false
|
|
84
|
+
normalized = slots.dup
|
|
85
|
+
|
|
86
|
+
if normalized.key?("exclude-calendars") && !normalized.key?("exclude_calendars")
|
|
87
|
+
normalized["exclude_calendars"] = normalized.delete("exclude-calendars")
|
|
88
|
+
changed = true
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
if normalized.key?("weekdays-only") && !normalized.key?("weekdays_only")
|
|
92
|
+
normalized["weekdays_only"] = normalized.delete("weekdays-only")
|
|
93
|
+
changed = true
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
return [data, false] unless changed
|
|
97
|
+
|
|
98
|
+
data = data.dup
|
|
99
|
+
data["slots"] = normalized
|
|
100
|
+
[data, true]
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def config_file
|
|
104
|
+
CONFIG_FILE
|
|
105
|
+
end
|
|
106
|
+
|
|
67
107
|
def locale
|
|
68
108
|
load["locale"].to_s
|
|
69
109
|
end
|
data/lib/flycal_cli/version.rb
CHANGED
data/locales/en.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
|
+
"loading_calendars": "Loading calendars...",
|
|
3
4
|
"weekdays": {
|
|
4
5
|
"full": ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"],
|
|
5
6
|
"abbr": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
|
|
@@ -8,12 +9,33 @@
|
|
|
8
9
|
"full": ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
|
|
9
10
|
}
|
|
10
11
|
},
|
|
12
|
+
"config": {
|
|
13
|
+
"prompt": "Choose a configuration option:",
|
|
14
|
+
"options": {
|
|
15
|
+
"calendar_default": "calendar_default",
|
|
16
|
+
"exclude_calendars": "exclude_calendars",
|
|
17
|
+
"edit_config": "edit config"
|
|
18
|
+
},
|
|
19
|
+
"calendar_default": {
|
|
20
|
+
"prompt": "Choose the default calendar:",
|
|
21
|
+
"saved": "✓ Default calendar set to: %{name}"
|
|
22
|
+
},
|
|
23
|
+
"exclude_calendars": {
|
|
24
|
+
"prompt": "Choose calendars whose events block free slots:",
|
|
25
|
+
"saved": "✓ Exclude calendars set to: %{names}"
|
|
26
|
+
},
|
|
27
|
+
"edit": {
|
|
28
|
+
"failed": "Error: could not open config with %{editor}."
|
|
29
|
+
}
|
|
30
|
+
},
|
|
11
31
|
"slots": {
|
|
12
32
|
"no_available": "No available slots found.",
|
|
13
|
-
"no_calendar": "No calendar found. Run 'flycal
|
|
33
|
+
"no_calendar": "No calendar found. Run 'flycal config' to set a default."
|
|
14
34
|
},
|
|
15
35
|
"errors": {
|
|
16
36
|
"not_connected": "You are not connected. Run 'flycal login' first.",
|
|
17
|
-
"duration_positive": "Error: --in must be a positive duration."
|
|
37
|
+
"duration_positive": "Error: --in must be a positive duration.",
|
|
38
|
+
"no_calendars": "No calendars found.",
|
|
39
|
+
"calendar_fetch": "Error in calendar %{calendar}: %{message}"
|
|
18
40
|
}
|
|
19
41
|
}
|
data/locales/it.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
|
+
"loading_calendars": "Caricamento calendari...",
|
|
3
4
|
"weekdays": {
|
|
4
5
|
"full": ["domenica", "lunedi", "martedi", "mercoledi", "giovedi", "venerdi", "sabato"],
|
|
5
6
|
"abbr": ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"]
|
|
@@ -8,12 +9,33 @@
|
|
|
8
9
|
"full": ["gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno", "luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre"]
|
|
9
10
|
}
|
|
10
11
|
},
|
|
12
|
+
"config": {
|
|
13
|
+
"prompt": "Scegli un'opzione di configurazione:",
|
|
14
|
+
"options": {
|
|
15
|
+
"calendar_default": "calendar_default",
|
|
16
|
+
"exclude_calendars": "exclude_calendars",
|
|
17
|
+
"edit_config": "edit config"
|
|
18
|
+
},
|
|
19
|
+
"calendar_default": {
|
|
20
|
+
"prompt": "Scegli il calendario predefinito:",
|
|
21
|
+
"saved": "✓ Calendario predefinito impostato su: %{name}"
|
|
22
|
+
},
|
|
23
|
+
"exclude_calendars": {
|
|
24
|
+
"prompt": "Scegli i calendari i cui eventi bloccano gli slot liberi:",
|
|
25
|
+
"saved": "✓ Calendari esclusi impostati su: %{names}"
|
|
26
|
+
},
|
|
27
|
+
"edit": {
|
|
28
|
+
"failed": "Errore: impossibile aprire il config con %{editor}."
|
|
29
|
+
}
|
|
30
|
+
},
|
|
11
31
|
"slots": {
|
|
12
32
|
"no_available": "Nessuno slot disponibile.",
|
|
13
|
-
"no_calendar": "Nessun calendario trovato. Esegui 'flycal
|
|
33
|
+
"no_calendar": "Nessun calendario trovato. Esegui 'flycal config' per impostare il predefinito."
|
|
14
34
|
},
|
|
15
35
|
"errors": {
|
|
16
36
|
"not_connected": "Non sei connesso. Esegui prima 'flycal login'.",
|
|
17
|
-
"duration_positive": "Errore: --in deve essere una durata positiva."
|
|
37
|
+
"duration_positive": "Errore: --in deve essere una durata positiva.",
|
|
38
|
+
"no_calendars": "Nessun calendario trovato.",
|
|
39
|
+
"calendar_fetch": "Errore nel calendario %{calendar}: %{message}"
|
|
18
40
|
}
|
|
19
41
|
}
|