Skip to content

Commit

Permalink
cli, completion: compress some const strings (#652)
Browse files Browse the repository at this point in the history
This uses `supersnappy` [1], which is a zero-dependency pure-Nim
implementation of Google's Snappy [2].

With it, it is straightforward to compress our larger `const` strings
at compile time and uncompress them at run time. For now, this commit
compresses:

- The `configlet --help` message
- The completion scripts

`supersnappy` is less than 500 lines of code, which is why compressing
these strings (which aren't so large) produces a slightly smaller
configlet binary, despite the added dependency.

We may end up adding `zippy` [3] as a dependency if configlet learns
to make network requests (e.g. for the online `configlet lint` checks)
so that we can use gzip. But we can't use `zippy` at compile time, so it
isn't useful for this commit, even though the compression is better.
`zippy` is also a bigger dependency (about 40 KiB), so it wouldn't
produce a net saving for this commit anyway.

`nim-snappy` [4] is an alternative Snappy implementation, but it would
add dependencies [5] on `faststreams`, `unittest2`, and `stew`.

[1] https://github.com/guzba/supersnappy
[2] https://github.com/google/snappy
[3] https://github.com/guzba/zippy
[4] https://github.com/status-im/nim-snappy
[5] https://github.com/status-im/nim-snappy/blob/7cb2e57a5861/snappy.nimble

Closes: #651
  • Loading branch information
ee7 authored Aug 9, 2022
1 parent 4447bd2 commit 1d689ed
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 12 deletions.
11 changes: 6 additions & 5 deletions configlet.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,19 @@ bin = @["configlet"]

# Dependencies
requires "nim >= 1.6.6"
requires "cligen#b962cf8bc0be847cbc1b4f77952775de765e9689" # 1.5.19 (2021-09-13)
requires "jsony#2a2cc4331720b7695c8b66529dbfea6952727e7b" # 1.1.3 (2022-01-03)
requires "parsetoml#9cdeb3f65fd10302da157db8a8bac5c42f055249" # 0.6.0 (2021-06-07)
requires "uuids#8cb8720b567c6bcb261bd1c0f7491bdb5209ad06" # 0.1.11 (2021-01-15)
requires "cligen#b962cf8bc0be847cbc1b4f77952775de765e9689" # 1.5.19 (2021-09-13)
requires "jsony#2a2cc4331720b7695c8b66529dbfea6952727e7b" # 1.1.3 (2022-01-03)
requires "parsetoml#9cdeb3f65fd10302da157db8a8bac5c42f055249" # 0.6.0 (2021-06-07)
requires "supersnappy#e4df8cb5468dd96fc5a4764028e20c8a3942f16a" # 2.1.3 (2022-06-12)
requires "uuids#8cb8720b567c6bcb261bd1c0f7491bdb5209ad06" # 0.1.11 (2021-01-15)
# To make Nimble use the pinned `isaac` version, we must pin `isaac` after `uuids`
# (which has `isaac` as a dependency).
# Nimble still clones the latest `isaac` tag if there is no tag-versioned one
# on-disk (e.g. at ~/.nimble/pkgs/isaac-0.1.3), and adds it to the path when
# building, but (due to writing it later) the pinned version takes precedence.
# Nimble will support lock files in the future, which should provide more robust
# version pinning.
requires "isaac#45a5cbbd54ff59ba3ed94242620c818b9aad1b5b" # 0.1.3 (2017-11-16)
requires "isaac#45a5cbbd54ff59ba3ed94242620c818b9aad1b5b" # 0.1.3 (2017-11-16)

task test, "Runs the test suite":
exec "nim r ./tests/all_tests.nim"
Expand Down
10 changes: 5 additions & 5 deletions src/cli.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import std/[os, parseutils, strformat, strutils, terminal]
import pkg/cligen/parseopt3
import pkg/[cligen/parseopt3, supersnappy]

type
ActionKind* = enum
Expand Down Expand Up @@ -295,9 +295,9 @@ func genHelpText: string =
setLen(result, result.len - 1)

proc showHelp(exitCode: range[0..255] = 0) =
const helpText = genHelpText()
const helpText = genHelpText().compress()
let f = if exitCode == 0: stdout else: stderr
f.writeLine helpText
f.writeLine helpText.uncompress()
if f == stdout:
f.flushFile()
quit(exitCode)
Expand Down Expand Up @@ -415,8 +415,8 @@ proc parseOption(kind: CmdLineKind, key: string, val: string): Opt =
user's cache directory - there is no longer an option to configure the location.
Performing an offline sync now requires only one option (--offline), but you
must first run a `configlet sync` command without --offline at least once on
your machine.""".unindent()
stderr.writeLine msg
your machine.""".unindent().compress()
stderr.writeLine msg.uncompress()
showError(&"invalid option: {formatOpt(kind, key)}")

proc parseVal[T: enum](kind: CmdLineKind, key: string, val: string): T =
Expand Down
5 changes: 3 additions & 2 deletions src/completion/completion.nim
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import std/[os, strformat]
import pkg/supersnappy
import ../cli

proc readCompletions: array[Shell, string] =
const repoRootDir = currentSourcePath().parentDir().parentDir().parentDir()
const completionsDir = repoRootDir / "completions"
for shell in sBash .. result.high:
result[shell] = staticRead(completionsDir / &"configlet.{shell}")
result[shell] = staticRead(completionsDir / &"configlet.{shell}").compress()

proc completion*(shellKind: Shell) =
const completions = readCompletions()
stdout.write completions[shellKind]
stdout.write completions[shellKind].uncompress()

0 comments on commit 1d689ed

Please sign in to comment.