galaaz 2.1.8 → 2.1.9

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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/Rakefile +20 -2
  4. data/bin/check_gemfile_lock_version +46 -0
  5. data/bin/release_bump +26 -0
  6. data/blogs/README.md +4 -0
  7. data/blogs/galaaz_2_0/galaaz_2_0.Rmd +385 -0
  8. data/blogs/galaaz_2_0/galaaz_2_0.md +409 -0
  9. data/blogs/galaaz_2_0/galaaz_2_0.tex +756 -0
  10. data/blogs/galaaz_2_0/images/galaaz-header.png +0 -0
  11. data/blogs/galaaz_2_0/images/galaaz-lockup-stacked.png +0 -0
  12. data/blogs/galaaz_ggplot/galaaz_ggplot.Rmd +14 -1
  13. data/blogs/galaaz_ggplot/galaaz_ggplot.md +123 -103
  14. data/blogs/galaaz_ggplot/galaaz_ggplot.tex +60 -23
  15. data/blogs/galaaz_ggplot/images/galaaz-lockup-stacked.png +0 -0
  16. data/blogs/gknit/gknit.Rmd +16 -1
  17. data/blogs/gknit/gknit.md +13 -1
  18. data/blogs/gknit/gknit.tex +64 -23
  19. data/blogs/gknit/gknit_files/figure-html/bubble-1.png +0 -0
  20. data/blogs/gknit/gknit_files/figure-html/diverging_bar.png +0 -0
  21. data/blogs/gknit/gknit_files/figure-latex/bubble-1.png +0 -0
  22. data/blogs/gknit/images/galaaz-lockup-stacked.png +0 -0
  23. data/blogs/manual/images/galaaz-lockup-stacked.png +0 -0
  24. data/blogs/manual/manual.Rmd +32 -11
  25. data/blogs/manual/manual.md +30 -23
  26. data/blogs/manual/manual.tex +88 -66
  27. data/blogs/manual/manual_files/figure-html/bubble-1.png +0 -0
  28. data/blogs/manual/manual_files/figure-latex/bubble-1.png +0 -0
  29. data/blogs/nse_dplyr/images/galaaz-lockup-stacked.png +0 -0
  30. data/blogs/nse_dplyr/nse_dplyr.Rmd +14 -1
  31. data/blogs/nse_dplyr/nse_dplyr.md +697 -649
  32. data/blogs/nse_dplyr/nse_dplyr.tex +61 -24
  33. data/blogs/oh_my/images/galaaz-lockup-stacked.png +0 -0
  34. data/blogs/oh_my/oh_my.Rmd +14 -1
  35. data/blogs/oh_my/oh_my.md +36 -26
  36. data/blogs/oh_my/oh_my.tex +95 -58
  37. data/blogs/r_on_rails_ledger/images/00_portfolio_page.png +0 -0
  38. data/blogs/r_on_rails_ledger/images/01_results_panel.png +0 -0
  39. data/blogs/r_on_rails_ledger/images/02_density_tail_risk.png +0 -0
  40. data/blogs/r_on_rails_ledger/images/03_mc_cone.png +0 -0
  41. data/blogs/r_on_rails_ledger/images/04_rolling_var.png +0 -0
  42. data/blogs/r_on_rails_ledger/images/galaaz-lockup-stacked.png +0 -0
  43. data/blogs/r_on_rails_ledger/r_on_rails_ledger.Rmd +354 -0
  44. data/blogs/r_on_rails_ledger/r_on_rails_ledger.md +365 -0
  45. data/blogs/r_on_rails_ledger/r_on_rails_ledger.tex +670 -0
  46. data/blogs/ruby_plot/images/galaaz-lockup-stacked.png +0 -0
  47. data/blogs/ruby_plot/ruby_plot.Rmd +14 -1
  48. data/blogs/ruby_plot/ruby_plot.md +11 -1
  49. data/blogs/ruby_plot/ruby_plot.tex +60 -23
  50. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_jitter.png +0 -0
  51. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_violin_plot.png +0 -0
  52. data/blogs/ruby_plot/ruby_plot_files/figure-html/violin_with_jitter.png +0 -0
  53. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_jitter.png +0 -0
  54. data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_violin_plot.png +0 -0
  55. data/blogs/ruby_plot/ruby_plot_files/figure-latex/violin_with_jitter.png +0 -0
  56. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/facets_with_jitter.png +0 -0
  57. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/final_violin_plot.png +0 -0
  58. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/violin_with_jitter.png +0 -0
  59. data/lib/galaaz/cli.rb +47 -3
  60. data/logos/icon-font/README.md +27 -0
  61. data/logos/icon-font/build_font.py +130 -0
  62. data/logos/icon-font/galaaz-mark.svg +34 -0
  63. data/script/omarchy/README.md +8 -1
  64. data/script/omarchy/fonts/galaaz.ttf +0 -0
  65. data/script/omarchy/install-galaaz.sh +8 -1
  66. data/script/omarchy/omarchy-menu.jsonc +21 -9
  67. data/sty/galaaz-header.png +0 -0
  68. data/sty/galaaz-headers-from-p3.tex +4 -0
  69. data/sty/galaaz.sty +54 -23
  70. data/version.rb +1 -1
  71. metadata +30 -9
  72. data/blogs/galaaz_ggplot/galaaz_ggplot.log +0 -745
  73. data/blogs/gknit/gknit_files/gknit_files/figure-latex/bubble-1.png +0 -0
  74. data/blogs/manual/manual.log +0 -1530
  75. data/blogs/manual/manual_files/manual_files/figure-latex/bubble-1.png +0 -0
  76. data/blogs/nse_dplyr/nse_dplyr.log +0 -824
  77. data/blogs/oh_my/oh_my.log +0 -974
  78. data/blogs/ruby_plot/ruby_plot.log +0 -887
