Skip to content

Instantly share code, notes, and snippets.

@igor-ramazanov
Last active September 9, 2025 16:23
Show Gist options
  • Select an option

  • Save igor-ramazanov/2b6145a8bfb83c9986ce426fc6f145d2 to your computer and use it in GitHub Desktop.

Select an option

Save igor-ramazanov/2b6145a8bfb83c9986ce426fc6f145d2 to your computer and use it in GitHub Desktop.
Bloop + Nushell + ScalaCLI
def projects []: nothing -> table<value: string> {
bloop autocomplete --format fish --mode projects e> /dev/null
| lines
| wrap value
}
def commands []: nothing -> table<value: string> {
bloop autocomplete --format fish --mode commands e> /dev/null
| lines
| wrap value
}
def boolean []: nothing -> table<value: string> {
["true" "false"] | wrap value
}
def reporters []: nothing -> table<value: string> {
bloop autocomplete --format fish --mode reporters e> /dev/null
| lines
| wrap value
}
def protocols []: nothing -> table<value: string> {
bloop autocomplete --format fish --mode protocols e> /dev/null
| lines
| wrap value
}
def project_commands []: nothing -> list<string> {
bloop autocomplete --format fish --mode project-commands e> /dev/null
| split row " "
}
def testsfqcn [project:string]: nothing -> table<value> {
bloop autocomplete --format fish --mode testsfqcn --project $project e> /dev/null
| lines
| wrap value
}
def mainsfqcn [project:string]: nothing -> table<value> {
bloop autocomplete --format fish --mode mainsfqcn --project $project e> /dev/null
| lines
| wrap value
}
def flags_for_command [command:string]: nothing -> table<value: string, description: string, completer: string> {
bloop autocomplete --format fish --mode flags --command $command e> /dev/null
| lines
| parse --regex "^(?<value>[^#]+)#(?<description>[^#]+)#(?<completer>.*)$"
| upsert value {|line| $"--($line.value)"}
| upsert description {|line| $line.description | str substring 1..-3}
| upsert completer {|line| $line.completer | str substring 2..-2 }
}
export def main [
--debug
--spans:any
] {
def log [
name:string
data:any
]: nothing -> nothing {
if $debug {
$data | to json | save --force $"($env.PWD)/($name).json"
}
}
let flags: table<command: string, flags: table<value: string, description: string, completer: string>> = project_commands
| each {|command|
{
command: $command
flags: (flags_for_command $command)
}
}
log "spans" $spans
log "flags" $flags
let test_provided = $spans | window 2 | any {|w| $w.0 in ["--only" "-o"] and not ($w.1 | is-empty)}
if (($spans | length) == 2 and ($spans | last | is-empty)) or ($spans | length) == 1 {
commands
} else {
let command = $spans.1
log "command" $command
if $command in project_commands and ($spans | length) == 2 or (($spans | length) == 3 and ($spans | last | is-empty)) {
projects
} else {
let project = $spans.2
log "project" $project
let test_only_requested = $spans | any {|span| $span == "--only" or $span == "-o"}
log "test_only_requested" $test_only_requested
let test_only_provided = $spans | window 2 | any {|w|
$w.0 in ["--only" "-o"] and not (
($w.1 | is-empty) or ($w.1 | str ends-with '.')
)
}
log "test_only_provided" $test_only_provided
if $command == "test" and $test_only_requested and not $test_only_provided {
testsfqcn $project
} else {
let main_requested = $spans | any {|span| $span == "--main" or $span == "-m"}
log "main_requested" $main_requested
let main_provided = $spans | window 2 | any {|w|
$w.0 in ["--main" "-m"] and not (
($w.1 | is-empty) or ($w.1 | str ends-with '.')
)
}
log "main_provided" $main_provided
if $command == "run" and $main_requested and not $main_provided {
mainsfqcn $project
} else {
let command_flags = $flags | where command == $command | get 0.flags
log "command_flags" $command_flags
if ($spans | last) == '--' {
$command_flags | reject completer
} else {
let flag = $spans | last 2 | first
let completer = $command_flags | where value == $flag | get 0.completer --optional
log "completer" $completer
match $completer {
"reporters" => {reporters}
"boolean" => {boolean}
_ => {}
}
}
}
}
}
}
}
def projects []: nothing -> list<string> {
bloop projects | lines
}
# Run `script` as ScalaCLI script in context of `project`.
export def "bloop run-script" [
project:string@projects # Bloop project to be converted into ScalaCLI args.
script:path # Script to run.
]: nothing -> nothing {
run-external scala-cli run ...(bloop_project_scala_cli_args $project | append $script)
}
# Start ScalaCLI REPL in context of `project`.
export def "bloop console" [
project:string@projects # Bloop project to be converted into ScalaCLI args.
]: nothing -> nothing {
run-external scala-cli repl ...(bloop_project_scala_cli_args $project)
}
# Convert `.bloop/<project>.json` to ScalaCLI args.
def bloop_project_scala_cli_args [
project:string@projects # Bloop project to be converted into ScalaCLI args.
]: nothing -> list<string> {
let project_metadata = open $".bloop/($project).json" | get project
let deps = $project_metadata | get classpath
let classes = $project_metadata | get classesDir
let classpath = $deps | append $classes | str join ':'
let resources = $project_metadata
| get resources
| where {|dir| $dir | path exists }
| each {|dir| $"--resource-dir=($dir)" }
let scala_version = $project_metadata | get scala.version
let scalac_options = $project_metadata
| get scala.options
| each {|option| $"--scalac-option=($option)" }
let directory = $project_metadata | get directory
[
$"--class-path=($classpath)"
...($resources)
$"--scala-version=($scala_version)"
...($scalac_options)
$directory
] | flatten
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment