galaaz 2.1.3 → 2.1.5

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: '085fd47fe76016fb5b078f3c44a02100a7d9af05c2f7cf9e19ded83058947c8e'
4
- data.tar.gz: 19f36b20968fd4456ad95024f2a33dbde60dfdf62a3bbda295d49e08a8c32bc7
3
+ metadata.gz: d39a98e695448ffb0166d33746445cc0076efcbd15e6f34250c99512e7c8e71d
4
+ data.tar.gz: eff6228e3febeb502838f1a6b99e38d03186327678b1a5535e58e8548e516d72
5
5
  SHA512:
6
- metadata.gz: c7db477fca2f6de435d9eb6bd5ccc5ee709a779e3a5816febc9a0eda9be51f5f18812af79889e7fd4ce1e5facd79a080e80a98829381b19670d6a380765554c4
7
- data.tar.gz: 6ba4144e49328b6bb70188ab6330ed086f969cb952076758db0207171c54c2ff41e6fb21c8666a6cd87b459f47b2786a31edf8f1f1b98343d7d536aae902de36
6
+ metadata.gz: ffe309c54323c08acabe1752c677cd67090878170b33853eb739195f4be36450379b2e100dc5e9ecfa317e4e4373aed8082dfee8407bb5231cd1d5b41c6fbdf2
7
+ data.tar.gz: daef47d66a2f3c20e2e430797ffd6193e9d80cde6ffc9b82856835dab4c0a3e3f8833b17d1b6b3389e4e5e3c5a7cccba8aee42d9b023b2e110758b6e678e9a2c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,48 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.1.5
4
+
5
+ ### Fixed
6
+
7
+ - `gknit` / `gknit_Rscript`: resolve input with `File.expand_path` so absolute paths
8
+ (e.g. `~/galaaz-blogs/...`) are not prefixed with `Dir.pwd` (broke when run from
9
+ `~/.local/bin`).
10
+ - `galaaz add ledger`: do not strip app Ruby version pins; keep engine-agnostic
11
+ RubyGems `gem "galaaz"` rewrites only.
12
+
13
+ ### Changed
14
+
15
+ - Omarchy `omarchy-galaaz-add`: install pandoc via `pandoc-bin` or the latest GitHub
16
+ linux binary into `~/.local/bin` — not Arch `pandoc` / `pandoc-cli` (Haskell deps).
17
+ - Omarchy menu Docs / GitHub rows use `omarchy-launch-webapp` (same as Omarchy Learn).
18
+ - `galaaz add arrow` / ledger path: prefer Apache `LIBARROW_BINARY` prebuilt libarrow
19
+ (avoid Arch pacman arrow version skew on Omarchy).
20
+
21
+ ## 2.1.4
22
+
23
+ ### Added
24
+
25
+ - **`R::Job`**: long CRAN installs (and arbitrary R via `R::Job.eval`) run in a **child
26
+ Rscript** process, not on the NewBridge gatekeeper. Logs and metadata live under
27
+ `~/.local/share/galaaz/jobs/` (override with `GALAAZ_JOBS_DIR`). One install at a
28
+ time (`install.lock`). Bridge R stays free while Ruby awaits the job. Clears stale
29
+ `00LOCK-<pkg>` dirs before install (left behind after kill-on-timeout).
30
+ - **Layer C:** `R::Job.eval` / `R::Job.script` for long arbitrary R. Child gets
31
+ `setwd(job.dir)`, `GALAAZ_JOB_DIR`, and `result_path` (default `result.rds`). After
32
+ success, `job.load_rds` does a short sync `readRDS` on the bridge. Block form
33
+ awaits and yields the job (`coef = R::Job.eval(code) { |j| j.load_rds }`).
34
+ Documented in the manual section **Background R jobs (`R::Job`)** (README /
35
+ `blogs/manual/manual.Rmd`).
36
+
37
+ ### Changed
38
+
39
+ - `R.install_rlibs` / `R.install_and_loads` use `R::Job.install` and **await until
40
+ finished** by default (no bridge 60s install timeout). Optional await limit via
41
+ `install_timeout_sec:` or `GALAAZ_INSTALL_TIMEOUT_SEC` (also `gknit
42
+ --install_timeout_sec`); on timeout the child process group is killed so compile
43
+ work cannot OOM the shell. gknit reports install-job timeouts in the internal
44
+ error summary.
45
+
3
46
  ## 2.1.3
4
47
 
5
48
  ### Fixed
@@ -85,4 +128,6 @@ Galaaz 2.0 drives **GNU R** from **JRuby** or **CRuby** over a process bridge. I
85
128
  - `grun`, `gknit_Rscript`, and the polyglot path in `gknit-draft` are leftover from the Graal era; use `galaaz-jruby` / `gknit` (or `GALAAZ_RUBY=ruby` for CRuby).
86
129
  - The gatekeeper must be compiled on the install machine (Rcpp + C++ toolchain); it is not a prebuilt binary in the gem.