@@ -9,9 +9,17 @@ output:
9
9
  html_document:
10
10
  self_contained: true
11
11
  keep_md: true
12
+ toc: true
13
+ toc_float: true
14
+ toc_depth: 2
15
+ number_sections: true
16
+ includes:
17
+ before_body: _logo_before_body.html
12
18
  pdf_document:
13
19
  includes:
14
- in_header: "../../sty/galaaz.sty"
20
+ in_header:
21
+ - "../../sty/galaaz.sty"
22
+ - "../../sty/galaaz-headers-from-p3.tex"
15
23
  keep_tex: yes
16
24
  number_sections: yes
17
25
  toc: true
@@ -27,6 +35,11 @@ options(width = 70)
27
35
  # fig.width = 1, fig.height = 7, dev = "svg", out.width = "50%")
28
36
  ```
29
37
 
38
+ ```{r brand_logo, echo=FALSE, fig.align='center', out.width='45%', eval=knitr::is_latex_output()}
39
+ # PDF only — HTML uses _logo_before_body.html (above the TOC).
40
+ knitr::include_graphics("images/galaaz-lockup-stacked.png")
41
+ ```
42
+
30
43
  According to Wikipedia "Ruby is a dynamic, interpreted, reflective, object-oriented,
31
44
  general-purpose programming language. It was designed and developed in the mid-1990s by Yukihiro
32
45
  "Matz" Matsumoto in Japan." It reached high popularity with the development of Ruby on Rails
@@ -9,9 +9,17 @@ output:
9
9
  html_document:
10
10
  self_contained: true
11
11
  keep_md: true
12
+ toc: true
13
+ toc_float: true
14
+ toc_depth: 2
15
+ number_sections: true
16
+ includes:
17
+ before_body: _logo_before_body.html
12
18
  pdf_document:
13
19
  includes:
14
- in_header: "../../sty/galaaz.sty"
20
+ in_header:
21
+ - "../../sty/galaaz.sty"
22
+ - "../../sty/galaaz-headers-from-p3.tex"
15
23
  keep_tex: yes
16
24
  number_sections: yes
17
25
  toc: true
@@ -21,6 +29,8 @@ fontsize: 11pt
21
29
 
22
30
 
23
31
 
32
+
33
+
24
34
  According to Wikipedia "Ruby is a dynamic, interpreted, reflective, object-oriented,
25
35
  general-purpose programming language. It was designed and developed in the mid-1990s by Yukihiro
26
36
  "Matz" Matsumoto in Japan." It reached high popularity with the development of Ruby on Rails
@@ -101,7 +101,7 @@
101
101
  \usepackage[utf8]{inputenc}
102
102
 
103
103
  \usepackage{geometry}
104
- \geometry{a4paper, top=1in}
104
+ \geometry{a4paper, top=1.05in, headheight=30pt, headsep=14pt}
105
105
 
106
106
  % needed for kableExtra
107
107
  \usepackage{longtable}
@@ -122,29 +122,60 @@
122
122
  \usepackage{graphicx}
123
123
 
124
124
  \usepackage{fancyhdr}
125
- % set the header and foot style
126
- % style 'fancy' adds the section name on the header
127
- % and the page number on the footer
125
+ % Header: small Galaaz mark (left); page number + section title (right),
126
+ % matching classic LaTeX style: "4 AN EXTENSION TO THE EXAMPLE"
127
+ % (upright page number, uppercase italic section name).
128
+ % Logo paths cover repo blogs (../../sty/), installed ~/sty/, and local images/.
129
+ % Blogs may delay headers with \renewcommand{\galaazheaderfrompage}{3} after this sty
130
+ % (e.g. skip title/TOC and a logo splash page).
131
+ \newcommand{\galaazheaderfrompage}{1}
132
+ \newcommand{\galaazheaderlogo}{%
133
+ \raisebox{-0.12\height}{%
134
+ \IfFileExists{../../sty/galaaz-header.png}{%
135
+ \includegraphics[height=0.32in]{../../sty/galaaz-header.png}%
136
+ }{%
137
+ \IfFileExists{galaaz-header.png}{%
138
+ \includegraphics[height=0.32in]{galaaz-header.png}%
139
+ }{%
140
+ \IfFileExists{images/galaaz-header.png}{%
141
+ \includegraphics[height=0.32in]{images/galaaz-header.png}%
142
+ }{}%
143
+ }%
144
+ }%
145
+ }%
146
+ }
147
+ % Section title only in marks (no \thesection); page number is separate.
148
+ \renewcommand{\sectionmark}[1]{\markboth{#1}{}}
149
+ \renewcommand{\subsectionmark}[1]{}% keep the current section in the header
150
+ \newcommand{\galaazmaybeheaderlogo}{%
151
+ \ifnum\value{page}<\galaazheaderfrompage\relax\else\galaazheaderlogo\fi}
152
+ \newcommand{\galaazmayberighthead}{%
153
+ \ifnum\value{page}<\galaazheaderfrompage\relax
154
+ \else
155
+ \textup{\thepage}\hspace{1em}\textit{\MakeUppercase{\leftmark}}%
156
+ \fi
157
+ }
128
158
  \pagestyle{fancy}
129
-
130
- % style 'fancyhf' leaves header and footer empty
131
- %\fancyhf{}
132
-
133
- % sets the left head element to \rightmark, which contains the
134
- % current section (\leftmark is the current chapter)
135
- %\fancyhead[L]{\rightmark} .
136
-
137
- % sets the right head element to the page number.
138
- % \fancyhead[R]{\thepage}
139
-
140
- % lets the head rule disappear.
141
- % \renewcommand{\headrulewidth}{0pt}
142
- % Possible selectors for the optional argument of \fancyhead/\fancyfoot
143
- % are L (left), C (center) or R (right) for the position of the element
144
- % and E (even) or O (odd) to distinguish even and odd pages. If you omit
145
- % E/O the element is set for all pages.
146
-
147
- % \usepackage{lipsum}
159
+ \fancyhf{}
160
+ \fancyhead[L]{\galaazmaybeheaderlogo}
161
+ \fancyhead[R]{\galaazmayberighthead}
162
+ \renewcommand{\headrulewidth}{0.3pt}
163
+ \makeatletter
164
+ \renewcommand{\headrule}{%
165
+ \ifnum\value{page}<\galaazheaderfrompage\relax
166
+ \else
167
+ \hrule\@height\headrulewidth\@width\headwidth
168
+ \vskip-\headrulewidth
169
+ \fi
170
+ }
171
+ \makeatother
172
+ % First page often uses plain; same conditional header logic.
173
+ \fancypagestyle{plain}{%
174
+ \fancyhf{}%
175
+ \fancyhead[L]{\galaazmaybeheaderlogo}%
176
+ \fancyhead[R]{\galaazmayberighthead}%
177
+ \renewcommand{\headrulewidth}{0.3pt}%
178
+ }
148
179
 
149
180
  % make available command lastpage
150
181
  \usepackage{lastpage}
@@ -189,6 +220,10 @@
189
220
 
190
221
  %
191
222
  %\newcommand{\atraso}[1]{\color{red} \textbf {Tempo desde a Assinatura do Contrato: #1 dias}}
223
+ % No header on title/TOC (p.1) or splash logo page (p.2);
224
+ % logo + page number + section title from page 3 onward.
225
+ % Load after galaaz.sty.
226
+ \renewcommand{\galaazheaderfrompage}{3}
192
227
  \usepackage{bookmark}
193
228
  \IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available
194
229
  \urlstyle{same}
@@ -209,6 +244,8 @@
209
244
  \setcounter{tocdepth}{2}
210
245
  \tableofcontents
211
246
  }
247
+ \begin{center}\includegraphics[width=0.45\linewidth]{images/galaaz-lockup-stacked} \end{center}
248
+
212
249
  According to Wikipedia ``Ruby is a dynamic, interpreted, reflective,
213
250
  object-oriented, general-purpose programming language. It was designed
214
251
  and developed in the mid-1990s by Yukihiro''Matz'' Matsumoto in Japan.''
data/lib/galaaz/cli.rb CHANGED
@@ -8,7 +8,9 @@ require 'tmpdir'
8
8
 
9
9
  module Galaaz
10
10
  module CLI
11
- BLOG_NAMES = %w[oh_my gknit galaaz_ggplot manual nse_dplyr ruby_plot].freeze
11
+ BLOG_NAMES = %w[
12
+ oh_my gknit galaaz_ggplot galaaz_2_0 r_on_rails_ledger manual nse_dplyr ruby_plot
13
+ ].freeze
12
14
  PROFILES = %w[knit arrow tex bio examples ledger demo].freeze
13
15
  CONFIG_DIR = File.join(Dir.home, '.config', 'galaaz')
14
16
  PROFILES_DIR = File.join(CONFIG_DIR, 'profiles')
@@ -28,6 +30,8 @@ module Galaaz
28
30
  ['debug-galaaz.sh', 'omarchy-galaaz-debug', true]
29
31
  ].freeze
30
32
  OMARCHY_MENU_FILE = 'omarchy-menu.jsonc'
33
+ OMARCHY_FONT_REL = File.join('fonts', 'galaaz.ttf')
34
+ OMARCHY_FONT_FAMILY = 'galaaz'
31
35
  BLOGS_MARKER = '.galaaz-blogs'
32
36
  EXAMPLES_MARKER = '.galaaz-examples'
33
37
  CRAN = 'https://cloud.r-project.org'
@@ -148,6 +152,7 @@ module Galaaz
148
152
  Writes:
149
153
  ~/.local/bin/omarchy-install-galaaz (and add/remove/guide/gknit/debug)
150
154
  ~/.config/omarchy/extensions/omarchy-menu.jsonc
155
+ ~/.local/share/fonts/galaaz/galaaz.ttf (menu brand mark)
151
156
 
152
157
  Then: Super+Space → Install → Development → Galaaz
153
158
  HELP
@@ -193,6 +198,8 @@ module Galaaz
193
198
  puts " #{dest}: #{File.file?(path) ? path : 'MISSING'}"
194
199
  end
195
200
  puts " menu: #{File.file?(menu) ? menu : 'MISSING'}"
201
+ font = File.expand_path('~/.local/share/fonts/galaaz/galaaz.ttf')
202
+ puts " font: #{File.file?(font) ? font : 'MISSING'}"
196
203
  bundled = File.join(root, 'script', 'omarchy')
197
204
  puts " gem overlay: #{File.directory?(bundled) ? bundled : 'MISSING (reinstall gem)'}"
198
205
  0
@@ -202,7 +209,9 @@ module Galaaz
202
209
  d = File.join(root, 'script', 'omarchy')
203
210
  abort_unless(File.directory?(d), "Omarchy overlay missing from gem (#{d}). Reinstall galaaz.")
204
211
  abort_unless(
205
- File.file?(File.join(d, 'install-galaaz.sh')) && File.file?(File.join(d, OMARCHY_MENU_FILE)),
212
+ File.file?(File.join(d, 'install-galaaz.sh')) &&
213
+ File.file?(File.join(d, OMARCHY_MENU_FILE)) &&
214
+ File.file?(File.join(d, OMARCHY_FONT_REL)),
206
215
  "incomplete Omarchy overlay in gem (#{d})"
207
216
  )
208
217
  d
@@ -213,10 +222,11 @@ module Galaaz
213
222
  tmp = Dir.mktmpdir('galaaz-omarchy-')
214
223
  base = "https://raw.githubusercontent.com/#{OMARCHY_GITHUB_REPO}/#{ref}/script/omarchy"
215
224
  puts "galaaz omarchy: fetching #{base}/…"
216
- names = OMARCHY_BIN_FILES.map(&:first) + [OMARCHY_MENU_FILE]
225
+ names = OMARCHY_BIN_FILES.map(&:first) + [OMARCHY_MENU_FILE, OMARCHY_FONT_REL]
217
226
  names.uniq.each do |name|
218
227
  url = "#{base}/#{name}"
219
228
  dest = File.join(tmp, name)
229
+ FileUtils.mkdir_p(File.dirname(dest))
220
230
  ok = system('curl', '-fsSL', '-o', dest, url)
221
231
  unless ok && File.file?(dest) && File.size(dest).positive?
222
232
  FileUtils.rm_rf(tmp)
@@ -247,6 +257,23 @@ module Galaaz
247
257
  menu_dest = File.join(ext, OMARCHY_MENU_FILE)
248
258
  FileUtils.cp(menu_src, menu_dest)
249
259
  puts "galaaz omarchy: #{menu_dest}"
260
+
261
+ install_omarchy_font_from!(src_dir)
262
+ end
263
+
264
+ def install_omarchy_font_from!(src_dir)
265
+ src = File.join(src_dir, OMARCHY_FONT_REL)
266
+ abort_unless(File.file?(src), "missing #{src} (rebuild with logos/icon-font/build_font.py)")
267
+ fonts = File.expand_path('~/.local/share/fonts/galaaz')
268
+ FileUtils.mkdir_p(fonts)
269
+ dest = File.join(fonts, 'galaaz.ttf')
270
+ FileUtils.cp(src, dest)
271
+ puts "galaaz omarchy: #{dest} (family #{OMARCHY_FONT_FAMILY}, U+E900)"
272
+ if command_present?('fc-cache')
273
+ system('fc-cache', '-f', fonts)
274
+ end
275
+ warn 'galaaz omarchy: restart the Omarchy shell so Qt picks up the galaaz font' \
276
+ if ENV['OMARCHY_PATH'] || File.directory?(File.expand_path('~/.config/omarchy'))
250
277
  end
251
278
 
252
279
  # ---- blogs ----
@@ -607,6 +634,13 @@ module Galaaz
607
634
  ledger_bundle_env({ 'SEED_PROFILE' => 'fast' }, 'exec', 'rails', 'db:seed'),
608
635
  'rails db:seed failed'
609
636
  )
637
+ # builds/tailwind.css is gitignored — Propshaft needs a one-shot build for rails s
638
+ # (bin/dev runs tailwindcss:watch and would also create it).
639
+ puts 'galaaz add ledger: rails tailwindcss:build'
640
+ abort_unless(
641
+ ledger_bundle('exec', 'rails', 'tailwindcss:build'),
642
+ 'rails tailwindcss:build failed (tailwind.css missing for Propshaft)'
643
+ )
610
644
  end
611
645
 
612
646
  mark_profile!('ledger')
@@ -813,6 +847,16 @@ module Galaaz
813
847
  dest = File.join(sty_dir, 'galaaz.sty')
814
848
  FileUtils.cp(src, dest)
815
849
  puts "galaaz sty: #{dest}"
850
+ header = File.join(root, 'sty', 'galaaz-header.png')
851
+ if File.file?(header)
852
+ FileUtils.cp(header, File.join(sty_dir, 'galaaz-header.png'))
853
+ puts "galaaz sty header: #{File.join(sty_dir, 'galaaz-header.png')}"
854
+ end
855
+ from_p3 = File.join(root, 'sty', 'galaaz-headers-from-p3.tex')
856
+ if File.file?(from_p3)
857
+ FileUtils.cp(from_p3, File.join(sty_dir, 'galaaz-headers-from-p3.tex'))
858
+ puts "galaaz sty headers: #{File.join(sty_dir, 'galaaz-headers-from-p3.tex')}"
859
+ end
816
860
  dest
817
861
  end
818
862
 
@@ -0,0 +1,27 @@
1
+ # Galaaz Omarchy menu icon font
2
+
3
+ Private TrueType font (`family: galaaz`) with one private-use glyph:
4
+
5
+ | Codepoint | Name | Role |
6
+ |-----------|------|------|
7
+ | `U+E900` | `galaaz` | Monochrome R + gem cutout for Install menu rows |
8
+
9
+ ## Sources
10
+
11
+ | File | Role |
12
+ |------|------|
13
+ | `galaaz-mark.svg` | Editable monochrome silhouette (straight segments) |
14
+ | `build_font.py` | Builds `../../script/omarchy/fonts/galaaz.ttf` (needs `fonttools`) |
15
+ | `../../script/omarchy/fonts/galaaz.ttf` | Shipped with the Omarchy overlay |
16
+
17
+ Rebuild after editing the SVG:
18
+
19
+ ```bash
20
+ python3 -m venv /tmp/galaaz-font-venv
21
+ /tmp/galaaz-font-venv/bin/pip install fonttools
22
+ /tmp/galaaz-font-venv/bin/python logos/icon-font/build_font.py
23
+ ```
24
+
25
+ `galaaz omarchy` installs the TTF to `~/.local/share/fonts/galaaz/` and the menu
26
+ uses `"iconFont": "galaaz"`. Restart the Omarchy shell after install so Qt
27
+ reloads fonts (`omarchy menu refresh` alone is not enough for a new family).
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env python3
2
+ """Build script/omarchy/fonts/galaaz.ttf from logos/icon-font/galaaz-mark.svg."""
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ import sys
7
+ from pathlib import Path
8
+
9
+ from fontTools.fontBuilder import FontBuilder
10
+ from fontTools.misc.transform import Transform
11
+ from fontTools.pens.ttGlyphPen import TTGlyphPen
12
+ from fontTools.svgLib.path import SVGPath
13
+ from fontTools.ttLib import TTFont
14
+ from fontTools.ttLib.tables._g_l_y_f import Glyph as TTGlyph
15
+ from fontTools.ttLib.tables._g_l_y_f import GlyphCoordinates
16
+ from fontTools.ttLib.tables._g_l_y_f import flagOnCurve
17
+
18
+ ROOT = Path(__file__).resolve().parents[2]
19
+ SVG = ROOT / "logos" / "icon-font" / "galaaz-mark.svg"
20
+ OUT = ROOT / "script" / "omarchy" / "fonts" / "galaaz.ttf"
21
+ CODEPOINT = 0xE900
22
+
23
+
24
+ def extract_path_d(svg_text: str) -> str:
25
+ m = re.search(r'<path[^>]*\sd="([^"]+)"', svg_text, re.DOTALL)
26
+ if not m:
27
+ raise SystemExit("no <path d=...> in SVG")
28
+ return re.sub(r"\s+", " ", m.group(1)).strip()
29
+
30
+
31
+ def signed_area(pts) -> float:
32
+ a = 0.0
33
+ n = len(pts)
34
+ for i in range(n):
35
+ x1, y1 = pts[i]
36
+ x2, y2 = pts[(i + 1) % n]
37
+ a += x1 * y2 - x2 * y1
38
+ return 0.5 * a
39
+
40
+
41
+ def fix_hole_windings(glyph: TTGlyph) -> None:
42
+ """TrueType: outer CW (area < 0), holes CCW (area > 0)."""
43
+ if glyph.numberOfContours <= 0:
44
+ return
45
+ coords = list(glyph.coordinates)
46
+ ends = list(glyph.endPtsOfContours)
47
+ flags = list(glyph.flags)
48
+ start = 0
49
+ new_coords = []
50
+ new_flags = []
51
+ new_ends = []
52
+ for i, end in enumerate(ends):
53
+ pts = coords[start : end + 1]
54
+ fl = flags[start : end + 1]
55
+ area = signed_area(pts)
56
+ # First contour = outer; rest = holes (rails are positive fills — keep CW)
57
+ # Contours after first that are nested holes need opposite winding.
58
+ # Heuristic: second contour in our SVG is the gem hole; rails stay CW.
59
+ if i == 1 and area < 0:
60
+ pts = list(reversed(pts))
61
+ fl = list(reversed(fl))
62
+ new_coords.extend(pts)
63
+ new_flags.extend(fl)
64
+ new_ends.append(len(new_coords) - 1)
65
+ start = end + 1
66
+ glyph.coordinates = GlyphCoordinates(new_coords)
67
+ glyph.flags = new_flags
68
+ glyph.endPtsOfContours = new_ends
69
+ glyph.numberOfContours = len(new_ends)
70
+
71
+
72
+ def main() -> int:
73
+ d = extract_path_d(SVG.read_text(encoding="utf-8"))
74
+ transform = Transform(1, 0, 0, -1, 0, 1000)
75
+
76
+ pen = TTGlyphPen(glyphSet=None)
77
+ SVGPath.fromstring(
78
+ f'<path d="{d}" fill-rule="evenodd"/>', transform=transform
79
+ ).draw(pen)
80
+ glyph = pen.glyph()
81
+ fix_hole_windings(glyph)
82
+
83
+ fb = FontBuilder(1000, isTTF=True)
84
+ fb.setupGlyphOrder([".notdef", "galaaz"])
85
+ fb.setupCharacterMap({CODEPOINT: "galaaz"})
86
+ fb.setupGlyf({".notdef": TTGlyph(), "galaaz": glyph})
87
+ fb.setupHorizontalMetrics({".notdef": (600, 0), "galaaz": (1000, 0)})
88
+ fb.setupHorizontalHeader(ascent=1000, descent=0)
89
+ fb.setupOS2(
90
+ sTypoAscender=1000,
91
+ sTypoDescender=0,
92
+ sTypoLineGap=0,
93
+ usWinAscent=1000,
94
+ usWinDescent=0,
95
+ sxHeight=500,
96
+ sCapHeight=700,
97
+ )
98
+ fb.setupPost()
99
+ fb.setupNameTable(
100
+ {
101
+ "familyName": "galaaz",
102
+ "styleName": "Regular",
103
+ "uniqueFontIdentifier": "galaaz Regular",
104
+ "fullName": "galaaz Regular",
105
+ "psName": "galaaz-Regular",
106
+ "version": "Version 1.000",
107
+ "manufacturer": "Galaaz",
108
+ "description": "Monochrome Galaaz mark for Omarchy menu rows (U+E900).",
109
+ }
110
+ )
111
+ OUT.parent.mkdir(parents=True, exist_ok=True)
112
+ fb.save(OUT)
113
+
114
+ tt = TTFont(OUT)
115
+ assert tt["cmap"].getBestCmap().get(CODEPOINT) == "galaaz"
116
+ g = tt["glyf"]["galaaz"]
117
+ coords = list(g.coordinates)
118
+ ends = list(g.endPtsOfContours)
119
+ start = 0
120
+ for i, end in enumerate(ends):
121
+ pts = coords[start : end + 1]
122
+ a = signed_area(pts)
123
+ print(f" contour {i}: {'CW' if a < 0 else 'CCW'} area={a:.0f}")
124
+ start = end + 1
125
+ print(f"wrote {OUT} glyph U+{CODEPOINT:04X} family=galaaz")
126
+ return 0
127
+
128
+
129
+ if __name__ == "__main__":
130
+ sys.exit(main())
@@ -0,0 +1,34 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--
3
+ Monochrome Galaaz mark for the Omarchy menu icon font (menu-size silhouette).
4
+ Solid R with left top spur + diamond gem cutout (minimum-size spirit).
5
+ Straight segments only. Optical box ~150..880 in a 1000 viewBox.
6
+ -->
7
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000" fill="#000">
8
+ <path fill-rule="evenodd" d="
9
+ M 160 150
10
+ H 500
11
+ L 620 150
12
+ L 700 230
13
+ L 720 340
14
+ L 700 450
15
+ L 620 520
16
+ L 530 545
17
+ L 760 880
18
+ H 580
19
+ L 400 560
20
+ H 320
21
+ V 880
22
+ H 200
23
+ V 280
24
+ H 160
25
+ V 150
26
+ Z
27
+
28
+ M 460 280
29
+ L 380 350
30
+ L 460 420
31
+ L 540 350
32
+ Z
33
+ "/>
34
+ </svg>
@@ -31,6 +31,10 @@ Then Super+Space → Install → Development → **Galaaz**.
31
31
  | `debug-galaaz.sh` | Snapshot doctor/PATH/gem/bridge |
32
32
  | `remove-galaaz.sh` | Uninstall gem + marked blogs; leave R |
33
33
  | `omarchy-menu.jsonc` | Menu overlay submenu under Install → Development |
34
+ | `fonts/galaaz.ttf` | Monochrome brand mark (`iconFont: galaaz`, U+E900) |
35
+
36
+ Menu rows use the Galaaz icon font (not the Ruby-on-Rails Nerd Font gem). Source SVG
37
+ and rebuild script live under `logos/icon-font/`.
34
38
 
35
39
  After core, the menu includes **Guide (what's next)**, **Documentation (website)**, and **GitHub repository**. After Knit, **Knit demo (oh_my)** runs an example blog.
36
40
 
@@ -53,8 +57,11 @@ cp galaaz-guide.sh ~/.local/bin/omarchy-galaaz-guide
53
57
  cp galaaz-gknit.sh ~/.local/bin/omarchy-galaaz-gknit
54
58
  cp debug-galaaz.sh ~/.local/bin/omarchy-galaaz-debug
55
59
  cp omarchy-menu.jsonc ~/.config/omarchy/extensions/omarchy-menu.jsonc
60
+ mkdir -p ~/.local/share/fonts/galaaz
61
+ cp fonts/galaaz.ttf ~/.local/share/fonts/galaaz/
62
+ fc-cache -f ~/.local/share/fonts/galaaz
56
63
  chmod +x ~/.local/bin/omarchy-*
57
- ```
64
+ # Restart the Omarchy shell so the galaaz font is visible in the menu.```
58
65
 
