Skip to content

Commit 0f5d4ab

Browse files
committedDec 3, 2024·
feat(cpp): add C++ language support
1 parent 639e23b commit 0f5d4ab

File tree

5 files changed

+1030
-1
lines changed

5 files changed

+1030
-1
lines changed
 

Diff for: ‎lua/timber/config.lua

+42
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ local default_config = {
3333
rust = [[println!("%log_target: {:#?}", %log_target);]],
3434
python = [[print("%log_target", %log_target)]],
3535
c = [[printf("%log_target: %s\n", %log_target);]],
36+
cpp = [[std::cout << "%log_target: " << %log_target << std::endl;]],
3637
},
3738
},
3839
batch_log_templates = {
@@ -48,6 +49,7 @@ local default_config = {
4849
rust = [[println!("%repeat<%log_target: {:#?}><, >", %repeat<%log_target><, >);]],
4950
python = [[print(%repeat<"%log_target", %log_target><, >)]],
5051
c = [[printf("%repeat<%log_target: %s><, >\n", %repeat<%log_target><, >);]],
52+
cpp = [[std::cout %repeat<<< "%log_target: " << %log_target>< << "\n " > << std::endl;]],
5153
},
5254
},
5355
highlight = {
@@ -177,6 +179,46 @@ local function setup_keymaps()
177179
end, { mode = "n", expr = true, desc = "Add log targets to batch operator" })
178180
end
179181

182+
-- Test C++ logging templates
183+
function M.test_cpp_templates()
184+
local single_template = M.config.log_templates.default.cpp
185+
local batch_template = M.config.batch_log_templates.default.cpp
186+
187+
-- Test cases
188+
local test_cases = {
189+
{ input = "count", expected = [[printf("count: %s\n", count);]] },
190+
{ input = "x + y", expected = [[printf("x + y: %s\n", x + y);]] },
191+
}
192+
193+
-- Test single log template
194+
for _, case in ipairs(test_cases) do
195+
local result = single_template:gsub("%%log_target", case.input)
196+
assert(
197+
result == case.expected,
198+
string.format("Single template failed for '%s'\nExpected: %s\nGot: %s", case.input, case.expected, result)
199+
)
200+
end
201+
202+
-- Test batch template
203+
local batch_input = { "x", "y", "z" }
204+
local batch_expected = [[printf("x: %s, y: %s, z: %s\n", x, y, z);]]
205+
local batch_result = batch_template:gsub("%%repeat<(.-)><(.-)>", function(template, sep)
206+
local parts = {}
207+
for _, var in ipairs(batch_input) do
208+
local part = template:gsub("%%log_target", var)
209+
table.insert(parts, part)
210+
end
211+
return table.concat(parts, sep)
212+
end)
213+
214+
assert(
215+
batch_result == batch_expected,
216+
string.format("Batch template failed\nExpected: %s\nGot: %s", batch_expected, batch_result)
217+
)
218+
219+
return true
220+
end
221+
180222
-- This function is used during testing
181223
function M.reset_default_key_mappings()
182224
local reset_keymap = function(lhs, modes)

