norcal 1.2.0 → 1.4.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 +3 -2
- data/bin/norcal +99 -55
- 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: 9be7e8ddb9dd50827b5f06ebb3df0f77198839e50e243fe2a5afe2b9c3013de4
|
|
4
|
+
data.tar.gz: f4c4991791a1cfffe455411d4c08534f4f65a60539cf9ee01dd43f1084ab70e0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 39d0619b9c32fad49beeb6f720d7776c11e5238c4d85ac19d0a642aadf749b8196174b8e64be1bc5f37a585edb44a6db3369102e9f54a89be333593cc0694df9
|
|
7
|
+
data.tar.gz: 7f4cc6f41397632c34854ecee9cbbe24eccde9bc0dc6ca3741891ba161c78af61968fcf286b3a1b9e9f32806bb0891b1f681e91085923fb499675d020fae6dcf
|
data/README.md
CHANGED
|
@@ -31,7 +31,7 @@ gem install norcal
|
|
|
31
31
|
git clone https://github.com/baosen/norcal.git
|
|
32
32
|
cd norcal
|
|
33
33
|
gem build norcal.gemspec
|
|
34
|
-
gem install norcal-1.
|
|
34
|
+
gem install norcal-1.4.0.gem
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
## Usage
|
|
@@ -49,7 +49,8 @@ norcal --light 2026 # light mode, specific year
|
|
|
49
49
|
- ISO week numbers, Monday-first weeks
|
|
50
50
|
- Sundays and public holidays in red, Saturdays in gray
|
|
51
51
|
- Easter-based movable holidays (Computus algorithm)
|
|
52
|
-
- Notable dates: royal birthdays, Samefolkets dag, Morsdag, Farsdag, solverv, sommertid, and more
|
|
52
|
+
- Notable dates: royal birthdays, Samefolkets dag, Morsdag, Farsdag, solverv, sommertid, advent, and more
|
|
53
|
+
- Filter to show only red days (public holidays)
|
|
53
54
|
- Today highlighted with yellow background
|
|
54
55
|
- Dark mode (default) and light mode, with toggle button
|
|
55
56
|
- Zoom in/out (`+`/`–` buttons, Ctrl+scroll, Ctrl++/Ctrl+-)
|
data/bin/norcal
CHANGED
|
@@ -61,14 +61,14 @@ end
|
|
|
61
61
|
def red_days(year)
|
|
62
62
|
e = easter(year)
|
|
63
63
|
{
|
|
64
|
-
Date.new(year, 1, 1) => "
|
|
64
|
+
Date.new(year, 1, 1) => "Første nyttårsdag",
|
|
65
65
|
e - 3 => "Skjærtorsdag",
|
|
66
66
|
e - 2 => "Langfredag",
|
|
67
67
|
e => "1. påskedag",
|
|
68
68
|
e + 1 => "2. påskedag",
|
|
69
69
|
Date.new(year, 5, 1) => "Arbeidernes dag",
|
|
70
|
-
e + 39 => "
|
|
71
|
-
Date.new(year, 5, 17) => "
|
|
70
|
+
e + 39 => "Kristi himmelfartsdag",
|
|
71
|
+
Date.new(year, 5, 17) => "Grunnlovsdagen",
|
|
72
72
|
e + 49 => "1. pinsedag",
|
|
73
73
|
e + 50 => "2. pinsedag",
|
|
74
74
|
Date.new(year, 12, 25) => "1. juledag",
|
|
@@ -77,55 +77,75 @@ def red_days(year)
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
# Notable dates: [date, description, show_date_in_red?]
|
|
80
|
+
# Red days are auto-included from red_days(); some get extra context in the
|
|
81
|
+
# notable_names override below.
|
|
80
82
|
def notable_dates(year)
|
|
81
83
|
e = easter(year)
|
|
84
|
+
holidays = red_days(year)
|
|
85
|
+
|
|
82
86
|
morsdag = nth_wday(year, 2, 7, 2)
|
|
83
87
|
farsdag = nth_wday(year, 11, 7, 2)
|
|
84
88
|
sommer_start = last_wday(year, 3, 7)
|
|
85
89
|
sommer_slutt = last_wday(year, 10, 7)
|
|
86
90
|
fastelavn = e - 49
|
|
91
|
+
botsdag = last_wday(year, 10, 7)
|
|
87
92
|
nov27 = Date.new(year, 11, 27)
|
|
88
93
|
advent1 = nov27 + ((7 - nov27.cwday) % 7)
|
|
89
94
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
[
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
[e,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
[Date.new(year,
|
|
109
|
-
[
|
|
110
|
-
[
|
|
111
|
-
[Date.new(year,
|
|
112
|
-
[
|
|
113
|
-
[Date.new(year,
|
|
114
|
-
[Date.new(year,
|
|
115
|
-
[Date.new(year,
|
|
116
|
-
[
|
|
117
|
-
[
|
|
118
|
-
[Date.new(year,
|
|
119
|
-
[
|
|
120
|
-
[Date.new(year,
|
|
121
|
-
[Date.new(year,
|
|
122
|
-
[
|
|
123
|
-
[
|
|
124
|
-
[Date.new(year,
|
|
125
|
-
[Date.new(year,
|
|
126
|
-
[Date.new(year,
|
|
127
|
-
[Date.new(year,
|
|
128
|
-
|
|
95
|
+
# Override display names for some red days in the notable list
|
|
96
|
+
notable_names = {
|
|
97
|
+
e + 39 => "Kristi himmelfartsdag",
|
|
98
|
+
Date.new(year, 5, 17) => "Grunnlovsdagen 1814",
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
# Start with all red days
|
|
102
|
+
entries = holidays.map { |date, name|
|
|
103
|
+
[date, notable_names[date] || name, true]
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
# Red-in-list but not a public holiday
|
|
107
|
+
entries += [
|
|
108
|
+
[e - 7, "Palmesøndag", true],
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
# Non-red notable dates
|
|
112
|
+
entries += [
|
|
113
|
+
[Date.new(year, 1, 21), "Prinsesse Ingrid Alexandra, #{year - 2004} år"],
|
|
114
|
+
[Date.new(year, 2, 6), "Samefolkets dag"],
|
|
115
|
+
[morsdag, "Morsdag"],
|
|
116
|
+
[Date.new(year, 2, 14), "Valentinsdag"],
|
|
117
|
+
[fastelavn, "Fastelavn"],
|
|
118
|
+
[Date.new(year, 2, 21), "Kong Harald, #{year - 1937} år"],
|
|
119
|
+
[Date.new(year, 3, 8), "Kvinnedagen"],
|
|
120
|
+
[Date.new(year, 3, 20), "Vårjevndøgn"],
|
|
121
|
+
[sommer_start, "Sommertid start"],
|
|
122
|
+
[e - 1, "Påskeaften"],
|
|
123
|
+
[Date.new(year, 5, 8), "Frigjøringsdagen 1945"],
|
|
124
|
+
[e + 48, "Pinseaften"],
|
|
125
|
+
[Date.new(year, 6, 7), "Unionsoppløsning 1905"],
|
|
126
|
+
[Date.new(year, 6, 21), "Sommersolverv"],
|
|
127
|
+
[Date.new(year, 6, 23), "Sankthansaften"],
|
|
128
|
+
[Date.new(year, 7, 4), "Dronning Sonja, #{year - 1937} år"],
|
|
129
|
+
[Date.new(year, 7, 20), "Kronprins Haakon, #{year - 1973} år"],
|
|
130
|
+
[Date.new(year, 7, 29), "Olsokdagen"],
|
|
131
|
+
[Date.new(year, 8, 19), "Kronprinsesse Mette-Marit, #{year - 1973} år"],
|
|
132
|
+
[Date.new(year, 9, 23), "Høstjevndøgn"],
|
|
133
|
+
[botsdag, "Bots- og bededag"],
|
|
134
|
+
[sommer_slutt, "Sommertid slutt"],
|
|
135
|
+
[Date.new(year, 10, 31), "Halloween"],
|
|
136
|
+
[Date.new(year, 11, 1), "Allehelgensdag"],
|
|
137
|
+
[farsdag, "Farsdag"],
|
|
138
|
+
[advent1, "1. søndag i advent"],
|
|
139
|
+
[advent1 + 7, "2. søndag i advent"],
|
|
140
|
+
[Date.new(year, 12, 13), "Luciadagen"],
|
|
141
|
+
[advent1 + 14, "3. søndag i advent"],
|
|
142
|
+
[advent1 + 21, "4. søndag i advent"],
|
|
143
|
+
[Date.new(year, 12, 21), "Vintersolverv"],
|
|
144
|
+
[Date.new(year, 12, 24), "Julaften"],
|
|
145
|
+
[Date.new(year, 12, 31), "Nyttårsaften"],
|
|
146
|
+
].map { |date, name| [date, name, false] }
|
|
147
|
+
|
|
148
|
+
entries.sort_by { |d, _, _| d }
|
|
129
149
|
end
|
|
130
150
|
|
|
131
151
|
# -- GUI -----------------------------------------------------------------------
|
|
@@ -149,6 +169,7 @@ THEME = {
|
|
|
149
169
|
$dark = ARGV.delete('--light') ? false : true
|
|
150
170
|
$year = (ARGV[0] || Date.today.year).to_i
|
|
151
171
|
$zoom = 0
|
|
172
|
+
$red_only = false
|
|
152
173
|
|
|
153
174
|
def theme
|
|
154
175
|
THEME[$dark ? :dark : :light]
|
|
@@ -179,7 +200,8 @@ end
|
|
|
179
200
|
# All trackable widgets, grouped by update type.
|
|
180
201
|
# Labels store {w: widget, fg: theme_key, bg: theme_key, font: font_key}.
|
|
181
202
|
# Buttons store {w: widget, fg: theme_key, text_key: theme_key or nil, text: static}.
|
|
182
|
-
$w
|
|
203
|
+
$w = { bg: [], border: [], sep: [], labels: [], texts: [], buttons: [] }
|
|
204
|
+
$wn = { bg: [], border: [], sep: [], texts: [] } # notable-only (rebuilt on filter)
|
|
183
205
|
|
|
184
206
|
# Apply current theme + zoom to all tracked widgets (no widget recreation).
|
|
185
207
|
def restyle
|
|
@@ -191,15 +213,15 @@ def restyle
|
|
|
191
213
|
$scrollbar.configure(background: t[:bg], troughcolor: t[:bg])
|
|
192
214
|
$root.title = "Kalender #{$year}"
|
|
193
215
|
|
|
194
|
-
$w[:bg].each
|
|
195
|
-
$w[:border].each { |w| w.configure(background: t[:bg], highlightbackground: t[:border]) }
|
|
196
|
-
$w[:sep].each
|
|
216
|
+
($w[:bg] + $wn[:bg]).each { |w| w.configure(background: t[:bg]) }
|
|
217
|
+
($w[:border] + $wn[:border]).each { |w| w.configure(background: t[:bg], highlightbackground: t[:border]) }
|
|
218
|
+
($w[:sep] + $wn[:sep]).each { |w| w.configure(background: t[:sep]) }
|
|
197
219
|
|
|
198
220
|
$w[:labels].each do |e|
|
|
199
221
|
e[:w].configure(foreground: t[e[:fg]], background: t[e[:bg]], font: f[e[:font]])
|
|
200
222
|
end
|
|
201
223
|
|
|
202
|
-
$w[:texts].each do |tw|
|
|
224
|
+
($w[:texts] + $wn[:texts]).each do |tw|
|
|
203
225
|
tab = [65 + $zoom * 4, 40].max
|
|
204
226
|
tw.configure(background: t[:bg], font: f[:note], tabs: tab.to_s)
|
|
205
227
|
tw.tag_configure('dt', foreground: t[:fg], font: f[:note_b])
|
|
@@ -208,7 +230,7 @@ def restyle
|
|
|
208
230
|
end
|
|
209
231
|
|
|
210
232
|
$w[:buttons].each do |e|
|
|
211
|
-
text = e[:text_key] ? t[e[:text_key]] : e[:text]
|
|
233
|
+
text = e[:text_key] ? t[e[:text_key]] : (e[:text].respond_to?(:call) ? e[:text].call : e[:text])
|
|
212
234
|
e[:w].configure(text: text, font: f[:btn], foreground: t[e[:fg]],
|
|
213
235
|
background: t[:bg], activebackground: t[:bg], activeforeground: t[:fg])
|
|
214
236
|
end
|
|
@@ -282,15 +304,18 @@ def build_month(parent, year, month, holidays)
|
|
|
282
304
|
end
|
|
283
305
|
|
|
284
306
|
def build_notable(parent, year)
|
|
307
|
+
$wn.each_value(&:clear)
|
|
308
|
+
|
|
285
309
|
dates = notable_dates(year)
|
|
286
|
-
|
|
310
|
+
dates = dates.select { |_, _, is_red| is_red } if $red_only
|
|
311
|
+
third = [(dates.size / 3.0).ceil, 1].max
|
|
287
312
|
cols = dates.each_slice(third).to_a
|
|
288
313
|
|
|
289
314
|
outer = TkFrame.new(parent) { borderwidth 1; relief 'solid'; highlightthickness 0 }
|
|
290
|
-
$
|
|
315
|
+
$wn[:border] << outer
|
|
291
316
|
|
|
292
317
|
inner = TkFrame.new(outer)
|
|
293
|
-
$
|
|
318
|
+
$wn[:bg] << inner
|
|
294
319
|
inner.pack(padx: 5, pady: 5, fill: 'both')
|
|
295
320
|
|
|
296
321
|
cols.each_with_index do |entries, ci|
|
|
@@ -299,7 +324,7 @@ def build_notable(parent, year)
|
|
|
299
324
|
borderwidth 0; highlightthickness 0
|
|
300
325
|
wrap 'word'; padx 3; pady 2; cursor ''; insertwidth 0
|
|
301
326
|
}
|
|
302
|
-
$
|
|
327
|
+
$wn[:texts] << tw
|
|
303
328
|
|
|
304
329
|
entries.each_with_index do |(date, desc, is_red), i|
|
|
305
330
|
dtag = is_red ? 'dtr' : 'dt'
|
|
@@ -315,13 +340,20 @@ def build_notable(parent, year)
|
|
|
315
340
|
|
|
316
341
|
if ci < cols.size - 1
|
|
317
342
|
sep = TkFrame.new(inner) { width 1 }
|
|
318
|
-
$
|
|
343
|
+
$wn[:sep] << sep
|
|
319
344
|
sep.grid(row: 0, column: ci * 2 + 1, sticky: 'ns', padx: 4)
|
|
320
345
|
end
|
|
321
346
|
end
|
|
322
347
|
outer
|
|
323
348
|
end
|
|
324
349
|
|
|
350
|
+
def rebuild_notable
|
|
351
|
+
$notable_frame&.destroy
|
|
352
|
+
$notable_frame = build_notable($notable_parent, $year)
|
|
353
|
+
$notable_frame.grid(row: 4, column: 0, columnspan: 3, padx: 3, pady: [4, 0], sticky: 'ew')
|
|
354
|
+
restyle
|
|
355
|
+
end
|
|
356
|
+
|
|
325
357
|
def build_buttons(parent)
|
|
326
358
|
btn_bar = TkFrame.new(parent)
|
|
327
359
|
$w[:bg] << btn_bar
|
|
@@ -342,6 +374,17 @@ def build_buttons(parent)
|
|
|
342
374
|
b4 = TkButton.new(btn_bar) { relief 'flat'; borderwidth 0; command { $fit.call(false) } }
|
|
343
375
|
$w[:buttons] << { w: b4, fg: :dkgray, text_key: nil, text: 'fit' }
|
|
344
376
|
b4.pack(side: 'left', padx: 2)
|
|
377
|
+
|
|
378
|
+
b5 = TkButton.new(btn_bar) { relief 'flat'; borderwidth 0
|
|
379
|
+
command {
|
|
380
|
+
$red_only = !$red_only
|
|
381
|
+
rebuild_notable
|
|
382
|
+
restyle # update button text
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
$w[:buttons] << { w: b5, fg: :dkgray, text_key: nil,
|
|
386
|
+
text: -> { $red_only ? 'alle dager' : "bare r\u00f8de dager" } }
|
|
387
|
+
b5.pack(side: 'left', padx: 2)
|
|
345
388
|
end
|
|
346
389
|
|
|
347
390
|
def build_all(year)
|
|
@@ -370,8 +413,9 @@ def build_all(year)
|
|
|
370
413
|
.grid(row: idx / 3, column: idx % 3, padx: 3, pady: 3, sticky: 'nsew')
|
|
371
414
|
end
|
|
372
415
|
|
|
373
|
-
|
|
374
|
-
|
|
416
|
+
$notable_parent = grid_f
|
|
417
|
+
$notable_frame = build_notable(grid_f, year)
|
|
418
|
+
$notable_frame.grid(row: 4, column: 0, columnspan: 3, padx: 3, pady: [4, 0], sticky: 'ew')
|
|
375
419
|
|
|
376
420
|
build_buttons(grid_f)
|
|
377
421
|
3.times { |c| grid_f.grid_columnconfigure(c, weight: 1) }
|