59
66
  ## TryOmarchy steps
60
67
 
Binary file
@@ -271,10 +271,17 @@ fi
271
271
  "${HOME}/.local/bin/galaaz" doctor 2>&1 | tee -a "${LOG}" || true
272
272
 
273
273
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
274
- mkdir -p "${HOME}/.config/omarchy/extensions" "${HOME}/.local/bin"
274
+ mkdir -p "${HOME}/.config/omarchy/extensions" "${HOME}/.local/bin" "${HOME}/.local/share/fonts/galaaz"
275
275
  if [[ -f "${SCRIPT_DIR}/omarchy-menu.jsonc" ]]; then
276
276
  cp "${SCRIPT_DIR}/omarchy-menu.jsonc" "${HOME}/.config/omarchy/extensions/omarchy-menu.jsonc"
277
277
  fi
278
+ if [[ -f "${SCRIPT_DIR}/fonts/galaaz.ttf" ]]; then
279
+ cp "${SCRIPT_DIR}/fonts/galaaz.ttf" "${HOME}/.local/share/fonts/galaaz/galaaz.ttf"
280
+ if command -v fc-cache >/dev/null 2>&1; then
281
+ fc-cache -f "${HOME}/.local/share/fonts/galaaz" >/dev/null 2>&1 || true
282
+ fi
283
+ log "menu font: ${HOME}/.local/share/fonts/galaaz/galaaz.ttf"
284
+ fi
278
285
  cp "${BASH_SOURCE[0]}" "${HOME}/.local/bin/omarchy-install-galaaz"