87
130
  - Multi-runtime Docker R (Phase 4.5) is a slow integration spec, not part of cold-install CI.
88
- - The gknit installation-timeout spec is skipped pending a dedicated pass; SimpleCov is a development gem and is not installed in the smoke image.
131
+ - The gknit installation-timeout spec covers `R::Job` await timeouts
132
+ (`GALAAZ_INSTALL_TIMEOUT_SEC`); SimpleCov is a development gem and is not installed in
133
+ the smoke image.
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
  title: "Galaaz Manual"
3
3
  subtitle: "R-on-Rails: GNU R meets Ruby for the web"
4
4
  author: "Rodrigo Botafogo"
5
- tags: [Galaaz, "R-on-Rails", Ruby, Rails, JRuby, R, "GNU R", ggplot2, knitr, dplyr, Bioconductor, Arrow]
5
+ tags: [Galaaz, "R-on-Rails", Ruby, Rails, JRuby, CRuby, R, "GNU R", ggplot2, knitr, dplyr, Bioconductor, Arrow]
6
6
  date: "2026"
7
7
  bibliography: "../../examples/Bibliography/stats.bib"
8
8
  output:
@@ -73,7 +73,7 @@ rewrite in another stack. **R-on-Rails** means:
73
73
  1. **Keep your science in R** — packages, formulas, plots, Bioconductor, the same engine as RStudio.
74
74
  2. **Learn enough Ruby/Rails** — routes, controllers, views, jobs, auth—not a second statistics career.
75
75
  3. **Call R from the app** — Galaaz loads R behind the scenes; long jobs can complete asynchronously
76
- while Rails stays responsive (see later sections on the bridge and `R::Async`).
76
+ while Rails stays responsive (see later sections on the bridge, `R::Async`, and `R::Job`).
77
77
  4. **Ship alone when you need to** — one developer can own both the analysis and the product UI,
78
78
  without waiting for a separate “stats engineer” and “Rails engineer.”
79
79
 
