rich-ri 0.1.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 +7 -0
- data/CHANGELOG.md +57 -0
- data/LICENSE.txt +21 -0
- data/README.md +85 -0
- data/SECURITY.md +55 -0
- data/completions/rich-ri.bash +23 -0
- data/completions/rich-ri.fish +9 -0
- data/completions/rich-ri.zsh +18 -0
- data/docs/compatibility.md +40 -0
- data/docs/config.example.yml +49 -0
- data/docs/configuration.md +254 -0
- data/docs/development.md +110 -0
- data/docs/images/README.md +29 -0
- data/docs/maintenance.md +105 -0
- data/docs/shell-completion.md +51 -0
- data/docs/troubleshooting.md +95 -0
- data/docs/usage.md +147 -0
- data/exe/rich-ri +6 -0
- data/lib/rich_ri/ansi.rb +35 -0
- data/lib/rich_ri/bat.rb +73 -0
- data/lib/rich_ri/cli.rb +112 -0
- data/lib/rich_ri/color.rb +54 -0
- data/lib/rich_ri/completion.rb +135 -0
- data/lib/rich_ri/configuration.rb +177 -0
- data/lib/rich_ri/configuration_options.rb +95 -0
- data/lib/rich_ri/driver.rb +111 -0
- data/lib/rich_ri/formatter.rb +169 -0
- data/lib/rich_ri/highlighter.rb +195 -0
- data/lib/rich_ri/manual.rb +74 -0
- data/lib/rich_ri/options.rb +160 -0
- data/lib/rich_ri/style.rb +48 -0
- data/lib/rich_ri/theme.rb +88 -0
- data/lib/rich_ri/version.rb +5 -0
- data/lib/rich_ri.rb +23 -0
- data/man/man1/rich-ri.1 +419 -0
- metadata +209 -0
data/docs/development.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Development checks
|
|
2
|
+
|
|
3
|
+
Use [Contributing](../CONTRIBUTING.md) for the usual edit, test and PR workflow.
|
|
4
|
+
The commands here cover CI, dependency compatibility and performance work.
|
|
5
|
+
|
|
6
|
+
## Documentation checks
|
|
7
|
+
|
|
8
|
+
For documentation changes, run:
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
bundle exec rake docs:check
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
This checks local links, spelling, the generated manual and runnable examples
|
|
15
|
+
from the usage and configuration guides. It does not need the optional shells
|
|
16
|
+
or system manual tools.
|
|
17
|
+
|
|
18
|
+
CI uses these checks for changes limited to Markdown guides in `docs`, the
|
|
19
|
+
configuration example, PNG comparison images, the PR template and the root README,
|
|
20
|
+
architecture, contribution, changelog, security and code of conduct documents.
|
|
21
|
+
Pull requests also run the commit checks.
|
|
22
|
+
|
|
23
|
+
Code, dependencies, scripts, workflows, test fixtures, the generated manual and
|
|
24
|
+
unrecognized paths run the full suite. CI considers the entire PR, including
|
|
25
|
+
deleted and renamed files; an unavailable comparison also runs the full suite.
|
|
26
|
+
The required `ci` check verifies that every expected job succeeded before a
|
|
27
|
+
change can merge.
|
|
28
|
+
|
|
29
|
+
Releases always run the full suite, including workflow dry runs. Scheduled runs
|
|
30
|
+
check the dependency advisory database.
|
|
31
|
+
|
|
32
|
+
## Shell tests
|
|
33
|
+
|
|
34
|
+
Run completion tests in all three shells with:
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
bundle exec rake test:shells
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The task uses local Bash, Zsh and Fish when all are available and Bash can load
|
|
41
|
+
bash-completion 2.x. Otherwise, it uses a running Docker engine or, if unavailable,
|
|
42
|
+
Podman. `bundle exec rake check` includes this task and requires every shell test
|
|
43
|
+
to pass. The shorter `bundle exec rake` run skips unavailable local integrations.
|
|
44
|
+
|
|
45
|
+
To run in an isolated environment even when the shells are installed:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
bundle exec rake test:shells:container
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The first build downloads the image and installs the locked bundle; later builds
|
|
52
|
+
reuse those layers. Only the project files needed for testing are copied into the
|
|
53
|
+
image. Tests run as an unprivileged user with temporary storage and no network.
|
|
54
|
+
The container uses its pinned Linux/Ruby environment and `Gemfile.lock`, regardless
|
|
55
|
+
of the host Ruby version. CI checks this route as well as native shell integrations
|
|
56
|
+
on Linux and macOS.
|
|
57
|
+
|
|
58
|
+
Set `RICH_RI_CONTAINER_RUNTIME=docker` or `RICH_RI_CONTAINER_RUNTIME=podman` to
|
|
59
|
+
select an engine when running in a container. For example:
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
RICH_RI_CONTAINER_RUNTIME=podman bundle exec rake test:shells:container
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Compatibility checks
|
|
66
|
+
|
|
67
|
+
The main `Gemfile.lock` fixes development dependencies. CI also resolves current
|
|
68
|
+
versions with `bundle update` in a fresh checkout. Run that check in a separate
|
|
69
|
+
checkout to keep your working lockfile intact.
|
|
70
|
+
|
|
71
|
+
To test the minimum runtime dependencies, use Ruby 3.4 with Bash, Zsh, Fish and
|
|
72
|
+
bash-completion 2.x installed locally, then run:
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
BUNDLE_GEMFILE=gemfiles/legacy.gemfile bundle install
|
|
76
|
+
BUNDLE_GEMFILE=gemfiles/legacy.gemfile bundle exec ruby -rrdoc/rdoc -e \
|
|
77
|
+
'RDoc::RDoc.new.document(ARGV)' -- --ri --quiet --op tmp/legacy-ri test/fixtures/example.rb
|
|
78
|
+
BUNDLE_GEMFILE=gemfiles/minimum.gemfile bundle install
|
|
79
|
+
LEGACY_RI_STORE="$PWD/tmp/legacy-ri" BUNDLE_GEMFILE=gemfiles/minimum.gemfile \
|
|
80
|
+
RICH_RI_REQUIRE_SHELLS=1 bundle exec ruby bin/test-compatibility
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The first bundle generates a store using RDoc 6.14. The second runs the runtime
|
|
84
|
+
tests using the minimum direct dependencies compatible with RDoc 8.1, including
|
|
85
|
+
lookup and completion against that older store. Maintenance-only tests and the
|
|
86
|
+
optional server/profiler modes use the main bundle; missing-gem behavior is tested
|
|
87
|
+
with both bundles. `LEGACY_RI_STORE` selects the test store; `RICH_RI_REQUIRE_SHELLS=1`
|
|
88
|
+
requires all shell integrations to be available. This check uses the selected
|
|
89
|
+
minimum bundle and local shells; the container task uses the main locked bundle.
|
|
90
|
+
|
|
91
|
+
When raising a runtime dependency floor, update the minimum Gemfile and
|
|
92
|
+
[compatibility policy](compatibility.md) in the same change.
|
|
93
|
+
|
|
94
|
+
## Performance
|
|
95
|
+
|
|
96
|
+
```sh
|
|
97
|
+
bundle exec ruby bin/benchmark --output /tmp/rich-ri-before.json
|
|
98
|
+
# Make the change, then measure again on the same machine and Ruby.
|
|
99
|
+
bundle exec ruby bin/benchmark --compare /tmp/rich-ri-before.json
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The benchmark measures full CLI startup, rendering and completion against a
|
|
103
|
+
temporary RI store built from a repository fixture. It discards one warm-up
|
|
104
|
+
invocation and reports the median of five runs. `--iterations=N` selects 1 to 50
|
|
105
|
+
runs; `--output=FILE` saves the JSON report.
|
|
106
|
+
|
|
107
|
+
Comparison exits unsuccessfully when a case slows by both more than 30% and
|
|
108
|
+
50 ms. Compare under similar load with the same Ruby and dependency versions;
|
|
109
|
+
small timing differences are not meaningful. CI uploads a `benchmark` artifact
|
|
110
|
+
for each quality run so a reviewer can inspect measurements across changes.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# README comparison
|
|
2
|
+
|
|
3
|
+
`ri-vs-rich-ri.png` compares the original `ri -f ansi` formatter with rich-ri's
|
|
4
|
+
default terminal theme. Both panels show the complete installed `Object#then`
|
|
5
|
+
documentation, from the first line to the last. Its Ruby examples include method
|
|
6
|
+
chains, blocks, strings, constants and symbols.
|
|
7
|
+
|
|
8
|
+
The renderer captures both commands with the project's Bundler environment and
|
|
9
|
+
the same 58-column width, then displays their actual ANSI output using the same
|
|
10
|
+
dark terminal palette and monospace font. It preserves bold, italic,
|
|
11
|
+
underline and reverse-video attributes, including the original formatter's
|
|
12
|
+
inline-code styling. Long code and output lines soft-wrap at the panel width.
|
|
13
|
+
Every output line is included. The displayed commands show normal interactive
|
|
14
|
+
usage; capture adds `--no-pager --width=58` to both, and
|
|
15
|
+
`--no-config --color=always` to rich-ri.
|
|
16
|
+
|
|
17
|
+
To refresh the image, install the bundle, Ruby core RI documentation,
|
|
18
|
+
ImageMagick with SVG support and a monospace font with bold and italic faces.
|
|
19
|
+
The script uses Ruby's standard libraries to capture the output and generate
|
|
20
|
+
an SVG, then ImageMagick to convert it to PNG.
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
ruby docs/images/render_comparison.rb
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The script clears reader configuration overrides and saves the full raw captures
|
|
27
|
+
and SVG in a temporary directory printed at the end. Its footer records the Ruby
|
|
28
|
+
and RDoc versions. Review the PNG before committing it; documentation text can
|
|
29
|
+
change between Ruby versions.
|
data/docs/maintenance.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Maintenance
|
|
2
|
+
|
|
3
|
+
## Release infrastructure
|
|
4
|
+
|
|
5
|
+
`bundle exec rake github:verify` checks branch and tag protections, required CI
|
|
6
|
+
checks, the release environment and security settings. `rake github:setup`
|
|
7
|
+
applies the project policy. Both require repository administrator access.
|
|
8
|
+
|
|
9
|
+
Publication uses [RubyGems Trusted Publishing](https://guides.rubygems.org/trusted-publishing/).
|
|
10
|
+
The publisher must match repository `hvpaiva/rich-ri`, workflow `release.yml`
|
|
11
|
+
and environment `release`. Update that binding in RubyGems if the integration
|
|
12
|
+
changes. `github:verify` checks GitHub settings only.
|
|
13
|
+
|
|
14
|
+
## Release
|
|
15
|
+
|
|
16
|
+
From a clean, up-to-date `main`, with `gh` authenticated and Git signing configured:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
bin/release X.Y.Z --push
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The command prepares the version, changelog and manual, runs the checks, opens a
|
|
23
|
+
release PR, waits for CI, merges, and pushes a signed tag for the merge commit.
|
|
24
|
+
It then watches the Release workflow. Omit `--push` to stop at the PR;
|
|
25
|
+
`--dry-run` previews preparation without writing files or publishing.
|
|
26
|
+
|
|
27
|
+
The workflow reruns CI, validates the tag and branch ancestry, builds one gem,
|
|
28
|
+
and tests installation of that file. It records a SHA-256 checksum and a GitHub
|
|
29
|
+
build attestation. The publication and GitHub Release jobs download that artifact
|
|
30
|
+
and verify its checksum. RubyGems authentication uses short-lived OIDC credentials.
|
|
31
|
+
`rake release` publishes the verified artifact and refuses local execution.
|
|
32
|
+
|
|
33
|
+
To rehearse the workflow without publishing a gem or creating a GitHub Release:
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
gh workflow run release.yml --ref main -f dry_run=true
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Inspect the run in Actions. The rehearsal exercises CI, packaging, installation,
|
|
40
|
+
artifact transfer and attestation; it does not request RubyGems credentials.
|
|
41
|
+
It cannot validate the publisher's authentication with RubyGems.
|
|
42
|
+
|
|
43
|
+
## Verify a download
|
|
44
|
+
|
|
45
|
+
Download the gem and `SHA256SUMS` from its GitHub Release, then run:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
sha256sum --check SHA256SUMS
|
|
49
|
+
gh attestation verify rich-ri-X.Y.Z.gem --repo hvpaiva/rich-ri --source-ref refs/tags/vX.Y.Z
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
On macOS, use `shasum -a 256 --check SHA256SUMS`. The attestation binds the artifact
|
|
53
|
+
to its source and workflow. Release tags and published GitHub releases are immutable.
|
|
54
|
+
|
|
55
|
+
## Recover an interrupted release
|
|
56
|
+
|
|
57
|
+
Run the same `bin/release` command again. It inspects existing branches, PRs,
|
|
58
|
+
commits and tags before continuing. It never replaces an existing tag.
|
|
59
|
+
|
|
60
|
+
If a workflow failed before publication, correct the problem and follow the
|
|
61
|
+
printed retry command. If RubyGems publication succeeded and only GitHub Release
|
|
62
|
+
creation failed, retry that job alone. When the publication result is uncertain,
|
|
63
|
+
check RubyGems before retrying: an accepted version must not be pushed again.
|
|
64
|
+
|
|
65
|
+
## Urgent fixes
|
|
66
|
+
|
|
67
|
+
Only the latest released version receives fixes. If `main` contains unfinished
|
|
68
|
+
work for the next release, start a hotfix branch at the latest released tag.
|
|
69
|
+
For example, to fix `0.2.0` while `main` is preparing `0.3.0`:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
git switch -c hotfix/0.2 v0.2.0
|
|
73
|
+
git push -u origin hotfix/0.2
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Create a topic branch from it and submit the fix as a PR against `hotfix/0.2`.
|
|
77
|
+
Hotfix branches have the same protections as `main`. After the fix is merged,
|
|
78
|
+
update the local hotfix branch and run:
|
|
79
|
+
|
|
80
|
+
```sh
|
|
81
|
+
bin/release 0.2.1 --branch hotfix/0.2 --push
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The release must match the branch's major and minor version. Bring the fix and
|
|
85
|
+
release notes back to `main` through a separate PR, preserving changes still under
|
|
86
|
+
`Unreleased` and keeping dated changelog entries newest first.
|
|
87
|
+
|
|
88
|
+
If a published version must be withdrawn, publish a fixed version first when
|
|
89
|
+
possible. Explain the withdrawal in its changelog entry, then use
|
|
90
|
+
`gem yank rich-ri -v X.Y.Z` with your personal RubyGems credentials and MFA.
|
|
91
|
+
Trusted publishing only grants push access. A withdrawn version cannot be reused;
|
|
92
|
+
publish a new version number for the replacement.
|
|
93
|
+
|
|
94
|
+
## Dependencies and access
|
|
95
|
+
|
|
96
|
+
Dependabot proposes gem and test-image updates weekly and action updates monthly. Review the
|
|
97
|
+
upstream changes and run the same checks as other PRs. A runtime dependency change
|
|
98
|
+
may need a changelog entry even when Dependabot supplied `skip-changelog`.
|
|
99
|
+
Update `gemfiles/minimum.gemfile` when raising a supported dependency floor.
|
|
100
|
+
The scheduled audit checks the lockfile for known vulnerabilities.
|
|
101
|
+
|
|
102
|
+
Review repository administrators, RubyGems owners and publisher configuration
|
|
103
|
+
when maintainers change. Keep account recovery methods current and transfer both
|
|
104
|
+
services when handing over the project. Review changes to release code and
|
|
105
|
+
workflows with particular care; they run with publication or attestation permissions.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Shell completion
|
|
2
|
+
|
|
3
|
+
Completion reads the active Ruby's RI stores, including sources selected in your
|
|
4
|
+
configuration file, `RI` or `--doc-dir`. It makes no network requests. It suggests
|
|
5
|
+
installed classes, methods, pages, options, theme names and style roles, with
|
|
6
|
+
descriptions where available. Invalid configuration or unavailable stores prevent
|
|
7
|
+
documentation-name suggestions; options and theme values remain available. Run
|
|
8
|
+
`rich-ri --show-config` to diagnose configuration errors.
|
|
9
|
+
|
|
10
|
+
## Bash
|
|
11
|
+
|
|
12
|
+
Load bash-completion 2.x in your shell, then install the lazy-loaded script:
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
mkdir -p "${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion/completions"
|
|
16
|
+
rich-ri --completion=bash > "${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion/completions/rich-ri"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
To load it in the current shell, run `source <(rich-ri --completion=bash)`.
|
|
20
|
+
|
|
21
|
+
## Zsh
|
|
22
|
+
|
|
23
|
+
After `autoload -Uz compinit && compinit` in your `.zshrc`, add:
|
|
24
|
+
|
|
25
|
+
```zsh
|
|
26
|
+
source <(rich-ri --completion=zsh)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Fish
|
|
30
|
+
|
|
31
|
+
```fish
|
|
32
|
+
mkdir -p "$__fish_config_dir/completions"
|
|
33
|
+
rich-ri --completion=fish > "$__fish_config_dir/completions/rich-ri.fish"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Use the short name ri
|
|
37
|
+
|
|
38
|
+
For Bash, add these lines after loading bash-completion:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
alias ri='rich-ri'
|
|
42
|
+
source <(rich-ri --completion=bash)
|
|
43
|
+
complete -o filenames -F _rich_ri ri
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
For Zsh, add `alias ri='rich-ri'` after the completion setup. Zsh expands aliases
|
|
47
|
+
for completion by default. In Fish, use `alias ri rich-ri` in your configuration;
|
|
48
|
+
Fish aliases inherit completions from the wrapped command.
|
|
49
|
+
|
|
50
|
+
Bash and Fish install a copy of the script; repeat the installation after upgrading
|
|
51
|
+
rich-ri. The Zsh setup loads the current script when a new shell starts.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
## A page is missing
|
|
4
|
+
|
|
5
|
+
Check `rich-ri --list` for known classes and `rich-ri --list-doc-dirs` for the
|
|
6
|
+
directories being searched. Try `ri NAME` with the original reader as well.
|
|
7
|
+
If you use an alias, `command ri NAME` bypasses it in Bash and Zsh.
|
|
8
|
+
|
|
9
|
+
For a gem installed without documentation, run `gem rdoc GEM_NAME --ri`.
|
|
10
|
+
For Ruby's core classes, install the documentation package supplied by your Ruby
|
|
11
|
+
manager or operating system. Switch to the intended Ruby before generating or
|
|
12
|
+
reading documentation: each installation has its own stores.
|
|
13
|
+
|
|
14
|
+
See [documentation sources](usage.md#documentation-sources-and-missing-pages)
|
|
15
|
+
to read documentation from a project directory.
|
|
16
|
+
|
|
17
|
+
## An RI cache has an incompatible format
|
|
18
|
+
|
|
19
|
+
RDoc uses different serialized markup representations on Ruby 3 and Ruby 4.
|
|
20
|
+
Keep documentation with the Ruby installation that generated it. Regenerate gem
|
|
21
|
+
documentation with `gem rdoc GEM_NAME --ri` under the Ruby you are using now.
|
|
22
|
+
|
|
23
|
+
For core documentation, obtain the source for that Ruby version, then generate a
|
|
24
|
+
new RI store with the current RDoc. For example, from the Ruby source directory:
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
rdoc --ri --op doc/ri
|
|
28
|
+
rich-ri --no-standard-docs --doc-dir doc/ri Array
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Use [doc_dirs](configuration.md#file-keys) to keep using the new store. Do not
|
|
32
|
+
copy a cache from another Ruby installation as a substitute for regeneration.
|
|
33
|
+
|
|
34
|
+
## Colors are missing or hard to read
|
|
35
|
+
|
|
36
|
+
Colors are enabled automatically on a terminal. `NO_COLOR`, `TERM=dumb` and
|
|
37
|
+
redirected output disable automatic colors. Try `rich-ri --color=always NAME`
|
|
38
|
+
to force them, or `rich-ri --no-color NAME` for plain output.
|
|
39
|
+
|
|
40
|
+
The default theme uses the terminal's palette. Adjust a role such as
|
|
41
|
+
`--style='comment=bright_black'`, or select `--theme=light` or `--theme=dark`.
|
|
42
|
+
[Themes and styles](configuration.md#themes-and-styles) describes persistent settings.
|
|
43
|
+
|
|
44
|
+
Ruby highlighting is built in. Shell examples and other tagged languages need
|
|
45
|
+
bat on `PATH`; confirm it with `bat --version`. If bat fails or cannot safely
|
|
46
|
+
highlight an example, that example stays plain. A failure disables bat for the
|
|
47
|
+
rest of the page. `--shell-theme` and `--bat-theme` must name an installed bat
|
|
48
|
+
theme; list them with `bat --list-themes`.
|
|
49
|
+
|
|
50
|
+
## The pager behaves differently
|
|
51
|
+
|
|
52
|
+
Try `rich-ri --no-pager NAME` to isolate the reader from the pager.
|
|
53
|
+
`RI_PAGER` takes precedence over `PAGER`; a configured pager command and
|
|
54
|
+
`--pager-command` can also select it. Check the effective settings with
|
|
55
|
+
`rich-ri --show-config`. For less, rich-ri adds `-R` so ANSI colors are displayed.
|
|
56
|
+
|
|
57
|
+
## An optional RDoc mode cannot start
|
|
58
|
+
|
|
59
|
+
`--server` needs the `webrick` gem; `--profile` needs the `profile` gem. Install
|
|
60
|
+
the named gem with the active Ruby, then repeat the command. For example,
|
|
61
|
+
`gem install webrick` enables the web server. With `bundle exec`, include the
|
|
62
|
+
gem in the current Gemfile as well.
|
|
63
|
+
|
|
64
|
+
These gems are not required for terminal lookup or completion. See
|
|
65
|
+
[optional RDoc modes](usage.md#optional-rdoc-modes) for their behavior.
|
|
66
|
+
|
|
67
|
+
## Configuration prevents startup
|
|
68
|
+
|
|
69
|
+
`rich-ri --config-path` prints the selected file. `--no-config` skips that file;
|
|
70
|
+
environment variables still apply. Help and version output remain available
|
|
71
|
+
even when the file contains invalid YAML or settings.
|
|
72
|
+
|
|
73
|
+
See [configuration troubleshooting](configuration.md#troubleshooting) for
|
|
74
|
+
precedence, YAML types and path handling.
|
|
75
|
+
|
|
76
|
+
## Tab completion is missing
|
|
77
|
+
|
|
78
|
+
Follow the setup for your shell in [shell completion](shell-completion.md).
|
|
79
|
+
After changing a shell startup file, open a new shell or load the file again.
|
|
80
|
+
For an alias, include the alias setup from that guide.
|
|
81
|
+
|
|
82
|
+
If options complete but documentation names do not, check `--show-config` and
|
|
83
|
+
`--list-doc-dirs`. Invalid settings or an unreadable RI store prevent name
|
|
84
|
+
discovery. Bash and Fish completion scripts should be reinstalled after an upgrade.
|
|
85
|
+
|
|
86
|
+
## Report a problem
|
|
87
|
+
|
|
88
|
+
Include the command, expected result, actual result and a small document that
|
|
89
|
+
reproduces it. Provide `rich-ri --version`, `ruby --version`, your operating
|
|
90
|
+
system, shell and terminal, and the output of `gem list --local rdoc prism reline`.
|
|
91
|
+
For shell highlighting, include `bat --version` too.
|
|
92
|
+
|
|
93
|
+
Review any configuration output before sharing it; pager arguments and file
|
|
94
|
+
paths can contain private information. Open a [bug report](https://github.com/hvpaiva/rich-ri/issues/new?template=bug.yml).
|
|
95
|
+
Use the [private security channel](../SECURITY.md) for vulnerabilities.
|
data/docs/usage.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Reading documentation
|
|
2
|
+
|
|
3
|
+
Names follow RI conventions. Use `Class#method` for instance methods,
|
|
4
|
+
`Class::method` for class methods, and `Class.method` to search both.
|
|
5
|
+
Quote names containing shell punctuation, such as `rich-ri 'Array.[]'`.
|
|
6
|
+
Write long options in full; abbreviations are not accepted.
|
|
7
|
+
|
|
8
|
+
Run `rich-ri` without arguments for RI's interactive lookup. Its Tab completion
|
|
9
|
+
is extended with documentation pages and method prefixes such as `String#`,
|
|
10
|
+
`String.` and `String::`; submit an empty line to leave. With shell completion
|
|
11
|
+
installed, you can also find classes, methods, pages and options before running a command:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
rich-ri Str<Tab>
|
|
15
|
+
rich-ri String#<Tab>
|
|
16
|
+
rich-ri String.<Tab>
|
|
17
|
+
rich-ri ruby:<Tab>
|
|
18
|
+
rich-ri --<Tab>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
In less, use `/` to search, `n` for the next match, Space for the next page and
|
|
22
|
+
`q` to return. `--no-pager` writes directly to stdout.
|
|
23
|
+
|
|
24
|
+
Headings keep their RDoc level markers (`=`, `==`, through `======`), in the
|
|
25
|
+
same style as the heading text. Horizontal separators use plain hyphens in a
|
|
26
|
+
muted style. Search for `^=== ` to find level-three headings or `^---` to find
|
|
27
|
+
separators, then use `n` and `N` to move between matches. These markers remain
|
|
28
|
+
available with colors disabled.
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
rich-ri --all Array
|
|
32
|
+
rich-ri --width=72 String#scan
|
|
33
|
+
rich-ri --color=always Array#map | less -R
|
|
34
|
+
rich-ri --no-color Hash
|
|
35
|
+
rich-ri --format=markdown Array#map
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`--format` selects an original RDoc formatter. Otherwise, disabling colors
|
|
39
|
+
preserves rich-ri's page layout. Code blocks keep their content and indentation;
|
|
40
|
+
prose wraps by visible terminal width, including wide Unicode characters.
|
|
41
|
+
|
|
42
|
+
## Documentation sources and missing pages
|
|
43
|
+
|
|
44
|
+
rich-ri reads installed documentation; it does not download documentation or
|
|
45
|
+
generate it while you browse. `rich-ri --list-doc-dirs` shows the searched paths,
|
|
46
|
+
and `rich-ri --list` lists known classes.
|
|
47
|
+
|
|
48
|
+
If a gem was installed with `--no-document`, generate its RI documentation with
|
|
49
|
+
`gem rdoc GEM_NAME --ri`. Ruby core documentation depends on how your Ruby was
|
|
50
|
+
installed; install the documentation package supplied by your Ruby manager or OS.
|
|
51
|
+
|
|
52
|
+
### Read your project's documentation
|
|
53
|
+
|
|
54
|
+
Save this small example as `greeter.rb`:
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
class Greeter
|
|
58
|
+
# Returns a greeting for the given name.
|
|
59
|
+
#
|
|
60
|
+
# Greeter.new.greet("Ruby") # => "Hello, Ruby!"
|
|
61
|
+
def greet(name)
|
|
62
|
+
"Hello, #{name}!"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Generate its documentation and read the method:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
rdoc --ri --quiet --op doc/ri greeter.rb
|
|
71
|
+
rich-ri --no-standard-docs --doc-dir doc/ri --no-color --no-pager --width=60 Greeter#greet
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The output below abbreviates the current directory as `.`:
|
|
75
|
+
|
|
76
|
+
```text
|
|
77
|
+
= Greeter#greet
|
|
78
|
+
|
|
79
|
+
(from ./doc/ri)
|
|
80
|
+
------------------------------------------------------------
|
|
81
|
+
greet(name)
|
|
82
|
+
|
|
83
|
+
------------------------------------------------------------
|
|
84
|
+
|
|
85
|
+
Returns a greeting for the given name.
|
|
86
|
+
|
|
87
|
+
Greeter.new.greet("Ruby") # => "Hello, Ruby!"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
To use the same documentation sources for lookup and shell completion, configure
|
|
91
|
+
`RI` in the current shell:
|
|
92
|
+
|
|
93
|
+
| Shell | Command |
|
|
94
|
+
| --- | --- |
|
|
95
|
+
| Bash or Zsh | `export RI='--no-standard-docs --doc-dir doc/ri'` |
|
|
96
|
+
| Fish | `set -gx RI '--no-standard-docs --doc-dir doc/ri'` |
|
|
97
|
+
|
|
98
|
+
Only open RI stores you trust. RI caches use Ruby Marshal serialization; see
|
|
99
|
+
[security policy](../SECURITY.md) for the trust boundary.
|
|
100
|
+
|
|
101
|
+
## Manual
|
|
102
|
+
|
|
103
|
+
`rich-ri --help` lists the options. `rich-ri --man` opens the full manual.
|
|
104
|
+
To make the page available through `man rich-ri`, run `rich-ri --install-man`.
|
|
105
|
+
The command prints its destination and any needed `MANPATH` setting. Repeat it
|
|
106
|
+
when upgrading. Use `--install-man=DIR` to choose another `man1` directory.
|
|
107
|
+
|
|
108
|
+
## Optional programs
|
|
109
|
+
|
|
110
|
+
Ruby highlighting is built in. bat adds highlighting for shell commands and
|
|
111
|
+
other tagged languages. less, or another RI-compatible pager, provides scrolling
|
|
112
|
+
and search. `man` opens the bundled manual. These programs are available from
|
|
113
|
+
your operating system's package manager.
|
|
114
|
+
|
|
115
|
+
Without bat, those code blocks stay plain. If no pager is available, documentation
|
|
116
|
+
is written to the terminal; `--no-pager` selects this behavior explicitly.
|
|
117
|
+
`--help` and `--install-man` work without the `man` program.
|
|
118
|
+
|
|
119
|
+
## Optional RDoc modes
|
|
120
|
+
|
|
121
|
+
`rich-ri --server` starts RDoc's documentation web server on port 8214;
|
|
122
|
+
`--server=PORT` selects another port. This mode requires the `webrick` gem:
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
gem install webrick
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The server uses RDoc's web interface and network defaults, including listening
|
|
129
|
+
on all interfaces. Stop it with Ctrl-C. rich-ri's terminal themes do not apply
|
|
130
|
+
to the web pages.
|
|
131
|
+
|
|
132
|
+
`--profile` runs Ruby's profiler while reading documentation and prints timing
|
|
133
|
+
information when the command exits. It requires the `profile` gem:
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
gem install profile
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Install either gem for the same Ruby that runs rich-ri. Neither is needed for
|
|
140
|
+
normal terminal lookup, highlighting or completion. Missing optional gems produce
|
|
141
|
+
an installation hint and exit status 1. When running through Bundler, add the
|
|
142
|
+
needed gem to that bundle too.
|
|
143
|
+
|
|
144
|
+
## Exit status
|
|
145
|
+
|
|
146
|
+
The command exits with 0 on success, 1 for lookup or usage errors and 130 when
|
|
147
|
+
interrupted. A closed output pipe is a normal exit.
|
data/exe/rich-ri
ADDED
data/lib/rich_ri/ansi.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RichRI
|
|
4
|
+
SGR = /\e\[[\d;]*m/
|
|
5
|
+
RESET = "\e[0m"
|
|
6
|
+
COLORS = {
|
|
7
|
+
title: "1;36", heading: "1;34", subheading: "1;35",
|
|
8
|
+
code: "36", reference: "36", link: "4;36", label: "1;33",
|
|
9
|
+
muted: "90", emphasis: "3", bold: "1", strike: "9",
|
|
10
|
+
keyword: "35", string: "32", number: "33", constant: "33",
|
|
11
|
+
symbol: "33", method: "36", comment: "90", operator: "35"
|
|
12
|
+
}.freeze
|
|
13
|
+
|
|
14
|
+
def self.plain(text)
|
|
15
|
+
text.gsub(SGR, "")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Documentation may contain literal terminal controls. Show them as text;
|
|
19
|
+
# only styles produced by this reader may reach the terminal as escapes.
|
|
20
|
+
def self.sanitize(text)
|
|
21
|
+
text.gsub(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f\u0080-\u009f\u202a-\u202e\u2066-\u2069]|\r(?!\n)/) do |char|
|
|
22
|
+
format("\\u%04x", char.ord)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.width(text)
|
|
27
|
+
Reline::Unicode.calculate_width(text, true)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Each word has balanced SGRs: less resets colors at newlines, and wrapping
|
|
31
|
+
# must never make a style bleed into the next paragraph or the shell prompt.
|
|
32
|
+
def self.paint(text, *roles, enabled: true)
|
|
33
|
+
Theme.new.paint(text, *roles, enabled:)
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/rich_ri/bat.rb
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RichRI
|
|
4
|
+
# Optional highlighting must not prevent the reader from displaying a page.
|
|
5
|
+
class Bat
|
|
6
|
+
TIMEOUT = 2
|
|
7
|
+
MAX_INPUT = 1_048_576
|
|
8
|
+
MAX_OUTPUT = 8_388_608
|
|
9
|
+
|
|
10
|
+
def initialize(timeout: TIMEOUT, max_output: MAX_OUTPUT)
|
|
11
|
+
@timeout = timeout
|
|
12
|
+
@max_output = max_output
|
|
13
|
+
@available = true
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def highlight(text, language:, theme:)
|
|
17
|
+
return unless @available && text.bytesize <= MAX_INPUT
|
|
18
|
+
|
|
19
|
+
output = capture(text, language, theme)
|
|
20
|
+
output&.force_encoding(text.encoding)
|
|
21
|
+
output = output.delete_suffix("\n") if output && !text.end_with?("\n") && output.end_with?("\n")
|
|
22
|
+
return output if output&.valid_encoding? && RichRI.plain(output) == text
|
|
23
|
+
|
|
24
|
+
@available = false
|
|
25
|
+
nil
|
|
26
|
+
rescue SystemCallError, IOError, Timeout::Error
|
|
27
|
+
@available = false
|
|
28
|
+
nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def capture(text, language, theme)
|
|
34
|
+
args = ["bat", "--no-config", "--language=#{language}", "--style=plain", "--color=always",
|
|
35
|
+
"--paging=never", "--wrap=never", "--theme=#{theme}"]
|
|
36
|
+
Open3.popen2(*args, err: File::NULL, pgroup: true) do |input, output, waiter|
|
|
37
|
+
completed = false
|
|
38
|
+
writer = Thread.new { write(input, text) }
|
|
39
|
+
Timeout.timeout(@timeout) do
|
|
40
|
+
result = output.read(@max_output + 1).to_s
|
|
41
|
+
next if result.bytesize > @max_output
|
|
42
|
+
|
|
43
|
+
writer.value
|
|
44
|
+
status = waiter.value
|
|
45
|
+
completed = true
|
|
46
|
+
result if status.success?
|
|
47
|
+
end
|
|
48
|
+
ensure
|
|
49
|
+
writer&.kill
|
|
50
|
+
terminate(waiter) unless completed
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def write(input, text)
|
|
55
|
+
input.write(text)
|
|
56
|
+
rescue Errno::EPIPE, IOError
|
|
57
|
+
nil
|
|
58
|
+
ensure
|
|
59
|
+
input.close unless input.closed?
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def terminate(waiter)
|
|
63
|
+
Process.kill("TERM", -waiter.pid)
|
|
64
|
+
waiter.join(0.1)
|
|
65
|
+
# Descendants may still hold pipes open after their parent exits.
|
|
66
|
+
Process.kill("KILL", -waiter.pid)
|
|
67
|
+
rescue Errno::ESRCH
|
|
68
|
+
nil
|
|
69
|
+
ensure
|
|
70
|
+
waiter.join
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|