diff --git a/examples/standard/guessing_game.lux b/examples/standard/guessing_game.lux index c29f1dd..071f4f8 100644 --- a/examples/standard/guessing_game.lux +++ b/examples/standard/guessing_game.lux @@ -1,25 +1,44 @@ // Number guessing game - demonstrates Random and Console effects +// +// Expected output: +// Welcome to the Guessing Game! +// Target number: 42 +// Simulating guesses... +// Guess 50: Too high! +// Guess 25: Too low! +// Guess 37: Too low! +// Guess 43: Too high! +// Guess 40: Too low! +// Guess 41: Too low! +// Guess 42: Correct! +// Found in 7 attempts! -fn gameLoop(secret: Int, attempts: Int): Unit with {Console} = { - Console.print("Guess the number (1-100), attempt " + toString(attempts) + ":") - let guess = Console.readInt() - if guess == secret then - Console.print("Correct! You got it in " + toString(attempts) + " attempts!") - else if guess < secret then { - Console.print("Too low!") - gameLoop(secret, attempts + 1) - } - else { - Console.print("Too high!") - gameLoop(secret, attempts + 1) - } +// Game logic - check a guess against the secret +fn checkGuess(guess: Int, secret: Int): String = + if guess == secret then "Correct" + else if guess < secret then "Too low" + else "Too high" + +// Binary search simulation to find the number +fn binarySearch(low: Int, high: Int, secret: Int, attempts: Int): Int with {Console} = { + let mid = (low + high) / 2 + let result = checkGuess(mid, secret) + Console.print("Guess " + toString(mid) + ": " + result + "!") + + if result == "Correct" then attempts + else if result == "Too low" then binarySearch(mid + 1, high, secret, attempts + 1) + else binarySearch(low, mid - 1, secret, attempts + 1) } -fn main(): Unit with {Console, Random} = { +fn main(): Unit with {Console} = { Console.print("Welcome to the Guessing Game!") - Console.print("I'm thinking of a number between 1 and 100...") - let secret = Random.int(1, 100) - gameLoop(secret, 1) + // Use a fixed "secret" for reproducible output + let secret = 42 + Console.print("Target number: " + toString(secret)) + Console.print("Simulating guesses...") + + let attempts = binarySearch(1, 100, secret, 1) + Console.print("Found in " + toString(attempts) + " attempts!") } let output = run main() with {} diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 7f2bad2..10c691b 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -241,50 +241,68 @@ pub fn render_diagnostic( colors::RESET )); - // Source code snippet with line numbers - let line_num_width = end_line.to_string().len().max(4); + // Source code snippet with line numbers and context + let context_lines = 2; // Show 2 lines before and after + let start_line = line.saturating_sub(context_lines).max(1); + let end_context_line = (end_line + context_lines).min(source.lines().count()); + let line_num_width = end_context_line.to_string().len().max(4); - // Show the problematic line(s) - for line_num in line..=end_line { + // Show context before, error lines, and context after + for line_num in start_line..=end_context_line { if let Some(source_line) = get_source_line(source, line_num) { - // Line number - output.push_str(&format!( - "{}{:>width$} │{} ", - colors::DIM, - line_num, - colors::RESET, - width = line_num_width - )); + let is_error_line = line_num >= line && line_num <= end_line; - // Source line - output.push_str(source_line); - output.push('\n'); - - // Underline the error span - let underline_start = if line_num == line { col - 1 } else { 0 }; - let underline_end = if line_num == end_line { - end_col - 1 + // Line number (dimmed for context, normal for error lines) + if is_error_line { + output.push_str(&format!( + "{}{:>width$} │{} ", + colors::DIM, + line_num, + colors::RESET, + width = line_num_width + )); + // Source line (normal) + output.push_str(source_line); } else { - source_line.len() - }; - - let underline_len = underline_end.saturating_sub(underline_start).max(1); - - output.push_str(&format!( - "{}{:>width$} │{} ", - colors::DIM, - "", - colors::RESET, - width = line_num_width - )); - output.push_str(&" ".repeat(underline_start)); - output.push_str(&format!( - "{}{}{}", - severity_color, - "^".repeat(underline_len), - colors::RESET - )); + // Context lines are fully dimmed + output.push_str(&format!( + "{}{:>width$} │ {}{}", + colors::DIM, + line_num, + source_line, + colors::RESET, + width = line_num_width + )); + } output.push('\n'); + + // Underline the error span (only for error lines) + if is_error_line { + let underline_start = if line_num == line { col - 1 } else { 0 }; + let underline_end = if line_num == end_line { + end_col - 1 + } else { + source_line.len() + }; + + let underline_len = underline_end.saturating_sub(underline_start).max(1); + + output.push_str(&format!( + "{}{:>width$} │{} ", + colors::DIM, + "", + colors::RESET, + width = line_num_width + )); + output.push_str(&" ".repeat(underline_start)); + output.push_str(&format!( + "{}{}{}", + severity_color, + "^".repeat(underline_len), + colors::RESET + )); + output.push('\n'); + } } }