279
286
  chmod +x "${HOME}/.local/bin/omarchy-install-galaaz"
280
287
  if [[ -f "${SCRIPT_DIR}/remove-galaaz.sh" ]]; then
@@ -4,14 +4,19 @@
4
4
  //
5
5
  // Use ~/.local/bin/galaaz (installer wrapper). Do not quote the whole
6
6
  // "galaaz add …" as one word — omarchy-launch-tui then does nothing useful.
7
+ //
8
+ // Brand mark: private-use U+E900 in family "galaaz"
9
+ // (script/omarchy/fonts/galaaz.ttf → ~/.local/share/fonts/galaaz/).
7
10
 
8
11
  "install.development.galaaz": {
9
- "icon": "󰫏",
12
+ "icon": "",
13
+ "iconFont": "galaaz",
10
14
  "label": "Galaaz",
11
15
  "description": "R on Rails"
12
16
  },
13
17
  "install.development.galaaz.core": {
14
- "icon": "󰫏",
18
+ "icon": "",
19
+ "iconFont": "galaaz",
15
20
  "label": "Galaaz (core)",
16
21
  "description": "gem + setup + blogs (not just gem install)",
17
22
  "action": "omarchy-launch-tui omarchy-install-galaaz",
@@ -39,7 +44,8 @@
39
44
  "when": "test -f ~/.config/galaaz/profiles/core"
40
45
  },
