rip-lang 1.2.2 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,9 +9,9 @@
9
9
  </p>
10
10
 
11
11
  <p align="center">
12
- <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-1.1.1-blue.svg" alt="Version"></a>
12
+ <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-1.3.0-blue.svg" alt="Version"></a>
13
13
  <a href="#es2022-target"><img src="https://img.shields.io/badge/target-ES2022-blue.svg" alt="Target"></a>
14
- <a href="#current-status"><img src="https://img.shields.io/badge/tests-864%2F864-brightgreen.svg" alt="Tests"></a>
14
+ <a href="#current-status"><img src="https://img.shields.io/badge/tests-878%2F878-brightgreen.svg" alt="Tests"></a>
15
15
  <a href="#current-status"><img src="https://img.shields.io/badge/coverage-100%25-brightgreen.svg" alt="Coverage"></a>
16
16
  <a href="#zero-dependencies"><img src="https://img.shields.io/badge/dependencies-ZERO-brightgreen.svg" alt="Dependencies"></a>
17
17
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
@@ -634,9 +634,20 @@ user?.profile?.name # ES6 optional chaining (native)
634
634
  arr?[0] # CoffeeScript soak (existence check)
635
635
  fn?(arg) # CoffeeScript soak call
636
636
 
637
- # Nullish coalescing
637
+ # Nullish coalescing (?? - rejects null OR undefined)
638
638
  port = config.port ?? 8080
639
639
 
640
+ # Otherwise operator (!? - rejects ONLY undefined)
641
+ timeout = config.timeout !? 5000 # null and 0 are valid!
642
+ enabled = options.enabled !? true # false means disabled, undefined means default
643
+
644
+ # Comparison:
645
+ null ?? 'default' # → 'default' (null fails)
646
+ null !? 'default' # → null (null is defined!)
647
+
648
+ # Use ?? when: Both null and undefined should use default
649
+ # Use !? when: Only undefined should use default (null/false/0 are meaningful)
650
+
640
651
  # Legacy existential operator (CoffeeScript compatibility)
641
652
  value = x ? y # SPACE? syntax (auto-converts to ??)
642
653
  value = x ?? y # Preferred modern syntax
package/bin/rip CHANGED
@@ -57,18 +57,38 @@ Shebang support:
57
57
  async function main() {
58
58
  const args = process.argv.slice(2);
59
59
 
60
- if (args.includes('-h') || args.includes('--help')) {
60
+ // Find the script file position (first non-option argument)
61
+ // Everything BEFORE it is rip options, everything AFTER it is script arguments
62
+ let scriptFileIndex = -1;
63
+ for (let i = 0; i < args.length; i++) {
64
+ // Skip option values (like -o filename)
65
+ if (i > 0 && (args[i - 1] === '-o' || args[i - 1] === '--output')) {
66
+ continue;
67
+ }
68
+ // First non-option arg is the script file
69
+ if (!args[i].startsWith('-')) {
70
+ scriptFileIndex = i;
71
+ break;
72
+ }
73
+ }
74
+
75
+ // Split into rip options and script arguments
76
+ const ripOptions = scriptFileIndex === -1 ? args : args.slice(0, scriptFileIndex);
77
+ const scriptArgs = scriptFileIndex === -1 ? [] : args.slice(scriptFileIndex + 1);
78
+
79
+ // Only check ripOptions for rip's flags (not script args!)
80
+ if (ripOptions.includes('-h') || ripOptions.includes('--help')) {
61
81
  printHelp();
62
82
  process.exit(0);
63
83
  }
64
84
 
65
- if (args.includes('-v') || args.includes('--version')) {
85
+ if (ripOptions.includes('-v') || ripOptions.includes('--version')) {
66
86
  console.log(`Rip ${VERSION} - ${SUMMARY}`);
67
87
  process.exit(0);
68
88
  }
69
89
 
70
90
  // Launch local browser REPL (starts server + opens browser)
71
- if (args.includes('-w') || args.includes('--web')) {
91
+ if (ripOptions.includes('-w') || ripOptions.includes('--web')) {
72
92
  console.log('🚀 Starting Rip browser REPL...\n');
73
93
 
74
94
  // Start the server and capture output to get the actual port
@@ -109,15 +129,15 @@ async function main() {
109
129
  // Check if REPL should be started
110
130
  // Launch REPL if: no args AND stdin is a TTY (not piped), OR explicit -r flag
111
131
  const isTTY = process.stdin.isTTY;
112
- if ((args.length === 0 && isTTY) || args.includes('-r') || args.includes('--repl')) {
132
+ if ((args.length === 0 && isTTY) || ripOptions.includes('-r') || ripOptions.includes('--repl')) {
113
133
  startREPL();
114
134
  return;
115
135
  }
116
136
 
117
- const showTokens = args.includes('-t') || args.includes('--tokens');
118
- const showSExpr = args.includes('-s') || args.includes('--sexpr');
119
- const showCompiled = args.includes('-c') || args.includes('--compile');
120
- const quiet = args.includes('-q') || args.includes('--quiet');
137
+ const showTokens = ripOptions.includes('-t') || ripOptions.includes('--tokens');
138
+ const showSExpr = ripOptions.includes('-s') || ripOptions.includes('--sexpr');
139
+ const showCompiled = ripOptions.includes('-c') || ripOptions.includes('--compile');
140
+ const quiet = ripOptions.includes('-q') || ripOptions.includes('--quiet');
121
141
 
122
142
  const options = {
123
143
  showTokens,
@@ -125,16 +145,14 @@ async function main() {
125
145
  quiet
126
146
  };
127
147
 
128
- // Find input file (last non-option argument)
129
- let inputFile = null;
148
+ // Find input file and output file from ripOptions only
149
+ let inputFile = scriptFileIndex === -1 ? null : args[scriptFileIndex];
130
150
  let outputFile = null;
131
151
 
132
- for (let i = 0; i < args.length; i++) {
133
- if (args[i] === '-o' || args[i] === '--output') {
134
- outputFile = args[i + 1];
152
+ for (let i = 0; i < ripOptions.length; i++) {
153
+ if (ripOptions[i] === '-o' || ripOptions[i] === '--output') {
154
+ outputFile = ripOptions[i + 1];
135
155
  i++;
136
- } else if (!args[i].startsWith('-') && !inputFile) {
137
- inputFile = args[i]; // Only take first non-option as input file
138
156
  }
139
157
  }
140
158
 
@@ -150,10 +168,6 @@ async function main() {
150
168
  // Execute the script with Bun using our loader
151
169
  const loaderPath = join(__dirname, '../rip-loader.ts');
152
170
 
153
- // Get script arguments (everything after the input file)
154
- const inputFileIndex = args.indexOf(inputFile);
155
- const scriptArgs = args.slice(inputFileIndex + 1);
156
-
157
171
  try {
158
172
  execSync(`bun --preload ${loaderPath} ${inputFile} ${scriptArgs.join(' ')}`, {
159
173
  stdio: 'inherit'