Approval-based snapshot testing library for Go (mirror)
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: tree-sitter grammar, highlights and injection queries

+2478 -19
+1 -1
CLAUDE.md
··· 73 73 74 74 - Root module (`go.mod`): Main library - Go 1.23.12+ 75 75 - TUI module (`cmd/shutter/go.mod`): Separate module with Bubbletea dependencies - Go 1.25.2 76 - - `/editors/`: Tree-sitter grammar for snapshot format (Node.js/Rust/Python/Swift bindings) 76 + - `/editor/tree-sitter-snapshot/`: Tree-sitter grammar for snapshot format (Node.js/Rust/Python/Swift bindings)
+13
__snapshots__/combined_ignore_and_scrub.snap
··· 1 + --- 2 + title: Combined Ignore and Scrub 3 + test_name: TestCombinedIgnoreAndScrub 4 + file_name: ignore_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "created_at": "<TIMESTAMP>", 9 + "email": "<EMAIL>", 10 + "ip_address": "<IP>", 11 + "name": "John Doe", 12 + "user_id": "<UUID>" 13 + }
+78
__snapshots__/complex_nested_structure.snap
··· 1 + --- 2 + title: Complex Nested Structure 3 + test_name: TestComplexNestedStructure 4 + file_name: shutter_test.go 5 + version: 0.1.0 6 + --- 7 + shutter_test.Post{ 8 + ID: 100, 9 + Title: "Introduction to Go Snapshot Testing", 10 + Content: "This is a comprehensive guide to snapshot testing in Go...", 11 + Author: shutter_test.User{ 12 + ID: 1, 13 + Username: "john_doe", 14 + Email: "john@example.com", 15 + Active: true, 16 + CreatedAt: time.Time{ 17 + wall: 0x0, 18 + ext: 63809375400, 19 + loc: (*time.Location)(nil), 20 + }, 21 + Roles: []string{"admin", "moderator", "user"}, 22 + Metadata: map[string]interface{}{ 23 + "language": "en", 24 + "notifications": true, 25 + "preferences": map[string]interface{}{ 26 + "email_frequency": "weekly", 27 + "notifications": true, 28 + }, 29 + "theme": "dark", 30 + }, 31 + }, 32 + Tags: []string{"go", "testing", "snapshots", "best-practices"}, 33 + Comments: []shutter_test.Comment{ 34 + { 35 + ID: 1, 36 + Author: "alice", 37 + Content: "Great post!", 38 + CreatedAt: time.Time{ 39 + wall: 0x0, 40 + ext: 63810858120, 41 + loc: (*time.Location)(nil), 42 + }, 43 + Replies: []shutter_test.Comment{ 44 + { 45 + ID: 2, 46 + Author: "bob", 47 + Content: "I agree!", 48 + CreatedAt: time.Time{ 49 + wall: 0x0, 50 + ext: 63810863100, 51 + loc: (*time.Location)(nil), 52 + }, 53 + Replies: []shutter_test.Comment{ 54 + }, 55 + }, 56 + }, 57 + }, 58 + { 59 + ID: 3, 60 + Author: "charlie", 61 + Content: "Thanks for sharing!", 62 + CreatedAt: time.Time{ 63 + wall: 0x0, 64 + ext: 63810927000, 65 + loc: (*time.Location)(nil), 66 + }, 67 + Replies: []shutter_test.Comment{ 68 + }, 69 + }, 70 + }, 71 + Likes: 42, 72 + Published: true, 73 + CreatedAt: time.Time{ 74 + wall: 0x0, 75 + ext: 63809802000, 76 + loc: (*time.Location)(nil), 77 + }, 78 + }
+10
__snapshots__/custom_ignore_function.snap
··· 1 + --- 2 + title: Custom Ignore Function 3 + test_name: TestCustomIgnore 4 + file_name: ignore_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "grade": "A", 9 + "name": "John Doe" 10 + }
+11
__snapshots__/custom_regex_scrubber.snap
··· 1 + --- 2 + title: Custom Regex Scrubber 3 + test_name: TestCustomScrubbers/regex_scrubber 4 + file_name: scrubbers_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "api_key": "<API_KEY>", 9 + "name": "Test User", 10 + "secret_key": "<API_KEY>" 11 + }
+7
__snapshots__/custom_scrubber.snap
··· 1 + --- 2 + title: Custom Scrubber 3 + test_name: TestCustomScrubbers/custom_function_scrubber 4 + file_name: scrubbers_test.go 5 + version: 0.1.0 6 + --- 7 + hello world! this is a test.
+10
__snapshots__/custom_type_test.snap
··· 1 + --- 2 + title: Custom Type Test 3 + test_name: TestSnapCustomType 4 + file_name: shutter_test.go 5 + version: 0.1.0 6 + --- 7 + shutter_test.CustomStruct{ 8 + Name: "Alice", 9 + Age: 30, 10 + }
+7
__snapshots__/exact_match_scrubber.snap
··· 1 + --- 2 + title: Exact Match Scrubber 3 + test_name: TestCustomScrubbers/exact_match_scrubber 4 + file_name: scrubbers_test.go 5 + version: 0.1.0 6 + --- 7 + The secret password is '<PASSWORD>' and should be hidden.
+10
__snapshots__/ignore_empty_values.snap
··· 1 + --- 2 + title: Ignore Empty Values 3 + test_name: TestIgnoreValues/empty_values 4 + file_name: ignore_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "email": "john@example.com", 9 + "name": "John Doe" 10 + }
+20
__snapshots__/ignore_in_arrays.snap
··· 1 + --- 2 + title: Ignore in Arrays 3 + test_name: TestIgnoreKeys/arrays 4 + file_name: ignore_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "users": [ 9 + { 10 + "email": "alice@example.com", 11 + "id": 1, 12 + "name": "Alice" 13 + }, 14 + { 15 + "email": "bob@example.com", 16 + "id": 2, 17 + "name": "Bob" 18 + } 19 + ] 20 + }
+10
__snapshots__/ignore_key_pattern.snap
··· 1 + --- 2 + title: Ignore Key Pattern 3 + test_name: TestIgnoreKeyPatterns/contains_pattern 4 + file_name: ignore_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "email": "john@example.com", 9 + "username": "john_doe" 10 + }
+10
__snapshots__/ignore_keys_matching_pattern.snap
··· 1 + --- 2 + title: Ignore Keys Matching Pattern 3 + test_name: TestIgnoreKeyPatterns/prefix_pattern 4 + file_name: ignore_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "product_id": 100, 9 + "product_name": "Widget" 10 + }
+11
__snapshots__/ignore_multiple_keys.snap
··· 1 + --- 2 + title: Ignore Multiple Keys 3 + test_name: TestIgnoreKeys/multiple_keys 4 + file_name: ignore_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "email": "john@example.com", 9 + "id": 1, 10 + "name": "John Doe" 11 + }
+11
__snapshots__/ignore_null_values.snap
··· 1 + --- 2 + title: Ignore Null Values 3 + test_name: TestIgnoreValues/null_values 4 + file_name: ignore_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "age": 30, 9 + "email": "john@example.com", 10 + "name": "John Doe" 11 + }
+10
__snapshots__/ignore_password_field.snap
··· 1 + --- 2 + title: Ignore Password Field 3 + test_name: TestIgnoreKeys/key_value_pairs 4 + file_name: ignore_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "email": "john@example.com", 9 + "username": "john_doe" 10 + }
+11
__snapshots__/ignore_sensitive_keys.snap
··· 1 + --- 2 + title: Ignore Sensitive Keys 3 + test_name: TestIgnoreSensitiveKeys 4 + file_name: ignore_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "email": "john@example.com", 9 + "name": "John Doe", 10 + "username": "john_doe" 11 + }
+9
__snapshots__/ignore_specific_values.snap
··· 1 + --- 2 + title: Ignore Specific Values 3 + test_name: TestIgnoreValues/specific_values 4 + file_name: ignore_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "message": "Processing" 9 + }
+16
__snapshots__/json_with_special_characters.snap
··· 1 + --- 2 + title: JSON with Special Characters 3 + test_name: TestJsonWithSpecialCharacters 4 + file_name: shutter_test.go 5 + version: 0.1.0 6 + --- 7 + map[string]interface{}{ 8 + "backslash": "path\\to\\file", 9 + "emoji": "😀 😃 😄 😁 😆", 10 + "english": "Hello, World!", 11 + "escaped": "quotes: \"double\" and 'single'", 12 + "newlines": "line1\nline2\rline3\r\nline4", 13 + "special_chars": "!@#$%^&*()_+-=[]{}|;:,.<>?", 14 + "tabs": "col1\tcol2\tcol3", 15 + "unicode": "こんにちは 世界 🌍", 16 + }
+54
__snapshots__/large_json_structure.snap
··· 1 + --- 2 + title: Large JSON Structure 3 + test_name: TestLargeJson 4 + file_name: shutter_test.go 5 + version: 0.1.0 6 + --- 7 + map[string]interface{}{ 8 + "created_at": "2023-01-28T14:30:00Z", 9 + "customer_id": 42.0, 10 + "delivered_at": nil, 11 + "id": 1001.0, 12 + "products": []interface{}{ 13 + map[string]interface{}{ 14 + "description": "High-performance laptop", 15 + "id": 1.0, 16 + "in_stock": true, 17 + "name": "Laptop", 18 + "price": 999.99, 19 + "stock": 5.0, 20 + "tags": []interface{}{ 21 + "electronics", 22 + "computers", 23 + "laptops", 24 + }, 25 + }, 26 + map[string]interface{}{ 27 + "description": "Wireless mouse", 28 + "id": 2.0, 29 + "in_stock": true, 30 + "name": "Mouse", 31 + "price": 29.99, 32 + "stock": 50.0, 33 + "tags": []interface{}{ 34 + "electronics", 35 + "accessories", 36 + }, 37 + }, 38 + map[string]interface{}{ 39 + "description": "Mechanical keyboard", 40 + "id": 3.0, 41 + "in_stock": false, 42 + "name": "Keyboard", 43 + "price": 149.99, 44 + "stock": 0.0, 45 + "tags": []interface{}{ 46 + "electronics", 47 + "accessories", 48 + }, 49 + }, 50 + }, 51 + "shipped_at": "2023-02-01T10:00:00Z", 52 + "status": "shipped", 53 + "total": 1179.97, 54 + }
+56
__snapshots__/multiple_complex_structures.snap
··· 1 + --- 2 + title: Multiple Complex Structures 3 + test_name: TestMultipleComplexStructures 4 + file_name: shutter_test.go 5 + version: 0.1.0 6 + --- 7 + []shutter_test.User{ 8 + { 9 + ID: 1, 10 + Username: "alice", 11 + Email: "alice@example.com", 12 + Active: true, 13 + CreatedAt: time.Time{ 14 + wall: 0x0, 15 + ext: 0, 16 + loc: (*time.Location)(nil), 17 + }, 18 + Roles: []string{"user", "moderator"}, 19 + Metadata: map[string]interface{}{ 20 + "badge": "verified", 21 + "verified": true, 22 + }, 23 + }, 24 + { 25 + ID: 2, 26 + Username: "bob", 27 + Email: "bob@example.com", 28 + Active: false, 29 + CreatedAt: time.Time{ 30 + wall: 0x0, 31 + ext: 0, 32 + loc: (*time.Location)(nil), 33 + }, 34 + Roles: []string{"user"}, 35 + Metadata: map[string]interface{}{ 36 + "avatar": "https://example.com/bob.jpg", 37 + "verified": false, 38 + }, 39 + }, 40 + { 41 + ID: 3, 42 + Username: "charlie", 43 + Email: "charlie@example.com", 44 + Active: true, 45 + CreatedAt: time.Time{ 46 + wall: 0x0, 47 + ext: 0, 48 + loc: (*time.Location)(nil), 49 + }, 50 + Roles: []string{"user", "admin"}, 51 + Metadata: map[string]interface{}{ 52 + "account_age_days": 365, 53 + "verified": true, 54 + }, 55 + }, 56 + }
+27
__snapshots__/multiple_scrubbers.snap
··· 1 + --- 2 + title: Multiple Scrubbers 3 + test_name: TestBuiltInScrubbers 4 + file_name: scrubbers_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "api_key": "<API_KEY>", 9 + "backup_card": "<CREDIT_CARD>", 10 + "backup_email": "<EMAIL>", 11 + "birth_date": "<DATE>", 12 + "card_number": "<CREDIT_CARD>", 13 + "client_ip": "<IP>", 14 + "created_at": "<TIMESTAMP>", 15 + "email": "<EMAIL>", 16 + "jwt_token": "<JWT>", 17 + "message": "Connection from <IP>", 18 + "name": "John Doe", 19 + "server_ip": "<IP>", 20 + "session_id": "<UUID>", 21 + "stripe_key": "<API_KEY>", 22 + "unix_created": <UNIX_TS>, 23 + "unix_updated": <UNIX_TS>, 24 + "updated_at": "<TIMESTAMP>", 25 + "us_format_date": "<DATE>", 26 + "user_id": "<UUID>" 27 + }
+16
__snapshots__/multiple_values_test.snap
··· 1 + --- 2 + title: Multiple Values Test 3 + test_name: TestSnapMultiple 4 + file_name: shutter_test.go 5 + version: 0.1.0 6 + --- 7 + "value1" 8 + "value2" 9 + 42 10 + "foo" 11 + "bar" 12 + "baz" 13 + "wibble" 14 + "wobble" 15 + "tock" 16 + interface{}(nil)
+18
__snapshots__/nested_ignore_patterns.snap
··· 1 + --- 2 + title: Nested Ignore Patterns 3 + test_name: TestNestedIgnorePatterns 4 + file_name: ignore_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "admin": {}, 9 + "user": { 10 + "email": "john@example.com", 11 + "id": 1, 12 + "name": "John Doe", 13 + "profile": { 14 + "bio": "Developer", 15 + "website": "https://example.com" 16 + } 17 + } 18 + }
+47
__snapshots__/nested_maps_and_slices.snap
··· 1 + --- 2 + title: Nested Maps and Slices 3 + test_name: TestNestedMapsAndSlices 4 + file_name: shutter_test.go 5 + version: 0.1.0 6 + --- 7 + map[string]interface{}{ 8 + "posts": map[string]interface{}{ 9 + "categories": []string{"tech", "lifestyle", "news"}, 10 + "drafts": 5, 11 + "published": 42, 12 + }, 13 + "stats": map[string]interface{}{ 14 + "daily": map[string]interface{}{ 15 + "clicks": 320, 16 + "conversions": map[string]interface{}{ 17 + "by_source": map[string]int{ 18 + "organic": 25, 19 + "paid": 15, 20 + "referral": 5, 21 + }, 22 + "total": 45, 23 + }, 24 + "views": 1500, 25 + }, 26 + }, 27 + "users": map[string]interface{}{ 28 + "active": []map[string]interface{}{ 29 + { 30 + "id": 1, 31 + "name": "Alice", 32 + "verified": true, 33 + }, 34 + { 35 + "id": 2, 36 + "name": "Bob", 37 + "verified": false, 38 + }, 39 + }, 40 + "inactive": []map[string]interface{}{ 41 + { 42 + "id": 3, 43 + "name": "Charlie", 44 + }, 45 + }, 46 + }, 47 + }
+28
__snapshots__/real_world_api_response.snap
··· 1 + --- 2 + title: Real World API Response 3 + test_name: TestComplexRealWorldExample 4 + file_name: ignore_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "metadata": { 9 + "server_ip": "<IP>", 10 + "session_token": "<JWT>", 11 + "user_agent": "Mozilla/5.0" 12 + }, 13 + "request_id": "<UUID>", 14 + "timestamp": "<TIMESTAMP>", 15 + "transaction": { 16 + "amount": 99.99, 17 + "currency": "USD", 18 + "id": "txn_abc123", 19 + "timestamp": "<TIMESTAMP>" 20 + }, 21 + "user": { 22 + "created_at": "<TIMESTAMP>", 23 + "email": "<EMAIL>", 24 + "id": "<UUID>", 25 + "ip_address": "<IP>", 26 + "name": "John Doe" 27 + } 28 + }
+12
__snapshots__/scrub_with_snap.snap
··· 1 + --- 2 + title: Scrub With Snap 3 + test_name: TestScrubWithSnapFunction 4 + file_name: scrubbers_test.go 5 + version: 0.1.0 6 + --- 7 + map[string]interface{}{ 8 + "created_at": "<TIMESTAMP>", 9 + "email": "<EMAIL>", 10 + "name": "John Doe", 11 + "user_id": "<UUID>", 12 + }
+12
__snapshots__/scrubbed_api_keys.snap
··· 1 + --- 2 + title: Scrubbed API Keys 3 + test_name: TestIndividualScrubbers/api_keys 4 + file_name: scrubbers_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "api_key_prod": "<API_KEY>", 9 + "name": "Test Config", 10 + "stripe_key": "<API_KEY>", 11 + "test_key": "<API_KEY>" 12 + }
+12
__snapshots__/scrubbed_credit_cards.snap
··· 1 + --- 2 + title: Scrubbed Credit Cards 3 + test_name: TestIndividualScrubbers/credit_cards 4 + file_name: scrubbers_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "another_card": "<CREDIT_CARD>", 9 + "backup_card": "<CREDIT_CARD>", 10 + "card_number": "<CREDIT_CARD>", 11 + "name": "John Doe" 12 + }
+12
__snapshots__/scrubbed_dates.snap
··· 1 + --- 2 + title: Scrubbed Dates 3 + test_name: TestIndividualScrubbers/dates 4 + file_name: scrubbers_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "birth_date": "<DATE>", 9 + "hire_date": "<DATE>", 10 + "name": "John Doe", 11 + "us_format": "<DATE>" 12 + }
+11
__snapshots__/scrubbed_emails.snap
··· 1 + --- 2 + title: Scrubbed Emails 3 + test_name: TestIndividualScrubbers/emails 4 + file_name: scrubbers_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "backup_email": "<EMAIL>", 9 + "email": "<EMAIL>", 10 + "name": "John Doe" 11 + }
+11
__snapshots__/scrubbed_ips.snap
··· 1 + --- 2 + title: Scrubbed IPs 3 + test_name: TestIndividualScrubbers/ip_addresses 4 + file_name: scrubbers_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "client_ip": "<IP>", 9 + "message": "Connection from <IP>", 10 + "server_ip": "<IP>" 11 + }
+10
__snapshots__/scrubbed_jwts.snap
··· 1 + --- 2 + title: Scrubbed JWTs 3 + test_name: TestIndividualScrubbers/jwts 4 + file_name: scrubbers_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "refresh_token": "<JWT>", 9 + "token": "<JWT>" 10 + }
+12
__snapshots__/scrubbed_timestamps.snap
··· 1 + --- 2 + title: Scrubbed Timestamps 3 + test_name: TestIndividualScrubbers/timestamps 4 + file_name: scrubbers_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "created_at": "<TIMESTAMP>", 9 + "deleted_at": "<TIMESTAMP>", 10 + "name": "Test Event", 11 + "updated_at": "<TIMESTAMP>" 12 + }
+12
__snapshots__/scrubbed_unix_timestamps.snap
··· 1 + --- 2 + title: Scrubbed Unix Timestamps 3 + test_name: TestIndividualScrubbers/unix_timestamps 4 + file_name: scrubbers_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "created": <UNIX_TS>, 9 + "deleted": <UNIX_TS>, 10 + "name": "Test Event", 11 + "updated": <UNIX_TS> 12 + }
+11
__snapshots__/scrubbed_uuids.snap
··· 1 + --- 2 + title: Scrubbed UUIDs 3 + test_name: TestIndividualScrubbers/uuid 4 + file_name: scrubbers_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "name": "John Doe", 9 + "session_id": "<UUID>", 10 + "user_id": "<UUID>" 11 + }
+42
__snapshots__/snapjson_complex_api_response.snap
··· 1 + --- 2 + title: SnapJSON Complex API Response 3 + test_name: TestSnapJsonComplexAPI 4 + file_name: shutter_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "code": 200, 9 + "data": { 10 + "pagination": { 11 + "page": 1, 12 + "per_page": 10, 13 + "total": 3, 14 + "total_pages": 1 15 + }, 16 + "users": [ 17 + { 18 + "active": true, 19 + "department": "Engineering", 20 + "id": 1, 21 + "name": "Alice", 22 + "role": "admin" 23 + }, 24 + { 25 + "active": true, 26 + "department": "Sales", 27 + "id": 2, 28 + "name": "Bob", 29 + "role": "user" 30 + }, 31 + { 32 + "active": false, 33 + "department": "Marketing", 34 + "id": 3, 35 + "name": "Charlie", 36 + "role": "user" 37 + } 38 + ] 39 + }, 40 + "status": "success", 41 + "timestamp": "2023-11-18T21:45:30Z" 42 + }
+41
__snapshots__/snapjson_mixed_types.snap
··· 1 + --- 2 + title: SnapJSON Mixed Types 3 + test_name: TestSnapJsonMixedTypes 4 + file_name: shutter_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "complex": [ 9 + { 10 + "id": 1, 11 + "type": "user" 12 + }, 13 + { 14 + "id": 100, 15 + "type": "post" 16 + }, 17 + [ 18 + 1, 19 + 2, 20 + 3 21 + ], 22 + "string", 23 + null 24 + ], 25 + "mixed_array": [ 26 + "string", 27 + 123, 28 + 45.67, 29 + true, 30 + false, 31 + null, 32 + { 33 + "nested": "object" 34 + }, 35 + [ 36 + 1, 37 + 2, 38 + 3 39 + ] 40 + ] 41 + }
+26
__snapshots__/snapjson_nested_objects.snap
··· 1 + --- 2 + title: SnapJSON Nested Objects 3 + test_name: TestSnapJsonWithNestedObjects 4 + file_name: shutter_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "created_at": "2023-06-15T10:30:00Z", 9 + "user": { 10 + "id": 42, 11 + "permissions": [ 12 + "read", 13 + "write", 14 + "admin" 15 + ], 16 + "profile": { 17 + "avatar": "https://example.com/avatar.jpg", 18 + "settings": { 19 + "language": "en", 20 + "notifications": true, 21 + "theme": "dark" 22 + }, 23 + "username": "jane_smith" 24 + } 25 + } 26 + }
+84
__snapshots__/snapjson_real_world_example.snap
··· 1 + --- 2 + title: SnapJSON Real World Example 3 + test_name: TestSnapJsonRealWorldExample 4 + file_name: shutter_test.go 5 + version: 0.1.0 6 + --- 7 + { 8 + "data": { 9 + "product": { 10 + "description": "High-quality wireless headphones with noise cancellation", 11 + "id": "prod_12345", 12 + "inventory": { 13 + "available": 425, 14 + "damaged": 25, 15 + "reserved": 50, 16 + "total": 500 17 + }, 18 + "name": "Premium Wireless Headphones", 19 + "price": { 20 + "amount": 199.99, 21 + "currency": "USD", 22 + "discount": 10, 23 + "final_price": 179.99 24 + }, 25 + "ratings": { 26 + "average": 4.5, 27 + "breakdown": { 28 + "1": 20, 29 + "2": 30, 30 + "3": 100, 31 + "4": 350, 32 + "5": 750 33 + }, 34 + "count": 1250 35 + }, 36 + "reviews": [ 37 + { 38 + "content": "Great sound quality and comfortable to wear.", 39 + "created_at": "2023-11-15T10:30:00Z", 40 + "helpful": 25, 41 + "id": "rev_001", 42 + "rating": 5, 43 + "title": "Excellent product!", 44 + "user": "john_doe" 45 + }, 46 + { 47 + "content": "Works well, could be cheaper.", 48 + "created_at": "2023-11-10T14:20:00Z", 49 + "helpful": 12, 50 + "id": "rev_002", 51 + "rating": 4, 52 + "title": "Good but pricey", 53 + "user": "jane_smith" 54 + } 55 + ], 56 + "sku": "PWH-001", 57 + "specifications": { 58 + "battery_life": "30 hours", 59 + "colors": [ 60 + "black", 61 + "white", 62 + "blue" 63 + ], 64 + "warranty_months": 24, 65 + "weight": "250g" 66 + } 67 + }, 68 + "related_products": [ 69 + { 70 + "id": "prod_12346", 71 + "name": "Headphone Case", 72 + "price": 29.99 73 + }, 74 + { 75 + "id": "prod_12347", 76 + "name": "Audio Cable", 77 + "price": 14.99 78 + } 79 + ] 80 + }, 81 + "request_id": "req_abc123def456", 82 + "success": true, 83 + "timestamp": "2023-11-18T22:00:00Z" 84 + }
+34
__snapshots__/structure_with_empty_values.snap
··· 1 + --- 2 + title: Structure with Empty Values 3 + test_name: TestStructureWithEmptyValues 4 + file_name: shutter_test.go 5 + version: 0.1.0 6 + --- 7 + []shutter_test.Container{ 8 + { 9 + Items: []string{ 10 + }, 11 + Tags: map[string]string{ 12 + }, 13 + OptionalID: (*int)(nil), 14 + Count: 0, 15 + Active: false, 16 + }, 17 + { 18 + Items: []string(nil), 19 + Tags: map[string]string(nil), 20 + OptionalID: (*int)(nil), 21 + Count: 0, 22 + Active: true, 23 + }, 24 + { 25 + Items: []string{"a", "b", "c"}, 26 + Tags: map[string]string{ 27 + "env": "dev", 28 + "type": "test", 29 + }, 30 + OptionalID: &int(42), 31 + Count: 3, 32 + Active: true, 33 + }, 34 + }
+76
__snapshots__/structure_with_interface_fields.snap
··· 1 + --- 2 + title: Structure with Interface Fields 3 + test_name: TestStructureWithInterface 4 + file_name: shutter_test.go 5 + version: 0.1.0 6 + --- 7 + []shutter_test.Response{ 8 + { 9 + Status: "success", 10 + Message: "User retrieved", 11 + Data: shutter_test.User{ 12 + ID: 1, 13 + Username: "john", 14 + Email: "john@example.com", 15 + Active: true, 16 + CreatedAt: time.Time{ 17 + wall: 0x0, 18 + ext: 0, 19 + loc: (*time.Location)(nil), 20 + }, 21 + Roles: []string(nil), 22 + Metadata: map[string]interface{}(nil), 23 + }, 24 + Meta: map[string]interface{}{ 25 + "request_id": "req-123", 26 + "timestamp": "2023-01-20T10:30:00Z", 27 + }, 28 + }, 29 + { 30 + Status: "error", 31 + Message: "User not found", 32 + Data: nil, 33 + Meta: map[string]interface{}{ 34 + "error_code": 404, 35 + "error_type": "NOT_FOUND", 36 + }, 37 + }, 38 + { 39 + Status: "success", 40 + Message: "Posts retrieved", 41 + Data: []shutter_test.Post{ 42 + { 43 + ID: 1, 44 + Title: "First Post", 45 + Content: "", 46 + Author: shutter_test.User{ 47 + ID: 0, 48 + Username: "", 49 + Email: "", 50 + Active: false, 51 + CreatedAt: time.Time{ 52 + wall: 0x0, 53 + ext: 0, 54 + loc: (*time.Location)(nil), 55 + }, 56 + Roles: []string(nil), 57 + Metadata: map[string]interface{}(nil), 58 + }, 59 + Tags: []string(nil), 60 + Comments: []shutter_test.Comment(nil), 61 + Likes: 0, 62 + Published: true, 63 + CreatedAt: time.Time{ 64 + wall: 0x0, 65 + ext: 0, 66 + loc: (*time.Location)(nil), 67 + }, 68 + }, 69 + }, 70 + Meta: map[string]interface{}{ 71 + "page": 1, 72 + "per_page": 20, 73 + "total_count": 10, 74 + }, 75 + }, 76 + }
+27
__snapshots__/structure_with_pointers.snap
··· 1 + --- 2 + title: Structure with Pointers 3 + test_name: TestStructureWithPointers 4 + file_name: shutter_test.go 5 + version: 0.1.0 6 + --- 7 + shutter_test.Person{ 8 + Name: "John", 9 + Age: 35, 10 + Address: &shutter_test.Address{ 11 + Street: "123 Main St", 12 + City: "Boston", 13 + Zip: "02101", 14 + }, 15 + Manager: &shutter_test.Person{ 16 + Name: "Jane", 17 + Age: 30, 18 + Address: (*shutter_test.Address)(<already shown>), 19 + Manager: (*shutter_test.Person)(nil), 20 + Friends: []*shutter_test.Person(nil), 21 + Email: &string("jane@example.com"), 22 + }, 23 + Friends: []*shutter_test.Person{ 24 + (*shutter_test.Person)(<already shown>), 25 + }, 26 + Email: (*string)(nil), 27 + }
+45
editor/tree-sitter-snapshot/grammar.js
··· 1 + /** 2 + * @file Snapshot test files generated by Shutter 3 + * @author ptdewey 4 + * @license MIT 5 + */ 6 + 7 + /// <reference types="tree-sitter-cli/dsl" /> 8 + // @ts-check 9 + 10 + module.exports = grammar({ 11 + name: "snapshot", 12 + 13 + extras: $ => [], 14 + 15 + rules: { 16 + source_file: $ => seq( 17 + $.front_matter, 18 + optional($.body) 19 + ), 20 + 21 + front_matter: $ => seq( 22 + $.delimiter, 23 + repeat($.field), 24 + $.delimiter 25 + ), 26 + 27 + delimiter: $ => seq('---', '\n'), 28 + 29 + field: $ => seq( 30 + $.field_name, 31 + ':', 32 + optional(seq(' ', $.field_value)), 33 + '\n' 34 + ), 35 + 36 + field_name: $ => /[a-z_]+/, 37 + 38 + field_value: $ => /[^\n]+/, 39 + 40 + body: $ => repeat1(choice( 41 + /[^\n]+/, 42 + /\n/ 43 + )), 44 + } 45 + });
+10
editor/tree-sitter-snapshot/queries/highlights.scm
··· 1 + ; Snapshot file syntax highlighting 2 + 3 + ; Front matter delimiters 4 + (delimiter) @punctuation.delimiter 5 + 6 + ; Field names (keys) 7 + (field_name) @property 8 + 9 + ; Field values 10 + (field_value) @string
+23
editor/tree-sitter-snapshot/queries/injections.scm
··· 1 + ; Language injections for snapshot body content 2 + ; 3 + ; Explicit content_type field in header takes precedence if present. 4 + ; Otherwise, JSON objects and arrays are detected by heuristic. 5 + 6 + ; Explicit content_type field takes precedence 7 + ((front_matter 8 + (field 9 + (field_name) @_name 10 + (field_value) @injection.language)) 11 + (body) @injection.content 12 + (#eq? @_name "content_type")) 13 + 14 + ; JSON object: starts with { 15 + ((body) @injection.content 16 + (#match? @injection.content "^\\s*\\{") 17 + (#set! injection.language "json")) 18 + 19 + ; JSON array: starts with [ 20 + ((body) @injection.content 21 + (#match? @injection.content "^\\s*\\[") 22 + (#set! injection.language "json")) 23 +
+129
editor/tree-sitter-snapshot/src/grammar.json
··· 1 + { 2 + "$schema": "https://tree-sitter.github.io/tree-sitter/assets/schemas/grammar.schema.json", 3 + "name": "snapshot", 4 + "rules": { 5 + "source_file": { 6 + "type": "SEQ", 7 + "members": [ 8 + { 9 + "type": "SYMBOL", 10 + "name": "front_matter" 11 + }, 12 + { 13 + "type": "CHOICE", 14 + "members": [ 15 + { 16 + "type": "SYMBOL", 17 + "name": "body" 18 + }, 19 + { 20 + "type": "BLANK" 21 + } 22 + ] 23 + } 24 + ] 25 + }, 26 + "front_matter": { 27 + "type": "SEQ", 28 + "members": [ 29 + { 30 + "type": "SYMBOL", 31 + "name": "delimiter" 32 + }, 33 + { 34 + "type": "REPEAT", 35 + "content": { 36 + "type": "SYMBOL", 37 + "name": "field" 38 + } 39 + }, 40 + { 41 + "type": "SYMBOL", 42 + "name": "delimiter" 43 + } 44 + ] 45 + }, 46 + "delimiter": { 47 + "type": "SEQ", 48 + "members": [ 49 + { 50 + "type": "STRING", 51 + "value": "---" 52 + }, 53 + { 54 + "type": "STRING", 55 + "value": "\n" 56 + } 57 + ] 58 + }, 59 + "field": { 60 + "type": "SEQ", 61 + "members": [ 62 + { 63 + "type": "SYMBOL", 64 + "name": "field_name" 65 + }, 66 + { 67 + "type": "STRING", 68 + "value": ":" 69 + }, 70 + { 71 + "type": "CHOICE", 72 + "members": [ 73 + { 74 + "type": "SEQ", 75 + "members": [ 76 + { 77 + "type": "STRING", 78 + "value": " " 79 + }, 80 + { 81 + "type": "SYMBOL", 82 + "name": "field_value" 83 + } 84 + ] 85 + }, 86 + { 87 + "type": "BLANK" 88 + } 89 + ] 90 + }, 91 + { 92 + "type": "STRING", 93 + "value": "\n" 94 + } 95 + ] 96 + }, 97 + "field_name": { 98 + "type": "PATTERN", 99 + "value": "[a-z_]+" 100 + }, 101 + "field_value": { 102 + "type": "PATTERN", 103 + "value": "[^\\n]+" 104 + }, 105 + "body": { 106 + "type": "REPEAT1", 107 + "content": { 108 + "type": "CHOICE", 109 + "members": [ 110 + { 111 + "type": "PATTERN", 112 + "value": "[^\\n]+" 113 + }, 114 + { 115 + "type": "PATTERN", 116 + "value": "\\n" 117 + } 118 + ] 119 + } 120 + } 121 + }, 122 + "extras": [], 123 + "conflicts": [], 124 + "precedences": [], 125 + "externals": [], 126 + "inline": [], 127 + "supertypes": [], 128 + "reserved": {} 129 + }
+95
editor/tree-sitter-snapshot/src/node-types.json
··· 1 + [ 2 + { 3 + "type": "body", 4 + "named": true, 5 + "fields": {} 6 + }, 7 + { 8 + "type": "delimiter", 9 + "named": true, 10 + "fields": {} 11 + }, 12 + { 13 + "type": "field", 14 + "named": true, 15 + "fields": {}, 16 + "children": { 17 + "multiple": true, 18 + "required": true, 19 + "types": [ 20 + { 21 + "type": "field_name", 22 + "named": true 23 + }, 24 + { 25 + "type": "field_value", 26 + "named": true 27 + } 28 + ] 29 + } 30 + }, 31 + { 32 + "type": "field_value", 33 + "named": true, 34 + "fields": {} 35 + }, 36 + { 37 + "type": "front_matter", 38 + "named": true, 39 + "fields": {}, 40 + "children": { 41 + "multiple": true, 42 + "required": true, 43 + "types": [ 44 + { 45 + "type": "delimiter", 46 + "named": true 47 + }, 48 + { 49 + "type": "field", 50 + "named": true 51 + } 52 + ] 53 + } 54 + }, 55 + { 56 + "type": "source_file", 57 + "named": true, 58 + "root": true, 59 + "fields": {}, 60 + "children": { 61 + "multiple": true, 62 + "required": true, 63 + "types": [ 64 + { 65 + "type": "body", 66 + "named": true 67 + }, 68 + { 69 + "type": "front_matter", 70 + "named": true 71 + } 72 + ] 73 + } 74 + }, 75 + { 76 + "type": "\n", 77 + "named": false 78 + }, 79 + { 80 + "type": " ", 81 + "named": false 82 + }, 83 + { 84 + "type": "---", 85 + "named": false 86 + }, 87 + { 88 + "type": ":", 89 + "named": false 90 + }, 91 + { 92 + "type": "field_name", 93 + "named": true 94 + } 95 + ]
+502
editor/tree-sitter-snapshot/src/parser.c
··· 1 + /* Automatically @generated by tree-sitter v0.25.10 */ 2 + 3 + #include "tree_sitter/parser.h" 4 + 5 + #if defined(__GNUC__) || defined(__clang__) 6 + #pragma GCC diagnostic ignored "-Wmissing-field-initializers" 7 + #endif 8 + 9 + #define LANGUAGE_VERSION 15 10 + #define STATE_COUNT 23 11 + #define LARGE_STATE_COUNT 2 12 + #define SYMBOL_COUNT 16 13 + #define ALIAS_COUNT 0 14 + #define TOKEN_COUNT 8 15 + #define EXTERNAL_TOKEN_COUNT 0 16 + #define FIELD_COUNT 0 17 + #define MAX_ALIAS_SEQUENCE_LENGTH 5 18 + #define MAX_RESERVED_WORD_SET_SIZE 0 19 + #define PRODUCTION_ID_COUNT 1 20 + #define SUPERTYPE_COUNT 0 21 + 22 + enum ts_symbol_identifiers { 23 + anon_sym_DASH_DASH_DASH = 1, 24 + anon_sym_LF = 2, 25 + anon_sym_COLON = 3, 26 + anon_sym_SPACE = 4, 27 + sym_field_name = 5, 28 + aux_sym_field_value_token1 = 6, 29 + aux_sym_body_token1 = 7, 30 + sym_source_file = 8, 31 + sym_front_matter = 9, 32 + sym_delimiter = 10, 33 + sym_field = 11, 34 + sym_field_value = 12, 35 + sym_body = 13, 36 + aux_sym_front_matter_repeat1 = 14, 37 + aux_sym_body_repeat1 = 15, 38 + }; 39 + 40 + static const char * const ts_symbol_names[] = { 41 + [ts_builtin_sym_end] = "end", 42 + [anon_sym_DASH_DASH_DASH] = "---", 43 + [anon_sym_LF] = "\n", 44 + [anon_sym_COLON] = ":", 45 + [anon_sym_SPACE] = " ", 46 + [sym_field_name] = "field_name", 47 + [aux_sym_field_value_token1] = "field_value_token1", 48 + [aux_sym_body_token1] = "body_token1", 49 + [sym_source_file] = "source_file", 50 + [sym_front_matter] = "front_matter", 51 + [sym_delimiter] = "delimiter", 52 + [sym_field] = "field", 53 + [sym_field_value] = "field_value", 54 + [sym_body] = "body", 55 + [aux_sym_front_matter_repeat1] = "front_matter_repeat1", 56 + [aux_sym_body_repeat1] = "body_repeat1", 57 + }; 58 + 59 + static const TSSymbol ts_symbol_map[] = { 60 + [ts_builtin_sym_end] = ts_builtin_sym_end, 61 + [anon_sym_DASH_DASH_DASH] = anon_sym_DASH_DASH_DASH, 62 + [anon_sym_LF] = anon_sym_LF, 63 + [anon_sym_COLON] = anon_sym_COLON, 64 + [anon_sym_SPACE] = anon_sym_SPACE, 65 + [sym_field_name] = sym_field_name, 66 + [aux_sym_field_value_token1] = aux_sym_field_value_token1, 67 + [aux_sym_body_token1] = aux_sym_body_token1, 68 + [sym_source_file] = sym_source_file, 69 + [sym_front_matter] = sym_front_matter, 70 + [sym_delimiter] = sym_delimiter, 71 + [sym_field] = sym_field, 72 + [sym_field_value] = sym_field_value, 73 + [sym_body] = sym_body, 74 + [aux_sym_front_matter_repeat1] = aux_sym_front_matter_repeat1, 75 + [aux_sym_body_repeat1] = aux_sym_body_repeat1, 76 + }; 77 + 78 + static const TSSymbolMetadata ts_symbol_metadata[] = { 79 + [ts_builtin_sym_end] = { 80 + .visible = false, 81 + .named = true, 82 + }, 83 + [anon_sym_DASH_DASH_DASH] = { 84 + .visible = true, 85 + .named = false, 86 + }, 87 + [anon_sym_LF] = { 88 + .visible = true, 89 + .named = false, 90 + }, 91 + [anon_sym_COLON] = { 92 + .visible = true, 93 + .named = false, 94 + }, 95 + [anon_sym_SPACE] = { 96 + .visible = true, 97 + .named = false, 98 + }, 99 + [sym_field_name] = { 100 + .visible = true, 101 + .named = true, 102 + }, 103 + [aux_sym_field_value_token1] = { 104 + .visible = false, 105 + .named = false, 106 + }, 107 + [aux_sym_body_token1] = { 108 + .visible = false, 109 + .named = false, 110 + }, 111 + [sym_source_file] = { 112 + .visible = true, 113 + .named = true, 114 + }, 115 + [sym_front_matter] = { 116 + .visible = true, 117 + .named = true, 118 + }, 119 + [sym_delimiter] = { 120 + .visible = true, 121 + .named = true, 122 + }, 123 + [sym_field] = { 124 + .visible = true, 125 + .named = true, 126 + }, 127 + [sym_field_value] = { 128 + .visible = true, 129 + .named = true, 130 + }, 131 + [sym_body] = { 132 + .visible = true, 133 + .named = true, 134 + }, 135 + [aux_sym_front_matter_repeat1] = { 136 + .visible = false, 137 + .named = false, 138 + }, 139 + [aux_sym_body_repeat1] = { 140 + .visible = false, 141 + .named = false, 142 + }, 143 + }; 144 + 145 + static const TSSymbol ts_alias_sequences[PRODUCTION_ID_COUNT][MAX_ALIAS_SEQUENCE_LENGTH] = { 146 + [0] = {0}, 147 + }; 148 + 149 + static const uint16_t ts_non_terminal_alias_map[] = { 150 + 0, 151 + }; 152 + 153 + static const TSStateId ts_primary_state_ids[STATE_COUNT] = { 154 + [0] = 0, 155 + [1] = 1, 156 + [2] = 2, 157 + [3] = 3, 158 + [4] = 4, 159 + [5] = 5, 160 + [6] = 6, 161 + [7] = 7, 162 + [8] = 8, 163 + [9] = 9, 164 + [10] = 10, 165 + [11] = 10, 166 + [12] = 12, 167 + [13] = 13, 168 + [14] = 14, 169 + [15] = 15, 170 + [16] = 16, 171 + [17] = 17, 172 + [18] = 18, 173 + [19] = 19, 174 + [20] = 20, 175 + [21] = 21, 176 + [22] = 16, 177 + }; 178 + 179 + static bool ts_lex(TSLexer *lexer, TSStateId state) { 180 + START_LEXER(); 181 + eof = lexer->eof(lexer); 182 + switch (state) { 183 + case 0: 184 + if (eof) ADVANCE(5); 185 + if (lookahead == '\n') ADVANCE(7); 186 + if (lookahead == ' ') ADVANCE(9); 187 + if (lookahead == '-') ADVANCE(3); 188 + if (lookahead == ':') ADVANCE(8); 189 + if (lookahead == '_' || 190 + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(10); 191 + END_STATE(); 192 + case 1: 193 + if (lookahead == '\n') ADVANCE(7); 194 + if (lookahead == ' ') ADVANCE(9); 195 + END_STATE(); 196 + case 2: 197 + if (lookahead == '-') ADVANCE(6); 198 + END_STATE(); 199 + case 3: 200 + if (lookahead == '-') ADVANCE(2); 201 + END_STATE(); 202 + case 4: 203 + if (eof) ADVANCE(5); 204 + if (lookahead == '\n') ADVANCE(12); 205 + if (lookahead != 0) ADVANCE(11); 206 + END_STATE(); 207 + case 5: 208 + ACCEPT_TOKEN(ts_builtin_sym_end); 209 + END_STATE(); 210 + case 6: 211 + ACCEPT_TOKEN(anon_sym_DASH_DASH_DASH); 212 + END_STATE(); 213 + case 7: 214 + ACCEPT_TOKEN(anon_sym_LF); 215 + END_STATE(); 216 + case 8: 217 + ACCEPT_TOKEN(anon_sym_COLON); 218 + END_STATE(); 219 + case 9: 220 + ACCEPT_TOKEN(anon_sym_SPACE); 221 + END_STATE(); 222 + case 10: 223 + ACCEPT_TOKEN(sym_field_name); 224 + if (lookahead == '_' || 225 + ('a' <= lookahead && lookahead <= 'z')) ADVANCE(10); 226 + END_STATE(); 227 + case 11: 228 + ACCEPT_TOKEN(aux_sym_field_value_token1); 229 + if (lookahead != 0 && 230 + lookahead != '\n') ADVANCE(11); 231 + END_STATE(); 232 + case 12: 233 + ACCEPT_TOKEN(aux_sym_body_token1); 234 + END_STATE(); 235 + default: 236 + return false; 237 + } 238 + } 239 + 240 + static const TSLexerMode ts_lex_modes[STATE_COUNT] = { 241 + [0] = {.lex_state = 0}, 242 + [1] = {.lex_state = 0}, 243 + [2] = {.lex_state = 0}, 244 + [3] = {.lex_state = 4}, 245 + [4] = {.lex_state = 0}, 246 + [5] = {.lex_state = 4}, 247 + [6] = {.lex_state = 4}, 248 + [7] = {.lex_state = 0}, 249 + [8] = {.lex_state = 4}, 250 + [9] = {.lex_state = 4}, 251 + [10] = {.lex_state = 4}, 252 + [11] = {.lex_state = 0}, 253 + [12] = {.lex_state = 1}, 254 + [13] = {.lex_state = 0}, 255 + [14] = {.lex_state = 4}, 256 + [15] = {.lex_state = 0}, 257 + [16] = {.lex_state = 1}, 258 + [17] = {.lex_state = 0}, 259 + [18] = {.lex_state = 0}, 260 + [19] = {.lex_state = 0}, 261 + [20] = {.lex_state = 1}, 262 + [21] = {.lex_state = 1}, 263 + [22] = {.lex_state = 1}, 264 + }; 265 + 266 + static const uint16_t ts_parse_table[LARGE_STATE_COUNT][SYMBOL_COUNT] = { 267 + [STATE(0)] = { 268 + [ts_builtin_sym_end] = ACTIONS(1), 269 + [anon_sym_DASH_DASH_DASH] = ACTIONS(1), 270 + [anon_sym_LF] = ACTIONS(1), 271 + [anon_sym_COLON] = ACTIONS(1), 272 + [anon_sym_SPACE] = ACTIONS(1), 273 + [sym_field_name] = ACTIONS(1), 274 + [aux_sym_body_token1] = ACTIONS(1), 275 + }, 276 + [STATE(1)] = { 277 + [sym_source_file] = STATE(18), 278 + [sym_front_matter] = STATE(3), 279 + [sym_delimiter] = STATE(2), 280 + [anon_sym_DASH_DASH_DASH] = ACTIONS(3), 281 + }, 282 + }; 283 + 284 + static const uint16_t ts_small_parse_table[] = { 285 + [0] = 4, 286 + ACTIONS(5), 1, 287 + anon_sym_DASH_DASH_DASH, 288 + ACTIONS(7), 1, 289 + sym_field_name, 290 + STATE(8), 1, 291 + sym_delimiter, 292 + STATE(4), 2, 293 + sym_field, 294 + aux_sym_front_matter_repeat1, 295 + [14] = 4, 296 + ACTIONS(9), 1, 297 + ts_builtin_sym_end, 298 + STATE(5), 1, 299 + aux_sym_body_repeat1, 300 + STATE(17), 1, 301 + sym_body, 302 + ACTIONS(11), 2, 303 + aux_sym_field_value_token1, 304 + aux_sym_body_token1, 305 + [28] = 4, 306 + ACTIONS(5), 1, 307 + anon_sym_DASH_DASH_DASH, 308 + ACTIONS(7), 1, 309 + sym_field_name, 310 + STATE(9), 1, 311 + sym_delimiter, 312 + STATE(7), 2, 313 + sym_field, 314 + aux_sym_front_matter_repeat1, 315 + [42] = 3, 316 + ACTIONS(13), 1, 317 + ts_builtin_sym_end, 318 + STATE(6), 1, 319 + aux_sym_body_repeat1, 320 + ACTIONS(15), 2, 321 + aux_sym_field_value_token1, 322 + aux_sym_body_token1, 323 + [53] = 3, 324 + ACTIONS(17), 1, 325 + ts_builtin_sym_end, 326 + STATE(6), 1, 327 + aux_sym_body_repeat1, 328 + ACTIONS(19), 2, 329 + aux_sym_field_value_token1, 330 + aux_sym_body_token1, 331 + [64] = 3, 332 + ACTIONS(22), 1, 333 + anon_sym_DASH_DASH_DASH, 334 + ACTIONS(24), 1, 335 + sym_field_name, 336 + STATE(7), 2, 337 + sym_field, 338 + aux_sym_front_matter_repeat1, 339 + [75] = 1, 340 + ACTIONS(27), 3, 341 + ts_builtin_sym_end, 342 + aux_sym_field_value_token1, 343 + aux_sym_body_token1, 344 + [81] = 1, 345 + ACTIONS(29), 3, 346 + ts_builtin_sym_end, 347 + aux_sym_field_value_token1, 348 + aux_sym_body_token1, 349 + [87] = 1, 350 + ACTIONS(31), 3, 351 + ts_builtin_sym_end, 352 + aux_sym_field_value_token1, 353 + aux_sym_body_token1, 354 + [93] = 1, 355 + ACTIONS(31), 2, 356 + anon_sym_DASH_DASH_DASH, 357 + sym_field_name, 358 + [98] = 2, 359 + ACTIONS(33), 1, 360 + anon_sym_LF, 361 + ACTIONS(35), 1, 362 + anon_sym_SPACE, 363 + [105] = 1, 364 + ACTIONS(37), 2, 365 + anon_sym_DASH_DASH_DASH, 366 + sym_field_name, 367 + [110] = 2, 368 + ACTIONS(39), 1, 369 + aux_sym_field_value_token1, 370 + STATE(21), 1, 371 + sym_field_value, 372 + [117] = 1, 373 + ACTIONS(41), 2, 374 + anon_sym_DASH_DASH_DASH, 375 + sym_field_name, 376 + [122] = 1, 377 + ACTIONS(43), 1, 378 + anon_sym_LF, 379 + [126] = 1, 380 + ACTIONS(45), 1, 381 + ts_builtin_sym_end, 382 + [130] = 1, 383 + ACTIONS(47), 1, 384 + ts_builtin_sym_end, 385 + [134] = 1, 386 + ACTIONS(49), 1, 387 + anon_sym_COLON, 388 + [138] = 1, 389 + ACTIONS(51), 1, 390 + anon_sym_LF, 391 + [142] = 1, 392 + ACTIONS(53), 1, 393 + anon_sym_LF, 394 + [146] = 1, 395 + ACTIONS(55), 1, 396 + anon_sym_LF, 397 + }; 398 + 399 + static const uint32_t ts_small_parse_table_map[] = { 400 + [SMALL_STATE(2)] = 0, 401 + [SMALL_STATE(3)] = 14, 402 + [SMALL_STATE(4)] = 28, 403 + [SMALL_STATE(5)] = 42, 404 + [SMALL_STATE(6)] = 53, 405 + [SMALL_STATE(7)] = 64, 406 + [SMALL_STATE(8)] = 75, 407 + [SMALL_STATE(9)] = 81, 408 + [SMALL_STATE(10)] = 87, 409 + [SMALL_STATE(11)] = 93, 410 + [SMALL_STATE(12)] = 98, 411 + [SMALL_STATE(13)] = 105, 412 + [SMALL_STATE(14)] = 110, 413 + [SMALL_STATE(15)] = 117, 414 + [SMALL_STATE(16)] = 122, 415 + [SMALL_STATE(17)] = 126, 416 + [SMALL_STATE(18)] = 130, 417 + [SMALL_STATE(19)] = 134, 418 + [SMALL_STATE(20)] = 138, 419 + [SMALL_STATE(21)] = 142, 420 + [SMALL_STATE(22)] = 146, 421 + }; 422 + 423 + static const TSParseActionEntry ts_parse_actions[] = { 424 + [0] = {.entry = {.count = 0, .reusable = false}}, 425 + [1] = {.entry = {.count = 1, .reusable = false}}, RECOVER(), 426 + [3] = {.entry = {.count = 1, .reusable = true}}, SHIFT(16), 427 + [5] = {.entry = {.count = 1, .reusable = true}}, SHIFT(22), 428 + [7] = {.entry = {.count = 1, .reusable = true}}, SHIFT(19), 429 + [9] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source_file, 1, 0, 0), 430 + [11] = {.entry = {.count = 1, .reusable = true}}, SHIFT(5), 431 + [13] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_body, 1, 0, 0), 432 + [15] = {.entry = {.count = 1, .reusable = true}}, SHIFT(6), 433 + [17] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_body_repeat1, 2, 0, 0), 434 + [19] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_body_repeat1, 2, 0, 0), SHIFT_REPEAT(6), 435 + [22] = {.entry = {.count = 1, .reusable = true}}, REDUCE(aux_sym_front_matter_repeat1, 2, 0, 0), 436 + [24] = {.entry = {.count = 2, .reusable = true}}, REDUCE(aux_sym_front_matter_repeat1, 2, 0, 0), SHIFT_REPEAT(19), 437 + [27] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_front_matter, 2, 0, 0), 438 + [29] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_front_matter, 3, 0, 0), 439 + [31] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_delimiter, 2, 0, 0), 440 + [33] = {.entry = {.count = 1, .reusable = true}}, SHIFT(13), 441 + [35] = {.entry = {.count = 1, .reusable = true}}, SHIFT(14), 442 + [37] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_field, 3, 0, 0), 443 + [39] = {.entry = {.count = 1, .reusable = true}}, SHIFT(20), 444 + [41] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_field, 5, 0, 0), 445 + [43] = {.entry = {.count = 1, .reusable = true}}, SHIFT(11), 446 + [45] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_source_file, 2, 0, 0), 447 + [47] = {.entry = {.count = 1, .reusable = true}}, ACCEPT_INPUT(), 448 + [49] = {.entry = {.count = 1, .reusable = true}}, SHIFT(12), 449 + [51] = {.entry = {.count = 1, .reusable = true}}, REDUCE(sym_field_value, 1, 0, 0), 450 + [53] = {.entry = {.count = 1, .reusable = true}}, SHIFT(15), 451 + [55] = {.entry = {.count = 1, .reusable = true}}, SHIFT(10), 452 + }; 453 + 454 + #ifdef __cplusplus 455 + extern "C" { 456 + #endif 457 + #ifdef TREE_SITTER_HIDE_SYMBOLS 458 + #define TS_PUBLIC 459 + #elif defined(_WIN32) 460 + #define TS_PUBLIC __declspec(dllexport) 461 + #else 462 + #define TS_PUBLIC __attribute__((visibility("default"))) 463 + #endif 464 + 465 + TS_PUBLIC const TSLanguage *tree_sitter_snapshot(void) { 466 + static const TSLanguage language = { 467 + .abi_version = LANGUAGE_VERSION, 468 + .symbol_count = SYMBOL_COUNT, 469 + .alias_count = ALIAS_COUNT, 470 + .token_count = TOKEN_COUNT, 471 + .external_token_count = EXTERNAL_TOKEN_COUNT, 472 + .state_count = STATE_COUNT, 473 + .large_state_count = LARGE_STATE_COUNT, 474 + .production_id_count = PRODUCTION_ID_COUNT, 475 + .supertype_count = SUPERTYPE_COUNT, 476 + .field_count = FIELD_COUNT, 477 + .max_alias_sequence_length = MAX_ALIAS_SEQUENCE_LENGTH, 478 + .parse_table = &ts_parse_table[0][0], 479 + .small_parse_table = ts_small_parse_table, 480 + .small_parse_table_map = ts_small_parse_table_map, 481 + .parse_actions = ts_parse_actions, 482 + .symbol_names = ts_symbol_names, 483 + .symbol_metadata = ts_symbol_metadata, 484 + .public_symbol_map = ts_symbol_map, 485 + .alias_map = ts_non_terminal_alias_map, 486 + .alias_sequences = &ts_alias_sequences[0][0], 487 + .lex_modes = (const void*)ts_lex_modes, 488 + .lex_fn = ts_lex, 489 + .primary_state_ids = ts_primary_state_ids, 490 + .name = "snapshot", 491 + .max_reserved_word_set_size = 0, 492 + .metadata = { 493 + .major_version = 0, 494 + .minor_version = 1, 495 + .patch_version = 0, 496 + }, 497 + }; 498 + return &language; 499 + } 500 + #ifdef __cplusplus 501 + } 502 + #endif
+54
editor/tree-sitter-snapshot/src/tree_sitter/alloc.h
··· 1 + #ifndef TREE_SITTER_ALLOC_H_ 2 + #define TREE_SITTER_ALLOC_H_ 3 + 4 + #ifdef __cplusplus 5 + extern "C" { 6 + #endif 7 + 8 + #include <stdbool.h> 9 + #include <stdio.h> 10 + #include <stdlib.h> 11 + 12 + // Allow clients to override allocation functions 13 + #ifdef TREE_SITTER_REUSE_ALLOCATOR 14 + 15 + extern void *(*ts_current_malloc)(size_t size); 16 + extern void *(*ts_current_calloc)(size_t count, size_t size); 17 + extern void *(*ts_current_realloc)(void *ptr, size_t size); 18 + extern void (*ts_current_free)(void *ptr); 19 + 20 + #ifndef ts_malloc 21 + #define ts_malloc ts_current_malloc 22 + #endif 23 + #ifndef ts_calloc 24 + #define ts_calloc ts_current_calloc 25 + #endif 26 + #ifndef ts_realloc 27 + #define ts_realloc ts_current_realloc 28 + #endif 29 + #ifndef ts_free 30 + #define ts_free ts_current_free 31 + #endif 32 + 33 + #else 34 + 35 + #ifndef ts_malloc 36 + #define ts_malloc malloc 37 + #endif 38 + #ifndef ts_calloc 39 + #define ts_calloc calloc 40 + #endif 41 + #ifndef ts_realloc 42 + #define ts_realloc realloc 43 + #endif 44 + #ifndef ts_free 45 + #define ts_free free 46 + #endif 47 + 48 + #endif 49 + 50 + #ifdef __cplusplus 51 + } 52 + #endif 53 + 54 + #endif // TREE_SITTER_ALLOC_H_
+291
editor/tree-sitter-snapshot/src/tree_sitter/array.h
··· 1 + #ifndef TREE_SITTER_ARRAY_H_ 2 + #define TREE_SITTER_ARRAY_H_ 3 + 4 + #ifdef __cplusplus 5 + extern "C" { 6 + #endif 7 + 8 + #include "./alloc.h" 9 + 10 + #include <assert.h> 11 + #include <stdbool.h> 12 + #include <stdint.h> 13 + #include <stdlib.h> 14 + #include <string.h> 15 + 16 + #ifdef _MSC_VER 17 + #pragma warning(push) 18 + #pragma warning(disable : 4101) 19 + #elif defined(__GNUC__) || defined(__clang__) 20 + #pragma GCC diagnostic push 21 + #pragma GCC diagnostic ignored "-Wunused-variable" 22 + #endif 23 + 24 + #define Array(T) \ 25 + struct { \ 26 + T *contents; \ 27 + uint32_t size; \ 28 + uint32_t capacity; \ 29 + } 30 + 31 + /// Initialize an array. 32 + #define array_init(self) \ 33 + ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL) 34 + 35 + /// Create an empty array. 36 + #define array_new() \ 37 + { NULL, 0, 0 } 38 + 39 + /// Get a pointer to the element at a given `index` in the array. 40 + #define array_get(self, _index) \ 41 + (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index]) 42 + 43 + /// Get a pointer to the first element in the array. 44 + #define array_front(self) array_get(self, 0) 45 + 46 + /// Get a pointer to the last element in the array. 47 + #define array_back(self) array_get(self, (self)->size - 1) 48 + 49 + /// Clear the array, setting its size to zero. Note that this does not free any 50 + /// memory allocated for the array's contents. 51 + #define array_clear(self) ((self)->size = 0) 52 + 53 + /// Reserve `new_capacity` elements of space in the array. If `new_capacity` is 54 + /// less than the array's current capacity, this function has no effect. 55 + #define array_reserve(self, new_capacity) \ 56 + _array__reserve((Array *)(self), array_elem_size(self), new_capacity) 57 + 58 + /// Free any memory allocated for this array. Note that this does not free any 59 + /// memory allocated for the array's contents. 60 + #define array_delete(self) _array__delete((Array *)(self)) 61 + 62 + /// Push a new `element` onto the end of the array. 63 + #define array_push(self, element) \ 64 + (_array__grow((Array *)(self), 1, array_elem_size(self)), \ 65 + (self)->contents[(self)->size++] = (element)) 66 + 67 + /// Increase the array's size by `count` elements. 68 + /// New elements are zero-initialized. 69 + #define array_grow_by(self, count) \ 70 + do { \ 71 + if ((count) == 0) break; \ 72 + _array__grow((Array *)(self), count, array_elem_size(self)); \ 73 + memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \ 74 + (self)->size += (count); \ 75 + } while (0) 76 + 77 + /// Append all elements from one array to the end of another. 78 + #define array_push_all(self, other) \ 79 + array_extend((self), (other)->size, (other)->contents) 80 + 81 + /// Append `count` elements to the end of the array, reading their values from the 82 + /// `contents` pointer. 83 + #define array_extend(self, count, contents) \ 84 + _array__splice( \ 85 + (Array *)(self), array_elem_size(self), (self)->size, \ 86 + 0, count, contents \ 87 + ) 88 + 89 + /// Remove `old_count` elements from the array starting at the given `index`. At 90 + /// the same index, insert `new_count` new elements, reading their values from the 91 + /// `new_contents` pointer. 92 + #define array_splice(self, _index, old_count, new_count, new_contents) \ 93 + _array__splice( \ 94 + (Array *)(self), array_elem_size(self), _index, \ 95 + old_count, new_count, new_contents \ 96 + ) 97 + 98 + /// Insert one `element` into the array at the given `index`. 99 + #define array_insert(self, _index, element) \ 100 + _array__splice((Array *)(self), array_elem_size(self), _index, 0, 1, &(element)) 101 + 102 + /// Remove one element from the array at the given `index`. 103 + #define array_erase(self, _index) \ 104 + _array__erase((Array *)(self), array_elem_size(self), _index) 105 + 106 + /// Pop the last element off the array, returning the element by value. 107 + #define array_pop(self) ((self)->contents[--(self)->size]) 108 + 109 + /// Assign the contents of one array to another, reallocating if necessary. 110 + #define array_assign(self, other) \ 111 + _array__assign((Array *)(self), (const Array *)(other), array_elem_size(self)) 112 + 113 + /// Swap one array with another 114 + #define array_swap(self, other) \ 115 + _array__swap((Array *)(self), (Array *)(other)) 116 + 117 + /// Get the size of the array contents 118 + #define array_elem_size(self) (sizeof *(self)->contents) 119 + 120 + /// Search a sorted array for a given `needle` value, using the given `compare` 121 + /// callback to determine the order. 122 + /// 123 + /// If an existing element is found to be equal to `needle`, then the `index` 124 + /// out-parameter is set to the existing value's index, and the `exists` 125 + /// out-parameter is set to true. Otherwise, `index` is set to an index where 126 + /// `needle` should be inserted in order to preserve the sorting, and `exists` 127 + /// is set to false. 128 + #define array_search_sorted_with(self, compare, needle, _index, _exists) \ 129 + _array__search_sorted(self, 0, compare, , needle, _index, _exists) 130 + 131 + /// Search a sorted array for a given `needle` value, using integer comparisons 132 + /// of a given struct field (specified with a leading dot) to determine the order. 133 + /// 134 + /// See also `array_search_sorted_with`. 135 + #define array_search_sorted_by(self, field, needle, _index, _exists) \ 136 + _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists) 137 + 138 + /// Insert a given `value` into a sorted array, using the given `compare` 139 + /// callback to determine the order. 140 + #define array_insert_sorted_with(self, compare, value) \ 141 + do { \ 142 + unsigned _index, _exists; \ 143 + array_search_sorted_with(self, compare, &(value), &_index, &_exists); \ 144 + if (!_exists) array_insert(self, _index, value); \ 145 + } while (0) 146 + 147 + /// Insert a given `value` into a sorted array, using integer comparisons of 148 + /// a given struct field (specified with a leading dot) to determine the order. 149 + /// 150 + /// See also `array_search_sorted_by`. 151 + #define array_insert_sorted_by(self, field, value) \ 152 + do { \ 153 + unsigned _index, _exists; \ 154 + array_search_sorted_by(self, field, (value) field, &_index, &_exists); \ 155 + if (!_exists) array_insert(self, _index, value); \ 156 + } while (0) 157 + 158 + // Private 159 + 160 + typedef Array(void) Array; 161 + 162 + /// This is not what you're looking for, see `array_delete`. 163 + static inline void _array__delete(Array *self) { 164 + if (self->contents) { 165 + ts_free(self->contents); 166 + self->contents = NULL; 167 + self->size = 0; 168 + self->capacity = 0; 169 + } 170 + } 171 + 172 + /// This is not what you're looking for, see `array_erase`. 173 + static inline void _array__erase(Array *self, size_t element_size, 174 + uint32_t index) { 175 + assert(index < self->size); 176 + char *contents = (char *)self->contents; 177 + memmove(contents + index * element_size, contents + (index + 1) * element_size, 178 + (self->size - index - 1) * element_size); 179 + self->size--; 180 + } 181 + 182 + /// This is not what you're looking for, see `array_reserve`. 183 + static inline void _array__reserve(Array *self, size_t element_size, uint32_t new_capacity) { 184 + if (new_capacity > self->capacity) { 185 + if (self->contents) { 186 + self->contents = ts_realloc(self->contents, new_capacity * element_size); 187 + } else { 188 + self->contents = ts_malloc(new_capacity * element_size); 189 + } 190 + self->capacity = new_capacity; 191 + } 192 + } 193 + 194 + /// This is not what you're looking for, see `array_assign`. 195 + static inline void _array__assign(Array *self, const Array *other, size_t element_size) { 196 + _array__reserve(self, element_size, other->size); 197 + self->size = other->size; 198 + memcpy(self->contents, other->contents, self->size * element_size); 199 + } 200 + 201 + /// This is not what you're looking for, see `array_swap`. 202 + static inline void _array__swap(Array *self, Array *other) { 203 + Array swap = *other; 204 + *other = *self; 205 + *self = swap; 206 + } 207 + 208 + /// This is not what you're looking for, see `array_push` or `array_grow_by`. 209 + static inline void _array__grow(Array *self, uint32_t count, size_t element_size) { 210 + uint32_t new_size = self->size + count; 211 + if (new_size > self->capacity) { 212 + uint32_t new_capacity = self->capacity * 2; 213 + if (new_capacity < 8) new_capacity = 8; 214 + if (new_capacity < new_size) new_capacity = new_size; 215 + _array__reserve(self, element_size, new_capacity); 216 + } 217 + } 218 + 219 + /// This is not what you're looking for, see `array_splice`. 220 + static inline void _array__splice(Array *self, size_t element_size, 221 + uint32_t index, uint32_t old_count, 222 + uint32_t new_count, const void *elements) { 223 + uint32_t new_size = self->size + new_count - old_count; 224 + uint32_t old_end = index + old_count; 225 + uint32_t new_end = index + new_count; 226 + assert(old_end <= self->size); 227 + 228 + _array__reserve(self, element_size, new_size); 229 + 230 + char *contents = (char *)self->contents; 231 + if (self->size > old_end) { 232 + memmove( 233 + contents + new_end * element_size, 234 + contents + old_end * element_size, 235 + (self->size - old_end) * element_size 236 + ); 237 + } 238 + if (new_count > 0) { 239 + if (elements) { 240 + memcpy( 241 + (contents + index * element_size), 242 + elements, 243 + new_count * element_size 244 + ); 245 + } else { 246 + memset( 247 + (contents + index * element_size), 248 + 0, 249 + new_count * element_size 250 + ); 251 + } 252 + } 253 + self->size += new_count - old_count; 254 + } 255 + 256 + /// A binary search routine, based on Rust's `std::slice::binary_search_by`. 257 + /// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`. 258 + #define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \ 259 + do { \ 260 + *(_index) = start; \ 261 + *(_exists) = false; \ 262 + uint32_t size = (self)->size - *(_index); \ 263 + if (size == 0) break; \ 264 + int comparison; \ 265 + while (size > 1) { \ 266 + uint32_t half_size = size / 2; \ 267 + uint32_t mid_index = *(_index) + half_size; \ 268 + comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \ 269 + if (comparison <= 0) *(_index) = mid_index; \ 270 + size -= half_size; \ 271 + } \ 272 + comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \ 273 + if (comparison == 0) *(_exists) = true; \ 274 + else if (comparison < 0) *(_index) += 1; \ 275 + } while (0) 276 + 277 + /// Helper macro for the `_sorted_by` routines below. This takes the left (existing) 278 + /// parameter by reference in order to work with the generic sorting function above. 279 + #define _compare_int(a, b) ((int)*(a) - (int)(b)) 280 + 281 + #ifdef _MSC_VER 282 + #pragma warning(pop) 283 + #elif defined(__GNUC__) || defined(__clang__) 284 + #pragma GCC diagnostic pop 285 + #endif 286 + 287 + #ifdef __cplusplus 288 + } 289 + #endif 290 + 291 + #endif // TREE_SITTER_ARRAY_H_
+286
editor/tree-sitter-snapshot/src/tree_sitter/parser.h
··· 1 + #ifndef TREE_SITTER_PARSER_H_ 2 + #define TREE_SITTER_PARSER_H_ 3 + 4 + #ifdef __cplusplus 5 + extern "C" { 6 + #endif 7 + 8 + #include <stdbool.h> 9 + #include <stdint.h> 10 + #include <stdlib.h> 11 + 12 + #define ts_builtin_sym_error ((TSSymbol)-1) 13 + #define ts_builtin_sym_end 0 14 + #define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024 15 + 16 + #ifndef TREE_SITTER_API_H_ 17 + typedef uint16_t TSStateId; 18 + typedef uint16_t TSSymbol; 19 + typedef uint16_t TSFieldId; 20 + typedef struct TSLanguage TSLanguage; 21 + typedef struct TSLanguageMetadata { 22 + uint8_t major_version; 23 + uint8_t minor_version; 24 + uint8_t patch_version; 25 + } TSLanguageMetadata; 26 + #endif 27 + 28 + typedef struct { 29 + TSFieldId field_id; 30 + uint8_t child_index; 31 + bool inherited; 32 + } TSFieldMapEntry; 33 + 34 + // Used to index the field and supertype maps. 35 + typedef struct { 36 + uint16_t index; 37 + uint16_t length; 38 + } TSMapSlice; 39 + 40 + typedef struct { 41 + bool visible; 42 + bool named; 43 + bool supertype; 44 + } TSSymbolMetadata; 45 + 46 + typedef struct TSLexer TSLexer; 47 + 48 + struct TSLexer { 49 + int32_t lookahead; 50 + TSSymbol result_symbol; 51 + void (*advance)(TSLexer *, bool); 52 + void (*mark_end)(TSLexer *); 53 + uint32_t (*get_column)(TSLexer *); 54 + bool (*is_at_included_range_start)(const TSLexer *); 55 + bool (*eof)(const TSLexer *); 56 + void (*log)(const TSLexer *, const char *, ...); 57 + }; 58 + 59 + typedef enum { 60 + TSParseActionTypeShift, 61 + TSParseActionTypeReduce, 62 + TSParseActionTypeAccept, 63 + TSParseActionTypeRecover, 64 + } TSParseActionType; 65 + 66 + typedef union { 67 + struct { 68 + uint8_t type; 69 + TSStateId state; 70 + bool extra; 71 + bool repetition; 72 + } shift; 73 + struct { 74 + uint8_t type; 75 + uint8_t child_count; 76 + TSSymbol symbol; 77 + int16_t dynamic_precedence; 78 + uint16_t production_id; 79 + } reduce; 80 + uint8_t type; 81 + } TSParseAction; 82 + 83 + typedef struct { 84 + uint16_t lex_state; 85 + uint16_t external_lex_state; 86 + } TSLexMode; 87 + 88 + typedef struct { 89 + uint16_t lex_state; 90 + uint16_t external_lex_state; 91 + uint16_t reserved_word_set_id; 92 + } TSLexerMode; 93 + 94 + typedef union { 95 + TSParseAction action; 96 + struct { 97 + uint8_t count; 98 + bool reusable; 99 + } entry; 100 + } TSParseActionEntry; 101 + 102 + typedef struct { 103 + int32_t start; 104 + int32_t end; 105 + } TSCharacterRange; 106 + 107 + struct TSLanguage { 108 + uint32_t abi_version; 109 + uint32_t symbol_count; 110 + uint32_t alias_count; 111 + uint32_t token_count; 112 + uint32_t external_token_count; 113 + uint32_t state_count; 114 + uint32_t large_state_count; 115 + uint32_t production_id_count; 116 + uint32_t field_count; 117 + uint16_t max_alias_sequence_length; 118 + const uint16_t *parse_table; 119 + const uint16_t *small_parse_table; 120 + const uint32_t *small_parse_table_map; 121 + const TSParseActionEntry *parse_actions; 122 + const char * const *symbol_names; 123 + const char * const *field_names; 124 + const TSMapSlice *field_map_slices; 125 + const TSFieldMapEntry *field_map_entries; 126 + const TSSymbolMetadata *symbol_metadata; 127 + const TSSymbol *public_symbol_map; 128 + const uint16_t *alias_map; 129 + const TSSymbol *alias_sequences; 130 + const TSLexerMode *lex_modes; 131 + bool (*lex_fn)(TSLexer *, TSStateId); 132 + bool (*keyword_lex_fn)(TSLexer *, TSStateId); 133 + TSSymbol keyword_capture_token; 134 + struct { 135 + const bool *states; 136 + const TSSymbol *symbol_map; 137 + void *(*create)(void); 138 + void (*destroy)(void *); 139 + bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); 140 + unsigned (*serialize)(void *, char *); 141 + void (*deserialize)(void *, const char *, unsigned); 142 + } external_scanner; 143 + const TSStateId *primary_state_ids; 144 + const char *name; 145 + const TSSymbol *reserved_words; 146 + uint16_t max_reserved_word_set_size; 147 + uint32_t supertype_count; 148 + const TSSymbol *supertype_symbols; 149 + const TSMapSlice *supertype_map_slices; 150 + const TSSymbol *supertype_map_entries; 151 + TSLanguageMetadata metadata; 152 + }; 153 + 154 + static inline bool set_contains(const TSCharacterRange *ranges, uint32_t len, int32_t lookahead) { 155 + uint32_t index = 0; 156 + uint32_t size = len - index; 157 + while (size > 1) { 158 + uint32_t half_size = size / 2; 159 + uint32_t mid_index = index + half_size; 160 + const TSCharacterRange *range = &ranges[mid_index]; 161 + if (lookahead >= range->start && lookahead <= range->end) { 162 + return true; 163 + } else if (lookahead > range->end) { 164 + index = mid_index; 165 + } 166 + size -= half_size; 167 + } 168 + const TSCharacterRange *range = &ranges[index]; 169 + return (lookahead >= range->start && lookahead <= range->end); 170 + } 171 + 172 + /* 173 + * Lexer Macros 174 + */ 175 + 176 + #ifdef _MSC_VER 177 + #define UNUSED __pragma(warning(suppress : 4101)) 178 + #else 179 + #define UNUSED __attribute__((unused)) 180 + #endif 181 + 182 + #define START_LEXER() \ 183 + bool result = false; \ 184 + bool skip = false; \ 185 + UNUSED \ 186 + bool eof = false; \ 187 + int32_t lookahead; \ 188 + goto start; \ 189 + next_state: \ 190 + lexer->advance(lexer, skip); \ 191 + start: \ 192 + skip = false; \ 193 + lookahead = lexer->lookahead; 194 + 195 + #define ADVANCE(state_value) \ 196 + { \ 197 + state = state_value; \ 198 + goto next_state; \ 199 + } 200 + 201 + #define ADVANCE_MAP(...) \ 202 + { \ 203 + static const uint16_t map[] = { __VA_ARGS__ }; \ 204 + for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ 205 + if (map[i] == lookahead) { \ 206 + state = map[i + 1]; \ 207 + goto next_state; \ 208 + } \ 209 + } \ 210 + } 211 + 212 + #define SKIP(state_value) \ 213 + { \ 214 + skip = true; \ 215 + state = state_value; \ 216 + goto next_state; \ 217 + } 218 + 219 + #define ACCEPT_TOKEN(symbol_value) \ 220 + result = true; \ 221 + lexer->result_symbol = symbol_value; \ 222 + lexer->mark_end(lexer); 223 + 224 + #define END_STATE() return result; 225 + 226 + /* 227 + * Parse Table Macros 228 + */ 229 + 230 + #define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) 231 + 232 + #define STATE(id) id 233 + 234 + #define ACTIONS(id) id 235 + 236 + #define SHIFT(state_value) \ 237 + {{ \ 238 + .shift = { \ 239 + .type = TSParseActionTypeShift, \ 240 + .state = (state_value) \ 241 + } \ 242 + }} 243 + 244 + #define SHIFT_REPEAT(state_value) \ 245 + {{ \ 246 + .shift = { \ 247 + .type = TSParseActionTypeShift, \ 248 + .state = (state_value), \ 249 + .repetition = true \ 250 + } \ 251 + }} 252 + 253 + #define SHIFT_EXTRA() \ 254 + {{ \ 255 + .shift = { \ 256 + .type = TSParseActionTypeShift, \ 257 + .extra = true \ 258 + } \ 259 + }} 260 + 261 + #define REDUCE(symbol_name, children, precedence, prod_id) \ 262 + {{ \ 263 + .reduce = { \ 264 + .type = TSParseActionTypeReduce, \ 265 + .symbol = symbol_name, \ 266 + .child_count = children, \ 267 + .dynamic_precedence = precedence, \ 268 + .production_id = prod_id \ 269 + }, \ 270 + }} 271 + 272 + #define RECOVER() \ 273 + {{ \ 274 + .type = TSParseActionTypeRecover \ 275 + }} 276 + 277 + #define ACCEPT_INPUT() \ 278 + {{ \ 279 + .type = TSParseActionTypeAccept \ 280 + }} 281 + 282 + #ifdef __cplusplus 283 + } 284 + #endif 285 + 286 + #endif // TREE_SITTER_PARSER_H_
+92
editor/tree-sitter-snapshot/test/corpus/basic.txt
··· 1 + ================== 2 + Snapshot with single field 3 + ================== 4 + --- 5 + title: Test 6 + --- 7 + body content 8 + 9 + --- 10 + 11 + (source_file 12 + (front_matter 13 + (delimiter) 14 + (field 15 + (field_name) 16 + (field_value)) 17 + (delimiter)) 18 + (body)) 19 + 20 + ================== 21 + Snapshot with multiple fields 22 + ================== 23 + --- 24 + title: Test Snapshot 25 + test_name: TestExample 26 + file_name: example_test.go 27 + version: 0.1.0 28 + --- 29 + {"key": "value"} 30 + 31 + --- 32 + 33 + (source_file 34 + (front_matter 35 + (delimiter) 36 + (field 37 + (field_name) 38 + (field_value)) 39 + (field 40 + (field_name) 41 + (field_value)) 42 + (field 43 + (field_name) 44 + (field_value)) 45 + (field 46 + (field_name) 47 + (field_value)) 48 + (delimiter)) 49 + (body)) 50 + 51 + ================== 52 + Empty field value 53 + ================== 54 + --- 55 + title: 56 + test_name: TestEmpty 57 + --- 58 + content 59 + 60 + --- 61 + 62 + (source_file 63 + (front_matter 64 + (delimiter) 65 + (field 66 + (field_name)) 67 + (field 68 + (field_name) 69 + (field_value)) 70 + (delimiter)) 71 + (body)) 72 + 73 + ================== 74 + Multiline body 75 + ================== 76 + --- 77 + title: Multiline 78 + --- 79 + line one 80 + line two 81 + line three 82 + 83 + --- 84 + 85 + (source_file 86 + (front_matter 87 + (delimiter) 88 + (field 89 + (field_name) 90 + (field_value)) 91 + (delimiter)) 92 + (body))
editors/.editorconfig editor/tree-sitter-snapshot/.editorconfig
editors/.gitattributes editor/tree-sitter-snapshot/.gitattributes
editors/.gitignore editor/tree-sitter-snapshot/.gitignore
editors/CMakeLists.txt editor/tree-sitter-snapshot/CMakeLists.txt
editors/Cargo.toml editor/tree-sitter-snapshot/Cargo.toml
editors/Makefile editor/tree-sitter-snapshot/Makefile
editors/Package.swift editor/tree-sitter-snapshot/Package.swift
editors/binding.gyp editor/tree-sitter-snapshot/binding.gyp
editors/bindings/c/tree-sitter-snapshot.pc.in editor/tree-sitter-snapshot/bindings/c/tree-sitter-snapshot.pc.in
editors/bindings/c/tree_sitter/tree-sitter-snapshot.h editor/tree-sitter-snapshot/bindings/c/tree_sitter/tree-sitter-snapshot.h
editors/bindings/go/binding.go editor/tree-sitter-snapshot/bindings/go/binding.go
editors/bindings/go/binding_test.go editor/tree-sitter-snapshot/bindings/go/binding_test.go
editors/bindings/node/binding.cc editor/tree-sitter-snapshot/bindings/node/binding.cc
editors/bindings/node/binding_test.js editor/tree-sitter-snapshot/bindings/node/binding_test.js
editors/bindings/node/index.d.ts editor/tree-sitter-snapshot/bindings/node/index.d.ts
editors/bindings/node/index.js editor/tree-sitter-snapshot/bindings/node/index.js
editors/bindings/python/tests/test_binding.py editor/tree-sitter-snapshot/bindings/python/tests/test_binding.py
editors/bindings/python/tree_sitter_snapshot/__init__.py editor/tree-sitter-snapshot/bindings/python/tree_sitter_snapshot/__init__.py
editors/bindings/python/tree_sitter_snapshot/__init__.pyi editor/tree-sitter-snapshot/bindings/python/tree_sitter_snapshot/__init__.pyi
editors/bindings/python/tree_sitter_snapshot/binding.c editor/tree-sitter-snapshot/bindings/python/tree_sitter_snapshot/binding.c
editors/bindings/python/tree_sitter_snapshot/py.typed editor/tree-sitter-snapshot/bindings/python/tree_sitter_snapshot/py.typed
editors/bindings/rust/build.rs editor/tree-sitter-snapshot/bindings/rust/build.rs
editors/bindings/rust/lib.rs editor/tree-sitter-snapshot/bindings/rust/lib.rs
editors/bindings/swift/TreeSitterSnapshot/snapshot.h editor/tree-sitter-snapshot/bindings/swift/TreeSitterSnapshot/snapshot.h
editors/bindings/swift/TreeSitterSnapshotTests/TreeSitterSnapshotTests.swift editor/tree-sitter-snapshot/bindings/swift/TreeSitterSnapshotTests/TreeSitterSnapshotTests.swift
editors/go.mod editor/tree-sitter-snapshot/go.mod
-17
editors/grammar.js
··· 1 - /** 2 - * @file Snapshot test files generated by Shutter 3 - * @author ptdewey 4 - * @license MIT 5 - */ 6 - 7 - /// <reference types="tree-sitter-cli/dsl" /> 8 - // @ts-check 9 - 10 - module.exports = grammar({ 11 - name: "snapshot", 12 - 13 - rules: { 14 - // TODO: add the actual grammar rules 15 - source_file: $ => "hello" 16 - } 17 - });
editors/package.json editor/tree-sitter-snapshot/package.json
editors/pyproject.toml editor/tree-sitter-snapshot/pyproject.toml
editors/setup.py editor/tree-sitter-snapshot/setup.py
+1 -1
editors/tree-sitter.json editor/tree-sitter-snapshot/tree-sitter.json
··· 7 7 "title": "Snapshot", 8 8 "scope": "source.snapshot", 9 9 "file-types": [ 10 - "snapshot" 10 + "snap" 11 11 ], 12 12 "injection-regex": "^snapshot$", 13 13 "class-name": "TreeSitterSnapshot"
+4
internal/files/files.go
··· 164 164 fileName := getSnapshotFileName(snap.Title, state) 165 165 filePath := filepath.Join(snapshotDir, fileName) 166 166 167 + if err := os.MkdirAll(filepath.Dir(filePath), 0755); err != nil { 168 + return err 169 + } 170 + 167 171 return os.WriteFile(filePath, []byte(snap.Serialize()), 0644) 168 172 } 169 173