main.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. use std::env;
  2. use std::process;
  3. use std::os::unix::process::CommandExt;
  4. const USAGE_HINT: &'static str =
  5. "NOTICE ABOUT CAB:
  6. Cabal was invoked using cab, a wrapper script around
  7. Cabal. For cab-specific help, use --cab-help.\n";
  8. const USAGE: &'static str =
  9. "Command line Cabal wrapper for new-style builds
  10. Usage: cab [GLOBAL_FLAGS] [COMMAND [FLAGS]]
  11. cab for the most part has the exact same usage as Cabal, but it
  12. deliberately rewrites certain commands so that they are understood as
  13. the 'new-style project' commands.
  14. Certain old-style commands cannot be invoked through cab (as running
  15. `cab test' will always be treated as `cabal new-test` and not `cabal
  16. test') but any command which does not have a new-style equivalent
  17. (such as `check') will be run identically.
  18. Commands which differ from Cabal:
  19. cab build => cabal new-build
  20. cab configure => cabal new-configure
  21. cab conf => cabal new-configure
  22. cab repl => cabal new-repl
  23. cab run => cabal new-run
  24. cab test => cabal new-test
  25. cab bench => cabal new-bench
  26. cab freeze => cabal new-freeze
  27. cab haddock => cabal new-haddock
  28. cab update => cabal new-update
  29. cab install => cabal new-install
  30. cab exec => cabal new-exec
  31. ";
  32. /// A function which knows all the replaceable arguments. This will
  33. /// return None if it's not one of the new-style commands it knows
  34. /// about.
  35. fn replace(s: &str) -> Option<String> {
  36. Some(match s {
  37. "build" => "new-build".to_owned(),
  38. "configure" => "new-configure".to_owned(),
  39. "repl" => "new-repl".to_owned(),
  40. "run" => "new-run".to_owned(),
  41. "test" => "new-test".to_owned(),
  42. "bench" => "new-bench".to_owned(),
  43. "freeze" => "new-freeze".to_owned(),
  44. "haddock" => "new-haddock".to_owned(),
  45. _ => None?,
  46. })
  47. }
  48. /// This is a tiny stateful iterator that has some logic around
  49. /// whether to rewrite arguments. (Not enough logic yet, I think, but
  50. /// this is fine for a first pass.)
  51. struct CabalArgs {
  52. seen_cmd: bool,
  53. args: env::Args,
  54. }
  55. impl CabalArgs {
  56. fn new() -> CabalArgs {
  57. let mut args = env::args();
  58. let _ = args.next();
  59. CabalArgs {
  60. seen_cmd: false,
  61. args: args,
  62. }
  63. }
  64. }
  65. impl Iterator for CabalArgs {
  66. type Item = String;
  67. fn next(&mut self) -> Option<String> {
  68. // Once we've seen a proper command, then we don't want to do
  69. // any kind of rewriting of the rest of it, so we just pass
  70. // the arguments on
  71. if self.seen_cmd {
  72. self.args.next()
  73. } else {
  74. // if we haven't seen a proper command yet, then we can
  75. // keep intercepting arguments
  76. self.args.next().and_then( |arg| {
  77. if &arg == "--help" {
  78. // if it's asking for help, then we should also
  79. // add a short note about how the usage for `cab`
  80. // is a bit different, but otherwise let `cabal`
  81. // print whatever it wants
  82. println!("{}", USAGE_HINT);
  83. Some(arg)
  84. } else if &arg == "--cab-help" {
  85. // We totally intercept --cab-help to display our
  86. // own full help string and leave it at that.
  87. println!("{}", USAGE);
  88. process::exit(0);
  89. } else if let Some(r) = replace(&arg) {
  90. // If there is a replacement for this fragment,
  91. // then we've now seen a command (and shouldn't do
  92. // anything else) but we should return the
  93. // replacement string (i.e. new-build for build)
  94. self.seen_cmd = true;
  95. Some(r)
  96. } else {
  97. // otherwise, keep going!
  98. Some(arg)
  99. }
  100. })
  101. }
  102. }
  103. }
  104. fn main() {
  105. process::Command::new("cabal")
  106. .args(CabalArgs::new())
  107. .exec();
  108. }