Last active
September 9, 2025 16:23
-
-
Save igor-ramazanov/2b6145a8bfb83c9986ce426fc6f145d2 to your computer and use it in GitHub Desktop.
Bloop + Nushell + ScalaCLI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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} | |
| _ => {} | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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