@@ -358,7 +358,13 @@ A **table of all `bin/` scripts** (bootstrap, Ruby launcher, gstudio, gknit, tes
358
358
  **`bin/run_all_rspec`** (same `GALAAZ_RUBY` rule). **`bin/galaaz-jruby`** remains a thin
359
359
  wrapper that forces JRuby.
360
360
 
361
- A **gstudio** try image (JRuby + R + Galaaz already installed) is **`docker run --rm -it ghcr.io/rbotafogo/galaaz-try:gstudio`** (or **`./docker/try-gstudio/run.sh`** from a checkout). Maintainers can prove a RubyGems install on a throwaway Ubuntu machine (no repo inside the container) with **`./docker/cold-install/run.sh published-specs`** (JRuby) or **`./docker/cold-install-cruby/run.sh published-specs`** (CRuby).
361
+ A **gstudio** try image with Galaaz already installed is available for both engines:
362
+ **JRuby** — `docker run --rm -it ghcr.io/rbotafogo/galaaz-try:gstudio` (or
363
+ `./docker/try-gstudio/run.sh` from a checkout); **CRuby** —
364
+ `docker run --rm -it ghcr.io/rbotafogo/galaaz-try:cruby` (or `./docker/try-cruby/run.sh`).
365
+ Maintainers can prove a RubyGems install on a throwaway Ubuntu machine (no repo inside
366
+ the container) with `./docker/cold-install/run.sh published-specs` (JRuby) or
367
+ `./docker/cold-install-cruby/run.sh published-specs` (CRuby).
362
368
 
363
369
  ## Windows + WSL2 (optional: Docker / R in a container)
364
370
 
@@ -394,11 +400,18 @@ WSL integration is enabled for the distro where Galaaz is installed.
394
400
  ``` ruby
395
401
  vec = R.c(1, 2, 3, 4)
396
402
  puts vec
403
+
404
+ # R.foo(...) calls an R *function*. Datasets are objects — fetch with ~:
405
+ df = ~R[:mtcars]
406
+ puts R.summary(df)
397
407
  ```
398
408
 
399
409
  ```
400
410
  ## [1] 1 2 3 4
401
411
  ```
412
+
413
+ (`R.mtcars` is wrong: it becomes `mtcars()` in R and fails. With
414
+ `using Galaaz::SymbolDSL`, the short form `~:mtcars` also works.)
402
415
 
403
416
  * Run all specs
404
417
 
@@ -456,8 +469,13 @@ driver). For concurrency tests on the bridge itself, see `specs/bridge_concurren
456
469
 
457
470
  ## Long-running R calls and a completion block
458
471
 
459
- For R work that can take a long time, the bridge can avoid a Ruby-side **wait timeout** by
460
- scheduling the call and resuming in a **block** when the `RET` arrives.
472
+ For R work that can take a long time **on the bridge**, the bridge can avoid a Ruby-side
473
+ **wait timeout** by scheduling the call and resuming in a **block** when the `RET` arrives.
474
+
475
+ **Important distinction:** this keeps the **same** GNU R process busy. Other sync
476
+ `eval_r` / gknit chunks still wait on that R. For CRAN installs and other work that must
477
+ **not** monopolize the bridge (or that can OOM a small VM if abandoned mid-compile), use
478
+ **`R::Job`** in the next section instead.
461
479
 
462
480
  - **`R.eval_r_async(code, timeout: nil) { |result| ... }`** — string eval; on success, `result.value`
463
481
  is the same formatted string as **`R.eval_r`** (use `timeout: nil` for no Ruby-side limit).
@@ -514,6 +532,67 @@ the outcome to storage, and notify the client (poll, WebSocket, Turbo Stream, et
514
532
  Ruby pattern above is only to show **when** the result exists (inside the block, or after data
515
533
  written there is observed elsewhere). Runnable specs live in **`new_bridge_specs/eval_r_async_spec.rb`**.
516
534
 
535
+ ## Background R jobs (`R::Job`)
536
+
537
+ `R::Async` / `R.eval_r_async` free the **Ruby** thread while the **same** bridge R process
538
+ runs your code. That is enough for Rails-style “don’t block the request thread,” but not
539
+ enough for heavy `install.packages` or multi-minute model fits: the gatekeeper R is still
540
+ busy, other chunks time out, and abandoning the wait can leave compile work burning RAM.
541
+
542
+ **`R::Job`** runs that work in a **child `Rscript` process**. The bridge stays free. Logs and
543
+ metadata live under `~/.local/share/galaaz/jobs/` (override with `GALAAZ_JOBS_DIR`).
544
+
545
+ ### Package installs
546
+
547
+ `R.install_and_loads` / `R.install_rlibs` use `R::Job.install` and **await until the child
548
+ finishes** (default: no wall-clock limit). Optional limit: `GALAAZ_INSTALL_TIMEOUT_SEC` or
549
+ `install_timeout_sec:`. On timeout the child process group is killed so leftover
550
+ `make`/`gcc` cannot OOM the shell. Stale `00LOCK-*` dirs are cleared before the next install.
551
+ Only one install runs at a time (`install.lock`).
552
+
553
+ ``` ruby
554
+ # May take a long time the first time (e.g. caret); the bridge is not used for compile.
555
+ R.install_and_loads 'caret'
556
+ ```
557
+
558
+ ### Long arbitrary R (`eval` / `script`)
559
+
560
+ Prefer the **block** form (like `File.open`): await the child, yield the job, return the
561
+ block’s value. Without a block, the methods still await by default and return the `Job`.
562
+
563
+ ``` ruby
564
+ coef = R::Job.eval(<<~R) { |job| job.load_rds }
565
+ fit <- lm(mpg ~ wt, data = mtcars)
566
+ saveRDS(unname(coef(fit)), result_path)
567
+ R
568
+ puts coef
569
+ ```
570
+
571
+ ```
572
+ ## [1] 37.285126 -5.344472
573
+ ```
574
+
575
+ ``` ruby
576
+ # Without a block: awaits (wait: true is the default) and returns the Job
577
+ job = R::Job.eval(code)
578
+ job = R::Job.eval(code, wait: false) # start only; call job.wait later
579
+
580
+ # Script file; trailing args → commandArgs(trailingOnly=TRUE) in the child
581
+ res = R::Job.script('train.R', '5') { |job| job.load_rds }
582
+ ```
583
+
584
+ In the child: `setwd(job.dir)`, `.libPaths` includes the Galaaz user library,
585
+ `GALAAZ_JOB_DIR` is set, and **`result_path`** defaults to
586
+ `file.path(GALAAZ_JOB_DIR, "result.rds")`. Persist with `saveRDS(..., result_path)`, then
587
+ load on the bridge with **`job.load_rds`** (short sync `readRDS` → a normal Galaaz R object).
588
+
589
+ ### Choosing async vs Job
590
+
591
+ | Need | Use |
592
+ |------|-----|
593
+ | Don’t freeze a Ruby thread; short/medium R on the bridge is OK | `R::Async` / `R.eval_r_async` |
594
+ | Install CRAN packages, or long R that must not block the bridge | `R::Job` / `R.install_and_loads` |
595
+
517
596
  ## Galaaz + Rails (R-on-Rails) integration baseline
518
597
 
519
598
  This is the practical **R-on-Rails** starter: an R scientist’s analysis behind a small Rails
@@ -1873,7 +1952,8 @@ using even a very complex package as 'caret' is trivial with Galaaz.
1873
1952
 
1874
1953
  A word of advice: the 'caret' package has lots of dependencies and installing
1875
1954
  it in a Linux system is a time consuming operation. Method 'R.install_and_loads'
1876
- will install the package if it is not already installed and can take a while.
1955
+ will install the package if it is not already installed (via **`R::Job`**: a child
1956
+ `Rscript`, so the bridge stays free) and can take a while.
1877
1957
 
1878
1958
  ````
1879
1959
  ```{include model}
@@ -4194,10 +4274,11 @@ pulls in several dependencies; the first install can take several minutes.
4194
4274
  ## Example: DESeq2 on the airway dataset
4195
4275
 
4196
4276
  The script **`examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb`** is the canonical
4197
- version in the repository. Run it from the **Galaaz repository root** with JRuby, for example:
4277
+ version in the repository. Run it from the **Galaaz repository root** with either engine, for example:
4198
4278
 
4199
4279
  ```text
4200
- bin/galaaz-jruby examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb
4280
+ bin/galaaz-ruby examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb
4281
+ # or: bin/galaaz-jruby examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb
4201
4282
  ```
4202
4283
 
4203
4284
  The workflow in Ruby mirrors a standard DESeq2 vignette:
@@ -4226,7 +4307,7 @@ manual is knitted, because **DESeq2** is heavy and may be absent on the build ma
4226
4307
 
4227
4308
  ``` ruby
4228
4309
  # Canonical script: examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb
4229
- # Run: bin/galaaz-jruby examples/.../deseq2_airway_galaaz.rb (repo root).
4310
+ # Run: bin/galaaz-ruby examples/.../deseq2_airway_galaaz.rb (repo root).
4230
4311
 
4231
4312
  require 'galaaz'
4232
4313
 
data/bin/gknit CHANGED
@@ -65,26 +65,22 @@ that are created during rendering.") do |opt|
65
65
  opts.on("--callback_timeout_ms TIMEOUT_MS", Integer, "Callback timeout in milliseconds for R<->Ruby calls inside chunk execution. Use for long installs/computation (e.g., 7200000 for 2h).") do |opt|
66
66
  options[:callback_timeout_ms] = opt
67
67
  end
68
- opts.on("--bridge_timeout_sec TIMEOUT_SEC", Integer, "Bridge request timeout in seconds for Ruby->R eval calls (default 60). Increase for long install.packages/compilation work.") do |opt|
68
+ opts.on("--bridge_timeout_sec TIMEOUT_SEC", Integer, "Bridge request timeout in seconds for Ruby->R eval calls (default 60). For CRAN installs via R::Job, use GALAAZ_INSTALL_TIMEOUT_SEC instead.") do |opt|
69
69
  options[:bridge_timeout_sec] = opt
70
70
  end
71
+ opts.on("--install_timeout_sec TIMEOUT_SEC", Integer, "Await limit in seconds for R::Job package installs (sets GALAAZ_INSTALL_TIMEOUT_SEC). Default: wait until the child finishes.") do |opt|
72
+ options[:install_timeout_sec] = opt
73
+ end
71
74
  end
72
75
 
73
76
  remaining_args = parser.permute(ARGV.dup)
74
77
  ARGV.replace(remaining_args)
75
78
 
76
- # Sets the directory
77
- dir = Dir.pwd
78
-
79
- #=========================================================================================
80
- # Check if the name of the file to gKnit was given and that it exists. If not,
81
- # issue error.
82
- #=========================================================================================
83
-
84
79
  options[:input_file] = ARGV[0] if !ARGV[0].nil?
85
80
  raise "Input file name is required for gKnitting. Add -f FILE or --input_file FILE. For help, type gknit -h" if
86
81
  options[:input_file].nil?
87
- options[:input_file] = "#{dir}/#{options[:input_file]}"
82
+ # File.expand_path keeps absolute paths intact (do not prefix Dir.pwd).
83
+ options[:input_file] = File.expand_path(options[:input_file])
88
84
  raise "File #{options[:input_file]} does not exist!" if !File.exist?(options[:input_file])
89
85
 
90
86
  #=========================================================================================
@@ -153,6 +149,7 @@ input_dir = File.dirname(input_file)
153
149
  code = <<EOF
154
150
  ENV['GALAAZ_CALLBACK_TIMEOUT_MS'] = #{options[:callback_timeout_ms].to_s.inspect} if #{!options[:callback_timeout_ms].nil?}
155
151
  ENV['GALAAZ_BRIDGE_TIMEOUT_SEC'] = #{options[:bridge_timeout_sec].to_s.inspect} if #{!options[:bridge_timeout_sec].nil?}
152
+ ENV['GALAAZ_INSTALL_TIMEOUT_SEC'] = #{options[:install_timeout_sec].to_s.inspect} if #{!options[:install_timeout_sec].nil?}
156
153
  require %q(galaaz)
157
154
  require %q(gknit)
158
155
 
@@ -199,6 +196,11 @@ Dir.chdir(#{input_dir.inspect}) do
199
196
  STDERR.puts "Likely bridge timeout during long-running Ruby->R evaluation."
200
197
  STDERR.puts "Current bridge timeout: \#{bridge_sec} sec; callback timeout: \#{callback_ms} ms."
201
198
  STDERR.puts "Use gknit --bridge_timeout_sec <sec> and/or --callback_timeout_ms <ms> for longer operations."
199
+ elsif e.message.to_s.match?(/install job timed out/i)
200
+ install_sec = ENV['GALAAZ_INSTALL_TIMEOUT_SEC'] || '(none - wait until done)'
201
+ STDERR.puts "Likely R::Job install await timeout."
202
+ STDERR.puts "Current GALAAZ_INSTALL_TIMEOUT_SEC: \#{install_sec}."
203
+ STDERR.puts "Use gknit --install_timeout_sec <sec> (or unset it to wait forever), or install the package outside gknit."
202
204
  end
203
205
  if missing_pkg
204
206
  STDERR.puts "Likely missing LaTeX package: \#{missing_pkg} (install with tlmgr)."
@@ -218,6 +220,7 @@ libx = File.expand_path('../lib', File.dirname(__FILE__))
218
220
  require File.join(libx, 'galaaz_ruby')
219
221
  ENV['GALAAZ_CALLBACK_TIMEOUT_MS'] = options[:callback_timeout_ms].to_s if !options[:callback_timeout_ms].nil?
220
222
  ENV['GALAAZ_BRIDGE_TIMEOUT_SEC'] = options[:bridge_timeout_sec].to_s if !options[:bridge_timeout_sec].nil?
223
+ ENV['GALAAZ_INSTALL_TIMEOUT_SEC'] = options[:install_timeout_sec].to_s if !options[:install_timeout_sec].nil?
221
224
  exec "#{GalaazRuby.shell_invocation(libx)} -e #{Shellwords.escape(code)}"
222
225
 
223
226
  =begin
data/bin/gknit_Rscript CHANGED
@@ -30,9 +30,6 @@ OptionParser.new do |opts|
30
30
  end
31
31
  end.parse!
32
32
 
33
- # Sets the directory
34
- dir = Dir.pwd
35
-
36
33
  #=========================================================================================
37
34
  # Check if the name of the file to gKnit was given and that it exists. If not,
38
35
  # issue error.
@@ -41,7 +38,8 @@ dir = Dir.pwd
41
38
  options[:input_file] = ARGV[0] if !ARGV[0].nil?
42
39
  raise "Input file name is required for gKnitting. Add -f FILE or --input_file FILE. For help, type gknit -h" if
43
40
  options[:input_file].nil?
44
- options[:input_file] = "#{dir}/#{options[:input_file]}"
41
+ # File.expand_path keeps absolute paths intact (do not prefix Dir.pwd).
42
+ options[:input_file] = File.expand_path(options[:input_file])
45
43
  raise "File #{options[:input_file]} does not exist!" if !File.exist?(options[:input_file])
46
44
 
47
45
  #=========================================================================================
data/bin/gstudio_irb.rb CHANGED
@@ -1,36 +1,85 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'galaaz'
2
4
  require 'ggplot'
3
- require 'irb/completion'
4
5
  require 'pp'
6
+ require 'irb'
7
+ require 'reline'
5
8
 
6
- IRB.conf[:PROMPT][:CUSTOM] = {
7
- :PROMPT_I => "galaaz >> ",
8
- :PROMPT_S => "%l>> ",
9
- :PROMPT_C => ".. ",
10
- :PROMPT_N => ".. ",
11
- :RETURN => "=> %s\n"
12
- }
9
+ # --- terminal capability -------------------------------------------------------
13
10
 
14
- IRB.conf[:PROMPT_MODE] = :CUSTOM
11
+ def gstudio_colorize?
12
+ return false unless ENV['NO_COLOR'].to_s.empty?
13
+ return false if ENV['TERM'].to_s == 'dumb'
14
+ true
15
+ end
16
+
17
+ def gstudio_version
18
+ spec = Gem.loaded_specs['galaaz']
19
+ return spec.version.to_s if spec
20
+
21
+ version_rb = File.expand_path('../../version.rb', __FILE__)
22
+ if File.file?(version_rb)
23
+ load version_rb
24
+ return $version.to_s if defined?($version) && $version
25
+ end
26
+
27
+ '?'
28
+ end
29
+
30
+ colorize = gstudio_colorize?
31
+ dumb = ENV['TERM'].to_s == 'dumb'
32
+
33
+ # --- modern IRB defaults (Ruby >= 3.1 / Reline) --------------------------------
34
+
35
+ IRB.conf[:USE_MULTILINE] = !dumb
36
+ IRB.conf[:USE_COLORIZE] = colorize
37
+ IRB.conf[:USE_AUTOCOMPLETE] = !dumb
15
38
  IRB.conf[:AUTO_INDENT] = true
16
39
  IRB.conf[:SAVE_HISTORY] = 1000
17
- IRB.conf[:HISTORY_FILE] = '~/.galaaz.history'
40
+ IRB.conf[:HISTORY_FILE] = File.expand_path('~/.galaaz.history')
41
+ # R-like session: expression results are printed by Galaaz/R, not Ruby inspect.
18
42
  IRB.conf[:ECHO] = false
19
43
 
20
- # history command
21
- def history(count = 0)
44
+ cyan = colorize ? "\e[36m" : ''
45
+ bold = colorize ? "\e[1m" : ''
46
+ reset = colorize ? "\e[0m" : ''
47
+
48
+ IRB.conf[:PROMPT][:CUSTOM] = {
49
+ PROMPT_I: "#{bold}#{cyan}galaaz#{reset} >> ",
50
+ PROMPT_S: '%l>> ',
51
+ PROMPT_C: '.. ',
52
+ PROMPT_N: '.. ',
53
+ RETURN: "=> %s\n"
54
+ }
55
+ IRB.conf[:PROMPT_MODE] = :CUSTOM
56
+
57
+ prior_rc = IRB.conf[:IRB_RC]
58
+ IRB.conf[:IRB_RC] = lambda do |context|
59
+ prior_rc.call(context) if prior_rc.respond_to?(:call)
60
+ puts "Galaaz #{gstudio_version} on #{RUBY_ENGINE} #{RUBY_VERSION} " \
61
+ "(IRB #{IRB::VERSION}). Tab completes; `history` lists input."
62
+ end
22
63
 
23
- # Get history into an array
24
- history_array = Readline::HISTORY.to_a
64
+ # --- session helpers -----------------------------------------------------------
25
65
 
26
- # if count is > 0 we'll use it.
27
- # otherwise set it to 0
28
- count = count > 0 ? count : 0
66
+ module Kernel
67
+ # Print recent input lines. Optional +count+ limits to the last N entries.
68
+ def history(count = 0)
69
+ history_array =
70
+ if defined?(Reline::HISTORY)
71
+ Reline::HISTORY.to_a
72
+ elsif defined?(Readline::HISTORY)
73
+ Readline::HISTORY.to_a
74
+ else
75
+ []
76
+ end
29
77
 
30
- if count > 0
31
- from = hist.length - count
32
- history_array = history_array[from..-1]
33
- end
78
+ if count.is_a?(Integer) && count > 0
79
+ history_array = history_array.last(count)
80
+ end
34
81
 
35
- print history_array.join("\n")
82
+ puts history_array.join("\n")
83
+ nil
84
+ end
36
85
  end
data/blogs/README.md CHANGED
@@ -95,6 +95,6 @@ GALAAZ_DEBUG_R=1 bin/run_example examples/sthda_ggplot/all.rb
95
95
 
96
96
  ## Requirements
97
97
 
98
- - **JRuby** (same as specs/examples).
98
+ - **JRuby** or **CRuby** (same as specs/examples; use `bin/galaaz-ruby` / `GALAAZ_RUBY`).
99
99
  - **R** with packages used by the document (e.g. `rmarkdown`, `knitr`, `ggplot2`).
100
100
  - Run from the project root so `lib` and `bin` resolve correctly.
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  title: "Ruby Plotting with Galaaz"
3
- subtitle: "An example of tightly coupling Ruby and R (JRuby + GNU R, Galaaz 2.0)"
3
+ subtitle: "An example of tightly coupling Ruby and R (JRuby or CRuby + GNU R, Galaaz 2.0)"
4
4
  author: "Rodrigo Botafogo"
5
- tags: [Galaaz, Ruby, R, JRuby, "GNU R", ggplot2]
5
+ tags: [Galaaz, Ruby, R, JRuby, CRuby, "GNU R", ggplot2]
6
6
  date: "16 October 2018 (narrative updated for Galaaz 2.0, 2026)"
7
7
  output:
8
8
  html_document:
@@ -36,11 +36,11 @@ widely used examples among **many thousands** of packages on PyPI for numerical
36
36
  With Galaaz we do not intend to re-implement any of the scientific libraries in R; we allow
37
37
  for very tight coupling between the two languages to the point that the Ruby developer does
38
38
  not need to think about R syntax for every call. **Galaaz 2.0** does this with **[JRuby](https://www.jruby.org/)**
39
- and **GNU R**: a **bridge** evaluates R from Ruby and exchanges data between processes.
39
+ or **CRuby** and **GNU R**: a **bridge** evaluates R from Ruby and exchanges data between processes.
40
40
 
41
41
  An **earlier** Galaaz prototype used Oracle’s **GraalVM** with **TruffleRuby** and **FastR** in one JVM.
42
- That stack is **historical**; today’s documentation and tooling assume **JRuby + GNU R** (see the
43
- project manual and **`bin/galaaz-jruby`** / **`bin/gknit`**).
42
+ That stack is **historical**; today’s documentation and tooling assume **NewBridge on JRuby or CRuby**
43
+ (see the project manual and **`bin/galaaz-ruby`** / **`bin/gknit`**).
44
44
 
45
45
  For background on the old stack:
46
46
 
@@ -68,7 +68,7 @@ Galaaz is the Portuguese name for "Galahad". From Wikipedia:
68
68
 
69
69
  ## Prerequisites (Galaaz 2.0)
70
70
 
71
- * **JRuby** and a compatible **JDK**
71
+ * **JRuby** and a compatible **JDK**, *or* **CRuby 3.3+**
72
72
  * **GNU R** on your `PATH`
73
73
 
74
74
  The following R packages will be automatically installed when necessary, but could be installed prior
@@ -334,5 +334,5 @@ nicely complement R packages.
334
334
 
335
335
  For the Ruby developer, Galaaz allows the immediate use of R functions with minimal ceremony. As
336
336
  shown in the second example above, class `ScatterPlot` hides most R call details from the Ruby
337
- developer. **JRuby** provides **real parallel threads** on the Ruby side and access to the JVM
338
- ecosystem when you need it.
337
+ developer. Prefer **JRuby** when you want **real parallel threads** on the Ruby side and access to
338
+ the JVM ecosystem; **CRuby** works equally for the Galaaz bridge itself.
@@ -12,13 +12,13 @@ With Galaaz we do not intend to re-implement any of the scientific
12
12
  libraries in R; we allow for very tight coupling between the two
13
13
  languages to the point that the Ruby developer does not need to think
14
14
  about R syntax for every call. **Galaaz 2.0** does this with
15
- **[JRuby](https://www.jruby.org/)** and **GNU R**: a **bridge**
15
+ **[JRuby](https://www.jruby.org/)** or **CRuby** and **GNU R**: a **bridge**
16
16
  evaluates R from Ruby and exchanges data between processes.
17
17
 
18
18
  An **earlier** Galaaz prototype used Oracle’s **GraalVM** with
19
19
  **TruffleRuby** and **FastR** in one JVM. That stack is **historical**;
20
- today’s documentation and tooling assume **JRuby + GNU R** (see the
21
- project manual and **`bin/galaaz-jruby`** / **`bin/gknit`**).
20
+ today’s documentation and tooling assume **NewBridge on JRuby or CRuby**
21
+ (see the project manual and **`bin/galaaz-ruby`** / **`bin/gknit`**).
22
22
 
23
23
  For background on the old stack:
24
24
 
@@ -47,7 +47,7 @@ Galaaz is the Portuguese name for “Galahad”. From Wikipedia:
47
47
 
48
48
  ## Prerequisites (Galaaz 2.0)
49
49
 
50
- - **JRuby** and a compatible **JDK**
50
+ - **JRuby** and a compatible **JDK**, *or* **CRuby 3.3+**
51
51
  - **GNU R** on your `PATH`
52
52
 
53
53
  The following R packages will be automatically installed when necessary,
@@ -360,5 +360,5 @@ nicely complement R packages.
360
360
  For the Ruby developer, Galaaz allows the immediate use of R functions
361
361
  with minimal ceremony. As shown in the second example above, class
362
362
  `ScatterPlot` hides most R call details from the Ruby developer.
363
- **JRuby** provides **real parallel threads** on the Ruby side and access
364
- to the JVM ecosystem when you need it.
363
+ Prefer **JRuby** when you want **real parallel threads** on the Ruby side and access
364
+ to the JVM ecosystem; **CRuby** works equally for the Galaaz bridge itself.
@@ -3,7 +3,7 @@ title: "How to do reproducible research in Ruby with gKnit"
3
3
  author:
4
4
  - "Rodrigo Botafogo"
5
5
  - "Daniel Mossé - University of Pittsburgh"
6
- tags: [Tech, Data Science, Ruby, R, JRuby, "GNU R", Galaaz, gKnit, knitr]
6
+ tags: [Tech, Data Science, Ruby, R, JRuby, CRuby, "GNU R", Galaaz, gKnit, knitr]
7
7
  date: "29/04/2019 (narrative updated for Galaaz 2.0, 2026)"
8
8
  bibliography: stats.bib
9
9
  output:
@@ -109,7 +109,7 @@ written both in Ruby and/or R and output it in any of the available formats of _
109
109
  allows ruby developers to do literate programming and reproducible research by allowing them to
110
110
  have in a single document, text and code.
111
111
 
112
- gKnit runs with **JRuby**, **GNU R**, and **Galaaz** (the integration layer between Ruby and R—see below).
112
+ gKnit runs with **JRuby or CRuby**, **GNU R**, and **Galaaz** (the integration layer between Ruby and R—see below).
113
113
  Knitr and **R Markdown** orchestrate the document; Galaaz’s engine keeps **Ruby state across chunks**
114
114
  and talks to R through the **bridge**. Ruby chunks can read and update R variables (`~R[:name]`, `R.*`)
115
115
  without GraalVM-style polyglot interop.
@@ -139,7 +139,7 @@ title: "How to do reproducible research in Ruby with gKnit"
139
139
  author:
140
140
  - "Rodrigo Botafogo"
141
141
  - "Daniel Mossé - University of Pittsburgh"
142
- tags: [Tech, Data Science, Ruby, R, JRuby, "GNU R", Galaaz]
142
+ tags: [Tech, Data Science, Ruby, R, JRuby, CRuby, "GNU R", Galaaz]
143
143
  date: "20/02/2019"
144
144
  output:
145
145
  html_document:
@@ -610,7 +610,8 @@ using even a very complex package as 'caret' is trivial with Galaaz.
610
610
 
611
611
  A word of advice: the 'caret' package has lots of dependencies and installing
612
612
  it in a Linux system is a time consuming operation. Method 'R.install_and_loads'
613
- will install the package if it is not already installed and can take a while.
613
+ will install the package if it is not already installed (via **`R::Job`**: a child
614
+ `Rscript`, so the bridge stays free) and can take a while.
614
615
 
615
616
  ````
616
617
  ```{include model}`r ''`
