5
54
Fork
You've already forked blue
4

feat: Implement fallback chain #302

Manually merged
old merged 1 commit from pipeline-operators into main 2026年07月10日 17:58:53 +02:00

This change introduces a new type of separator for chaining commands on the BLUE
CLI. The idea is to be able to express fallback chains so if the main operation
fails there is a way to run an alternative chain of commands.

Here are some examples:

SEXP: (and (or build repl) dist)
CLI: $ blue build , repl -- dist

SEXP: (or (and configure build) (and help repl))
CLI: $ blue configure -- build , help -- repl

SEXP: (or (and configure build) (and clean build) report-bug repl)
CLI: $ blue configure -- build , clean -- build , report-bug , repl

  • blue/ui.scm (load-blueprint-and-execute-commands): Handle fallback chaining.
    (entrypoint%): Pass chain pipeline.
    (chain-separator, fallback-separator): New variable.
    (separator?): New procedure.
    (parse-commands-arguments): Parse pipeline.
    (parse-arguments): Pass chain pipeline.

Fix: #280

This change introduces a new type of separator for chaining commands on the BLUE CLI. The idea is to be able to express fallback chains so if the main operation fails there is a way to run an alternative chain of commands. Here are some examples: SEXP: (and (or build repl) dist) CLI: $ blue build , repl -- dist SEXP: (or (and configure build) (and help repl)) CLI: $ blue configure -- build , help -- repl SEXP: (or (and configure build) (and clean build) report-bug repl) CLI: $ blue configure -- build , clean -- build , report-bug , repl * blue/ui.scm (load-blueprint-and-execute-commands): Handle fallback chaining. (entrypoint%): Pass chain pipeline. (chain-separator, fallback-separator): New variable. (separator?): New procedure. (parse-commands-arguments): Parse pipeline. (parse-arguments): Pass chain pipeline. Fix: #280
feat: Implement fallback chain
All checks were successful
ci/woodpecker/pr/arch Pipeline was successful
ci/woodpecker/pr/debian Pipeline was successful
ci/woodpecker/pr/ubuntu Pipeline was successful
ci/woodpecker/pr/fedora Pipeline was successful
4b231d8a3e
This change introduces a new type of separator for chaining commands on the BLUE
CLI. The idea is to be able to express fallback chains so if the main operation
fails there is a way to run an alternative chain of commands.
Here are some examples:
SEXP: (and (or build repl) dist)
CLI: $ blue build , repl -- dist
SEXP: (or (and configure build) (and help repl))
CLI: $ blue configure -- build , help -- repl
SEXP: (or (and configure build) (and clean build) report-bug repl)
CLI: $ blue configure -- build , clean -- build , report-bug , repl
* blue/ui.scm (load-blueprint-and-execute-commands): Handle fallback chaining.
(entrypoint%): Pass chain pipeline.
(chain-separator, fallback-separator): New variable.
(separator?): New procedure.
(parse-commands-arguments): Parse pipeline.
(parse-arguments): Pass chain pipeline.
Fix: #280 
pastor 2026年07月08日 11:24:15 +02:00
pastor added this to the alpha milestone 2026年07月08日 11:24:25 +02:00
Author
Owner
Copy link

@old I realized that the suggestion we had for implementing the pipeline using the -> is not possible since the bash lexer will pickup > as a redirection. I went ahead and used , as the fallback operator.

What do you think?

Also, we should probably add some tests for the new operator.

@old I realized that the suggestion we had for implementing the pipeline using the `->` is not possible since the bash lexer will pickup `>` as a redirection. I went ahead and used `,` as the fallback operator. What do you think? Also, we should probably add some tests for the new operator.
Owner
Copy link

SEXP: (and (or build repl) dist)
CLI: $ blue build , repl -- dist
SEXP: (or (and configure build) (and help repl))
CLI: $ blue configure -- build , help -- repl
SEXP: (or (and configure build) (and clean build) report-bug repl)
CLI: $ blue configure -- build , clean -- build , report-bug , repl

These are wrong I think. Here:

# Expect (true false)
$ blue true , false -- false
;;; (true)
# Expect (false true true)
$ blue false -- false , true -- true
;;; (false)
# Expect (false false true)
$ blue false -- false , false -- false , true , false 
;;; (false)
diff --git a/blueprint.scm b/blueprint.scm
index 093c3fa..1c767a8 100644
--- a/blueprint.scm
+++ b/blueprint.scm
@@ -35,8 +35,20 @@ (define blue-configuration
 (configuration
 (variables blue-variables)))
 
+(define-command (true args)
+ ((invoke "true"))
+ (pk 'true)
+ #t)
+
+(define-command (false args)
+ ((invoke "false"))
+ (pk 'false)
+ #f)
+
 (define blue-commands
 (list
+ true
+ false
 check-install-command
 coverage-command
 install-command

You can't express tree like logic with this. Threading logic sure.

> SEXP: (and (or build repl) dist) CLI: $ blue build , repl -- dist SEXP: (or (and configure build) (and help repl)) CLI: $ blue configure -- build , help -- repl SEXP: (or (and configure build) (and clean build) report-bug repl) CLI: $ blue configure -- build , clean -- build , report-bug , repl These are wrong I think. Here: ``` # Expect (true false) $ blue true , false -- false ;;; (true) # Expect (false true true) $ blue false -- false , true -- true ;;; (false) # Expect (false false true) $ blue false -- false , false -- false , true , false ;;; (false) ``` ```diff diff --git a/blueprint.scm b/blueprint.scm index 093c3fa..1c767a8 100644 --- a/blueprint.scm +++ b/blueprint.scm @@ -35,8 +35,20 @@ (define blue-configuration (configuration (variables blue-variables))) +(define-command (true args) + ((invoke "true")) + (pk 'true) + #t) + +(define-command (false args) + ((invoke "false")) + (pk 'false) + #f) + (define blue-commands (list + true + false check-install-command coverage-command install-command ``` You can't express tree like logic with this. Threading logic sure.
Owner
Copy link

@pastor wrote in #302 (comment):

@old I realized that the suggestion we had for implementing the pipeline using the -> is not possible since the bash lexer will pickup > as a redirection. I went ahead and used , as the fallback operator.

What do you think?

Also, we should probably add some tests for the new operator.

, is a valid separator for commands. blue foo --option=foo,bar. -- is known to be an invalid token in command line parsing so it is fine to use it.

@pastor wrote in https://codeberg.org/lapislazuli/blue/pulls/302#issuecomment-18786797: > @old I realized that the suggestion we had for implementing the pipeline using the `->` is not possible since the bash lexer will pickup `>` as a redirection. I went ahead and used `,` as the fallback operator. > > What do you think? > > Also, we should probably add some tests for the new operator. `,` is a valid separator for commands. `blue foo --option=foo,bar`. `--` is known to be an invalid token in command line parsing so it is fine to use it.
pastor force-pushed pipeline-operators from 4b231d8a3e
All checks were successful
ci/woodpecker/pr/arch Pipeline was successful
ci/woodpecker/pr/debian Pipeline was successful
ci/woodpecker/pr/ubuntu Pipeline was successful
ci/woodpecker/pr/fedora Pipeline was successful
to c01ffb8183
All checks were successful
ci/woodpecker/pr/arch Pipeline was successful
ci/woodpecker/pr/debian Pipeline was successful
ci/woodpecker/pr/ubuntu Pipeline was successful
ci/woodpecker/pr/fedora Pipeline was successful
2026年07月09日 11:09:28 +02:00
Compare
Author
Owner
Copy link

@old wrote in #302 (comment):

blue false -- false , true -- true

I think we are looking at different goals here. It seems we didn't wrote it down, but, if I recall correctly, we decided not to support a complete tree as it would make the CLI usage a bit uncomfortable, and for most real uses you are likely to have enough with the fallback behavior.

Now, let me write down, what I think we decided we want 😆

So the behavior is as follows:

  • -- is the chain operator, it means: as long as the previous command returns #t, go on with the next, exit otherwise.
  • , is the fallback operator, it means: if the previous command returns #f, go on with the next, exit otherwise (fallback not executed)

I think this allows to express most chains one would need and the user can always rely on a combination of BLUE chains + shell operators such as && and ; to cover the full range of possibilities, but since we think this is quite an unlikely case, we provide a comfortable interface just for BLUE chains with fallbacks.

With that in mind, I've corrected a bug that I noticed with your examples, now the expected output should be:

# Expect (true), fallback not executed.
$ blue true , false -- false
;;; (true)
# Expect (false true true)
$ blue false -- false , true -- true
;;; (false)
;;; (true)
;;; (true)
# Expect (false false true)
$ blue false -- false , false -- false , true , false 
;;; (false)
;;; (false)
;;; (true)

What do you think? Now it seems to be what we want.

@old wrote in https://codeberg.org/lapislazuli/blue/pulls/302#issuecomment-18808406: > blue false -- false , true -- true I think we are looking at different goals here. It seems we didn't wrote it down, but, if I recall correctly, we decided not to support a complete tree as it would make the CLI usage a bit uncomfortable, and for most real uses you are likely to have enough with the fallback behavior. Now, let me write down, what I think we decided we want 😆 So the behavior is as follows: - `--` is the chain operator, it means: as long as the previous command returns #t, go on with the next, exit otherwise. - `,` is the fallback operator, it means: if the previous command returns #f, go on with the next, exit otherwise (fallback not executed) I think this allows to express most chains one would need and the user can always rely on a combination of BLUE chains + shell operators such as `&&` and `;` to cover the full range of possibilities, but since we think this is quite an unlikely case, we provide a comfortable interface just for BLUE chains with fallbacks. With that in mind, I've corrected a bug that I noticed with your examples, now the expected output should be: ``` # Expect (true), fallback not executed. $ blue true , false -- false ;;; (true) # Expect (false true true) $ blue false -- false , true -- true ;;; (false) ;;; (true) ;;; (true) # Expect (false false true) $ blue false -- false , false -- false , true , false ;;; (false) ;;; (false) ;;; (true) ``` What do you think? Now it seems to be what we want.
Owner
Copy link

What do you think? Now it seems to be what we want.

Yes. But the examples in the commit message are wrong. We can't express S-EXP then.

> What do you think? Now it seems to be what we want. Yes. But the examples in the commit message are wrong. We can't express S-EXP then.
Author
Owner
Copy link

@old well, I just meant that that would be the sexp equivalent, not that you can do all the things you can in the SEXP, if you find it confusing we can drop those

@old well, I just meant that that would be the sexp equivalent, not that you can do all the things you can in the SEXP, if you find it confusing we can drop those
pastor force-pushed pipeline-operators from c01ffb8183
All checks were successful
ci/woodpecker/pr/arch Pipeline was successful
ci/woodpecker/pr/debian Pipeline was successful
ci/woodpecker/pr/ubuntu Pipeline was successful
ci/woodpecker/pr/fedora Pipeline was successful
to 7c7d8ae108
All checks were successful
ci/woodpecker/pr/arch Pipeline was successful
ci/woodpecker/pr/debian Pipeline was successful
ci/woodpecker/pr/ubuntu Pipeline was successful
ci/woodpecker/pr/fedora Pipeline was successful
2026年07月09日 14:38:34 +02:00
Compare
Author
Owner
Copy link

@old I've added a clarification note on the commit message.

@old I've added a clarification note on the commit message.
pastor changed title from (削除) feat: Implement fallback chain (削除ここまで) to WIP: feat: Implement fallback chain 2026年07月09日 15:24:10 +02:00
pastor force-pushed pipeline-operators from 7c7d8ae108
All checks were successful
ci/woodpecker/pr/arch Pipeline was successful
ci/woodpecker/pr/debian Pipeline was successful
ci/woodpecker/pr/ubuntu Pipeline was successful
ci/woodpecker/pr/fedora Pipeline was successful
to f5db8a378d
Some checks failed
ci/woodpecker/pr/arch Pipeline failed
ci/woodpecker/pr/ubuntu Pipeline was successful
ci/woodpecker/pr/debian Pipeline was successful
ci/woodpecker/pr/fedora Pipeline was successful
2026年07月09日 16:09:30 +02:00
Compare
pastor changed title from (削除) WIP: feat: Implement fallback chain (削除ここまで) to feat: Implement fallback chain 2026年07月09日 16:09:44 +02:00
Author
Owner
Copy link

@old Now it's ready, I've added a regression test for the new fallback behavior.

@old Now it's ready, I've added a regression test for the new fallback behavior.
old manually merged commit 32a5f1ad55 into main 2026年07月10日 17:58:53 +02:00
Sign in to join this conversation.
No reviewers
old
Labels
Clear labels
bug
Something is not working
contribution welcome
Contributions are very welcome, get started here
discussion
duplicate
This issue or pull request already exists
enhancement
New feature
good first issue
Interested in contributing? Get started here.
help wanted
Need some help
invalid
Something is wrong
optimization
question
More information is needed
upstream
Related to an upstream repository, already reported there
bug
Something is not working
contribution welcome
Contributions are very welcome, get started here
duplicate
This issue or pull request already exists
enhancement
New feature
good first issue
Interested in contributing? Get started here.
help wanted
Need some help
invalid
Something is wrong
question
More information is needed
upstream
Related to an upstream repository, already reported there
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lapislazuli/blue!302
Reference in a new issue
lapislazuli/blue
No description provided.
Delete branch "pipeline-operators"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?