41
46
  "install.development.galaaz.knit": {
42
- "icon": "󰫏",
47
+ "icon": "",
48
+ "iconFont": "galaaz",
43
49
  "label": "Knit (HTML blogs)",
44
50
  "description": "pandoc + knitr/rmarkdown",
45
51
  "action": "omarchy-launch-tui omarchy-galaaz-add knit",
@@ -53,38 +59,44 @@
53
59
  "when": "test -f ~/.config/galaaz/profiles/knit"
54
60
  },
55
61
  "install.development.galaaz.arrow": {
56
- "icon": "󰫏",
62
+ "icon": "",
63
+ "iconFont": "galaaz",
57
64
  "label": "Arrow",
58
65
  "action": "omarchy-launch-tui omarchy-galaaz-add arrow",
59
66
  "disabled": "test -f ~/.config/galaaz/profiles/arrow"
60
67
  },
61
68
  "install.development.galaaz.tex": {
62
- "icon": "󰫏",
69
+ "icon": "",
70
+ "iconFont": "galaaz",
63
71
  "label": "TeX (PDF blogs)",
64
72
  "action": "omarchy-launch-tui omarchy-galaaz-add tex",
65
73
  "disabled": "test -f ~/.config/galaaz/profiles/tex"
66
74
  },
67
75
  "install.development.galaaz.bio": {
68
- "icon": "󰫏",
76
+ "icon": "",
77
+ "iconFont": "galaaz",
69
78
  "label": "Bioconductor (DESeq2)",
70
79
  "action": "omarchy-launch-tui omarchy-galaaz-add bio",
71
80
  "disabled": "test -f ~/.config/galaaz/profiles/bio"
72
81
  },