@@ -633,7 +634,7 @@ puts model.test.head
633
634
  gKnit also allows developers to document and load files that are not in the same directory
634
635
  of the '.Rmd' file.
635
636
 
636
- Here is an example of loading the 'find.rb' file from **JRuby** (via `$LOAD_PATH`). In this example, relative
637
+ Here is an example of loading the 'find.rb' file from Ruby (via `$LOAD_PATH`). In this example, relative
637
638
  is set to FALSE, so Ruby will look for the file in its $LOAD\_PATH, and the user does not
638
639
  need to know its directory.
639
640
 
@@ -657,9 +658,9 @@ the Yaml header to generate this blog in PDF format instead of HTML:
657
658
 
658
659
  ```
659
660
  ---
660
- title: "gKnit - Ruby and R Knitting with Galaaz (JRuby + GNU R)"
661
+ title: "gKnit - Ruby and R Knitting with Galaaz (JRuby or CRuby + GNU R)"
661
662
  author: "Rodrigo Botafogo"
662
- tags: [Galaaz, Ruby, R, JRuby, "GNU R", knitr, gknit]
663
+ tags: [Galaaz, Ruby, R, JRuby, CRuby, "GNU R", knitr, gknit]
663
664
  date: "29 October 2018"
664
665
  output:
665
666
  pdf\_document:
@@ -682,13 +683,13 @@ be imported from files in the system. Ideally, in reproducible research, all th
682
683
  needed to rebuild a report should be easily packed together (in the same zipped directory)
683
684
  and distributed to peers for reexecution.
684
685
 
685
- **Galaaz 2.0** pairs **JRuby** with **GNU R**: you keep the full CRAN/Bioconductor world in R while
686
+ **Galaaz 2.0** pairs **JRuby or CRuby** with **GNU R**: you keep the full CRAN/Bioconductor world in R while
686
687
  writing orchestration, reuse, and application code in Ruby. The effort to wrap Ruby over R (Galaaz)
687
688
  and to wrap Knitr as gKnit was tiny compared to reimplementing R’s ecosystem in Ruby—much like
688
689
  Python’s investment in NumPy and Pandas, which no Ruby project is likely to duplicate.
689
690
 
690
691
  An **earlier** prototype used Oracle’s **GraalVM** and Truffle interop; the **current** stack is
691
- deliberately **standard GNU R** plus the Galaaz **bridge**, documented in the project manual.
692
+ deliberately **standard GNU R** plus the Galaaz **bridge** on JRuby or CRuby, documented in the project manual.
692
693
 
693
694
  More interesting than wrapping the R libraries with Ruby, is that Ruby adds
694
695
  value to R, by allowing developers to use powerful and modern constructs for code reuse that
@@ -700,7 +701,7 @@ readability.
700
701
 
701
702
  ## Prerequisites (Galaaz 2.0)
702
703
 
703
- * **JRuby** and a compatible **JDK**
704
+ * **JRuby** and a compatible **JDK**, *or* **CRuby 3.3+**
704
705
  * **GNU R** on your `PATH`
705
706
 
706
707
  The following R packages will be automatically installed when necessary, but could be installed prior
@@ -720,7 +721,7 @@ the usual build tools are typically enough. On macOS, Xcode command-line tools
720
721
  ## Usage
721
722
 
722
723
  * **`bin/gknit`** \<filename\> (from the Galaaz repo or your install layout); use **`--output_format all`** for HTML and PDF together.
723
- * Run Ruby with **`bin/galaaz-jruby`** when you need the same JVM flags as the project (see the manual).
724
+ * Run Ruby with **`bin/galaaz-ruby`** (either engine) or **`bin/galaaz-jruby`** when you need JRuby JVM flags (see the manual).
724
725
 
725
726
 
726
727
  # References