Diff for: ‎queries/cpp/timber-log-container.scm

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
; Variable declarations
2+
(
3+
(declaration) @log_container
4+
(#make-logable-range! @log_container "outer")
5+
)
6+
7+
; Assignment expressions
8+
(
9+
(expression_statement
10+
([
11+
(assignment_expression)
12+
(update_expression)
13+
(parameter_pack_expansion)
14+
]) @log_container
15+
)
16+
(#make-logable-range! @log_container "outer")
17+
)
18+
19+
; Function calls
20+
(
21+
(call_expression
22+
arguments: (argument_list) @log_container)
23+
(#make-logable-range! @log_container "outer")
24+
)
25+
26+
; Function declarations with parameters
27+
(
28+
(function_definition
29+
declarator: (function_declarator
30+
parameters: (parameter_list) @log_container
31+
)
32+
body: (compound_statement) @a
33+
)
34+
(#make-logable-range! @a "inner" 1 -1)
35+
)
36+
37+
; Class method declarations
38+
(
39+
(field_declaration
40+
declarator: (function_declarator
41+
parameters: (parameter_list) @log_container))
42+
)
43+
44+
; If statements
45+
(
46+
(if_statement
47+
condition: (condition_clause) @log_container
48+
consequence: (compound_statement) @a
49+
) @b
50+
(#not-has-parent? @b else_clause)
51+
(#make-logable-range! @a "inner" 1 -1)
52+
(#make-logable-range! @b "before")
53+
)
54+
55+
; If statements with single statement body
56+
(
57+
(if_statement
58+
condition: (condition_clause) @log_container
59+
consequence: (_) @a
60+
) @b
61+
(#not-match? @a "^\\{")
62+
(#make-logable-range! @b "before")
63+
)
64+
65+
; Else-If statements
66+
(
67+
(if_statement
68+
condition: (condition_clause) @log_container
69+
consequence: (compound_statement) @a
70+
) @b
71+
(#has-parent? @b else_clause)
72+
(#make-logable-range! @a "inner" 1 -1)
73+
)
74+
75+
; Traditional for loops
76+
(
77+
(for_statement
78+
initializer: (_) @log_container
79+
body: (compound_statement) @a
80+
) @b
81+
(#make-logable-range! @a "inner" 1 -1)
82+
)
83+
84+
(
85+
(for_statement
86+
condition: (_) @log_container
87+
body: (compound_statement) @a
88+
) @b
89+
(#make-logable-range! @a "inner" 1 -1)
90+
(#make-logable-range! @b "before")
91+
)
92+
93+
(
94+
(for_statement
95+
update: (_) @log_container
96+
body: (compound_statement) @a
97+
) @b
98+
(#make-logable-range! @a "inner" 1 -1)
99+
(#make-logable-range! @b "before")
100+
)
101+
102+
; While loops
103+
(
104+
(while_statement
105+
condition: (condition_clause) @log_container
106+
body: (compound_statement) @a
107+
) @b
108+
(#make-logable-range! @a "inner" 1 -1)
109+
(#make-logable-range! @b "before")
110+
)
111+
112+
; Do-while loops
113+
(
114+
(do_statement
115+
body: (compound_statement) @a
116+
condition: (parenthesized_expression) @log_container
117+
) @b
118+
(#make-logable-range! @a "inner" 1 -1)
119+
(#make-logable-range! @b "after")
120+
)
121+
122+
; Try-catch blocks
123+
(
124+
(try_statement
125+
body: (_)
126+
(catch_clause
127+
parameters: (parameter_list) @log_container
128+
body: (compound_statement) @a
129+
)
130+
)
131+
(#make-logable-range! @a "inner" 1 -1)
132+
)
133+
134+
; Lambda expressions
135+
(
136+
(lambda_expression
137+
captures: (lambda_capture_specifier) @log_container
138+
body: (compound_statement) @a
139+
) @b
140+
(#make-logable-range! @a "inner" 1 -1)
141+
(#make-logable-range! @b "before")
142+
)
143+
144+
145+
; Lambda expressions
146+
(
147+
(lambda_expression
148+
declarator: (abstract_function_declarator
149+
parameters: (parameter_list) @log_container
150+
)
151+
body: (compound_statement) @a
152+
)
153+
(#make-logable-range! @a "inner" 1 -1)
154+
)

Diff for: ‎queries/cpp/timber-log-target.scm

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
; Basic identifiers (variables) that are not part of other expressions
2+
(
3+
(identifier) @log_target
4+
(#not-has-parent? @log_target field_expression)
5+
(#not-has-parent? @log_target field_designator)
6+
(#not-has-parent? @log_target subscript_expression)
7+
(#not-field-of-parent? @log_target call_expression function)
8+
(#not-has-parent? @log_target namespace_identifier)
9+
)
10+
11+
; Field access through arrow operator (->)
12+
(field_expression
13+
argument: (identifier) @log_target
14+
)
15+
16+
; Field access through dot operator (.)
17+
(field_expression
18+
argument: (identifier) @log_target
19+
)
20+
21+
; Array subscript expressions
22+
(subscript_expression
23+
argument: (identifier) @log_target
24+
)
25+
26+
; Capture full field and subscript expressions
27+
(
28+
([
29+
(field_expression)
30+
(subscript_expression)
31+
]) @log_target
32+
(#not-field-of-ancestor? @log_target call_expression function)
33+
)
34+
35+
; C++ specific: Namespace qualified identifiers
36+
(qualified_identifier
37+
scope: (namespace_identifier)
38+
name: (identifier) @log_target
39+
)
40+
41+
; C++ specific: Template function calls
42+
(template_function
43+
name: (identifier) @log_target
44+
)
45+
46+
; C++ specific: Member function calls
47+
(call_expression
48+
function: (field_expression
49+
argument: (identifier) @log_target)
50+
)
51+
52+
; C++ specific: Container methods (like vector.size())
53+
(field_expression
54+
field: (field_identifier) @log_target
55+
(#match? @log_target "^(size|length|empty|capacity|begin|end)$")
56+
)

Diff for: ‎tests/minimal_init.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ vim.cmd("runtime plugin/plenary.vim")
1717
require("plenary.busted")
1818

1919
require("nvim-treesitter.configs").setup({
20-
ensure_installed = { "javascript", "typescript", "tsx", "lua", "ruby", "elixir", "go", "rust", "python", "c" },
20+
ensure_installed = { "javascript", "typescript", "tsx", "lua", "ruby", "elixir", "go", "rust", "python", "c", "cpp" },
2121
sync_install = true,
2222
auto_install = false,
2323
indent = { enable = true },

Diff for: ‎tests/timber/actions/lang/cpp_spec.lua

+777
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.