73
82
  "install.development.galaaz.examples": {
74
- "icon": "󰫏",
83
+ "icon": "",
84
+ "iconFont": "galaaz",
75
85
  "label": "Examples",
76
86
  "action": "omarchy-launch-tui omarchy-galaaz-add examples",
77
87
  "disabled": "test -f ~/.config/galaaz/profiles/examples"
78
88
  },
79
89
  "install.development.galaaz.ledger": {
80
- "icon": "󰫏",
90
+ "icon": "",
91
+ "iconFont": "galaaz",
81
92
  "label": "Ledger (R-on-Rails demo)",
82
93
  "description": "Clone app, seed, bin/dev",
83
94
  "action": "omarchy-launch-tui omarchy-galaaz-add ledger",
84
95
  "disabled": "test -f ~/.config/galaaz/profiles/ledger"
85
96
  },
86
97
  "remove.development.galaaz": {
87
- "icon": "󰫏",
98
+ "icon": "",
99
+ "iconFont": "galaaz",
88
100
  "label": "Galaaz",
89
101
  "description": "Core gem (add-on R packages stay)",
90
102
  "action": "omarchy-launch-tui omarchy-remove-galaaz"
Binary file
@@ -0,0 +1,4 @@
1
+ % No header on title/TOC (p.1) or splash logo page (p.2);
2
+ % logo + page number + section title from page 3 onward.
3
+ % Load after galaaz.sty.
4
+ \renewcommand{\galaazheaderfrompage}{3}