Skip to content

Commit 77dd769

Browse files
committed
Add cpo and ranges snippets
1 parent 3d7a978 commit 77dd769

File tree

9 files changed

+310
-33
lines changed

9 files changed

+310
-33
lines changed

README.md

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,19 @@ Snippets which trigger ends with "!" are `autosnippet`.
3535

3636
#### Normal Snippets
3737

38-
| Trig | Desc | Context |
39-
|:-------:|--------------------------------------------------------------------------------------------------|:--------:|
40-
| `ctor!` | Expand to default constructor | In Class |
41-
| `dtor!` | Expand to default destructor | In Class |
42-
| `cc!` | Expand to default copy constructor | In Class |
43-
| `mv!` | Expand to default move constructor | In Class |
44-
| `ncc!` | Expand to delete copy constructor | In Class |
45-
| `nmv!` | Expand to delete move constructor | In Class |
46-
| `ncm!` | Expand to delete copy and move constructor | In Class |
47-
| `fn` | Expand to lambda function in argument list or function body, otherwise expand to normal function | All |
38+
| Trig | Desc | Context Required |
39+
| :--------: | ------------------------------------------------------------------------------------------------ | :--------------: |
40+
| `ctor!` | Expand to default constructor | In Class |
41+
| `dtor!` | Expand to default destructor | In Class |
42+
| `cc!` | Expand to default copy constructor | In Class |
43+
| `mv!` | Expand to default move constructor | In Class |
44+
| `ncc!` | Expand to delete copy constructor | In Class |
45+
| `nmv!` | Expand to delete move constructor | In Class |
46+
| `ncm!` | Expand to delete copy and move constructor | In Class |
47+
| `fn` | Expand to lambda function in argument list or function body, otherwise expand to normal function | No |
48+
| `\| trans` | Expand to ranges::views::transform pipe. | No |
49+
| `\| filter` | Expand to ranges::views::filter pipe. | No |
50+
| `cpo` | Expand to customize point object. | No |
4851

4952
#### Postfix Snippets
5053

@@ -64,16 +67,17 @@ Snippets which trigger ends with "!" are `autosnippet`.
6467
] @any_expr
6568
```
6669

67-
| Trig | Desc (placehoder: `?`) | Expr before cursor |
68-
|:------:|----------------------------------------------------------------|:------------------:|
69-
| `.be` | Expand to begin and end exprs | `any_expr` |
70-
| `.mv` | Wraps with `std::move(?)` | `any_expr` |
71-
| `.fwd` | Wraps with `std::forward<decltype(?)>(?)` | `any_expr` |
72-
| `.val` | Wraps with `std::declval<?>()` | `any_expr` |
73-
| `.dt` | Wraps with `decltype(?)` | `any_expr` |
74-
| `.uu` | Wraps with `(void)?` | `any_expr` |
75-
| `.ts` | Switch indent's coding style between CamelCase and snake_case. | `indent` |
76-
| `.sc` | Wraps with `static_cast<>(?)` | `any_expr` |
70+
| Trig | Desc (placehoder: `?`) | Expr before cursor |
71+
| :-------: | ------------------------------------------------------------------ | :----------------: |
72+
| `.be` | Expand to begin and end exprs | `any_expr` |
73+
| `.mv` | Wraps with `std::move(?)` | `any_expr` |
74+
| `.fwd` | Wraps with `std::forward<decltype(?)>(?)` | `any_expr` |
75+
| `.val` | Wraps with `std::declval<?>()` | `any_expr` |
76+
| `.dt` | Wraps with `decltype(?)` | `any_expr` |
77+
| `.uu` | Wraps with `(void)?` | `any_expr` |
78+
| `.ts` | Switch indent's coding style between `CamelCase` and `snake_case`. | `indent` |
79+
| `.sc` | Wraps with `static_cast<>(?)` | `any_expr` |
80+
| `.single` | Wraps with `ranges::views::single(?)` | `any_expr` |
7781

7882
</details>
7983

@@ -95,28 +99,27 @@ Snippets which trigger ends with "!" are `autosnippet`.
9599
(call_expression)
96100
(identifier)
97101
(field_expression)
98-
102+
99103
(generic_type)
100104
(scoped_type_identifier)
101105
(reference_type)
102106
] @expr_or_type
103107
```
104108

105109
| Trig | Desc (placehoder: `?`) | Expr before cursor |
106-
|:----------:|------------------------------------------------------------|:------------------:|
107-
| `.rc` | Wraps with `Rc::new(?)` if expr, `Rc<?>` if type | `expr_or_type` |
110+
| :--------: | ---------------------------------------------------------- | :----------------: |
111+
| `.rc` | Wraps with `Rc::new(?)` if expr, `Rc<?>` if type | `expr_or_type` |
108112
| `.arc` | Wraps with `Arc::new(?)` if expr, `Arc<?>` if type | `expr_or_type` |
109113
| `.box` | Wraps with `Box::new(?)` if expr, `Box<?>` if type | `expr_or_type` |
110-
| `.mu` | Wraps with `Mutex::new(?)` if expr, `Mutex<?>` if type | `expr_or_type` |
111-
| `.rw` | Wraps with `RwLock::new(?)` if expr, `RwLock<?>` if type | `expr_or_type` |
112-
| `.cell` | Wraps with `Cell::new(?)` if expr, `Cell<?>` if type | `expr_or_type` |
114+
| `.mu` | Wraps with `Mutex::new(?)` if expr, `Mutex<?>` if type | `expr_or_type` |
115+
| `.rw` | Wraps with `RwLock::new(?)` if expr, `RwLock<?>` if type | `expr_or_type` |
116+
| `.cell` | Wraps with `Cell::new(?)` if expr, `Cell<?>` if type | `expr_or_type` |
113117
| `.refcell` | Wraps with `RefCell::new(?)` if expr, `RefCell<?>` if type | `expr_or_type` |
114118
| `.ref` | Wraps with `&?` | `expr` |
115-
| `.refm` | Wraps with `&mut ?` | `expr` |
116-
| `.ok` | Wraps with `Ok(?)` | `expr` |
119+
| `.refm` | Wraps with `&mut ?` | `expr` |
120+
| `.ok` | Wraps with `Ok(?)` | `expr` |
117121
| `.err` | Wraps with `Err(?)` | `expr` |
118-
| `.some` | Wraps with `Some(?)` | `expr` |
122+
| `.some` | Wraps with `Some(?)` | `expr` |
119123
| `.println` | Wraps with `println!("{:?}", ?)` | `expr` |
120124

121125
</details>
122-

lua/luasnip-snippets/init.lua

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
local M = {}
22

3-
-- dummy
4-
---@class LuaSnip.Snippet
5-
63
---@alias SnippetOrBuilder LuaSnip.Snippet|fun():SnippetOrBuilder
74

85
---Register snippets to luasnip.

lua/luasnip-snippets/nodes.lua

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,64 @@ local function choice_node(idx, choices, opts)
4242
return ls.choice_node(idx, choices, opts)
4343
end
4444

45+
---@alias LSSnippets.TrigMatcher fun(line_to_cursor: string, trigger: string): string, table
46+
---@alias LSSnippets.CustomTrigEngine fun(trigger: string): LSSnippets.TrigMatcher
47+
---@alias LSSnippets.TrigEngine "plain"|"pattern"|"ecma"|"vim"|LSSnippets.CustomTrigEngine
48+
49+
---@class LSSnippets.SnippetOptions
50+
---@field [1] string Trigger
51+
---@field name string? Snippet name
52+
---@field dscr string? Snippet description
53+
---@field mode string? Snippet mode, "w" for word trigger, "h" for hidden, "A" for autosnippet, "b" for line begin, "r" for regex pattern
54+
---@field engine LSSnippets.TrigEngine? Snippet trigger engine. If "r" in mode, defaults to "pattern".
55+
---@field hidden boolean? Hidden from completion, If "h" in mode, defaults to true.
56+
---@field nodes LuaSnip.Node[] Expansion nodes
57+
---@field priority number? Snippet priority
58+
---@field cond LSSnippets.ConditionObject? Condition object, including condition and show_condition
59+
---@field resolveExpandParams nil|fun(snippet: LuaSnip.Snippet, line_to_cursor: string, matched_trigger: string, captures: table): table Function to decide whether the snippet can be expanded or not.
60+
---@field opts table? Other options
61+
62+
---@param opts LSSnippets.SnippetOptions
63+
local function construct_snippet(opts)
64+
local CommonCond = require("luasnip-snippets.utils.common_cond")
65+
local ls = require("luasnip")
66+
67+
local trig = opts[1]
68+
local name = vim.F.if_nil(opts.name, trig)
69+
local dscr = vim.F.if_nil(opts.dscr, "Snippet: " .. name)
70+
local mode = vim.F.if_nil(opts.mode, "")
71+
local wordTrig = mode:match("w") ~= nil
72+
local trigEngine = vim.F.if_nil(opts.engine, "plain")
73+
if mode:match("r") ~= nil and opts.engine == nil then
74+
trigEngine = "pattern"
75+
end
76+
local hidden = vim.F.if_nil(opts.hidden, mode:match("h") ~= nil)
77+
local snippetType = mode:match("A") ~= nil and "autosnippet" or "snippet"
78+
local nodes = opts.nodes
79+
local priority = opts.priority or nil
80+
local cond = opts.cond or nil
81+
if mode:match("b") ~= nil then
82+
local line_begin = CommonCond.at_line_begin(trig)
83+
cond = cond and (cond + line_begin) or line_begin
84+
end
85+
local trig_arg = {
86+
trig = trig,
87+
name = name,
88+
dscr = dscr,
89+
wordTrig = wordTrig,
90+
trigEngine = trigEngine,
91+
hidden = hidden,
92+
priority = priority,
93+
snippetType = snippetType,
94+
condition = cond and cond.condition,
95+
show_condition = cond and cond.show_condition,
96+
resolveExpandParams = opts.resolveExpandParams,
97+
}
98+
return ls.s(trig_arg, nodes, opts.opts)
99+
end
100+
45101
return {
46102
insert_node = insert_node,
47103
choice_node = choice_node,
104+
construct_snippet = construct_snippet,
48105
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
local ls = require("luasnip")
2+
local snippet = require("luasnip-snippets.nodes").construct_snippet
3+
local i = require("luasnip-snippets.nodes").insert_node
4+
local c = require("luasnip-snippets.nodes").choice_node
5+
local fmta = require("luasnip.extras.fmt").fmta
6+
local f = ls.function_node
7+
local t = ls.text_node
8+
9+
local function cpo_snippet()
10+
local function cpo_func_to_namespace(name)
11+
-- try to convert name from pascal case to snake case
12+
if name:match("^[A-Z]") then
13+
-- is pascal case now, change to snake case
14+
name = name:gsub("(%u+)(%u%l)", "%1_%2")
15+
name = name:gsub("([a-z0-9])([A-Z])", "%1_%2")
16+
name = name:gsub("-", "_")
17+
name = name:lower()
18+
end
19+
return ("%s_fn"):format(name)
20+
end
21+
return snippet {
22+
"cpo",
23+
name = "(cpo) Customization point object",
24+
dscr = "Expands to a customization point object",
25+
mode = "bw",
26+
nodes = fmta(
27+
[[
28+
namespace <ns_name> {
29+
struct Fn {
30+
template<<typename T, bool _noexcept = true>>
31+
decltype(auto) operator()(T&& value) const noexcept(_noexcept) {
32+
<cursor>
33+
}
34+
};
35+
} // namespace <ns_name>
36+
inline constexpr <ns_name>::Fn <name>{};
37+
]],
38+
{
39+
name = i(1, "function name"),
40+
ns_name = f(function(args)
41+
return cpo_func_to_namespace(args[1][1])
42+
end, { 1 }),
43+
cursor = i(0),
44+
}
45+
),
46+
}
47+
end
48+
49+
---@param trig string
50+
---@param func string
51+
local function ranges_views_snippet(trig, func)
52+
return snippet {
53+
trig,
54+
name = ("(%s) %s"):format(trig, func:gsub("^%l", string.upper)),
55+
dscr = ("Expands to %s view"):format(func),
56+
nodes = fmta(
57+
[[
58+
| <namespace>::views::<func>([&](auto&& value) {
59+
<body>
60+
})
61+
]],
62+
{
63+
namespace = c(1, {
64+
t("ranges"),
65+
t("std"),
66+
}, { desc = "library" }),
67+
body = i(0),
68+
func = t(func),
69+
}
70+
),
71+
}
72+
end
73+
74+
return {
75+
cpo_snippet,
76+
77+
ranges_views_snippet("|trans", "transform"),
78+
ranges_views_snippet("|filter", "filter"),
79+
}

lua/luasnip-snippets/snippets/cpp/init.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ local function setup()
55
"statements",
66
"lambda_fn",
77
"postfix",
8+
"default",
89
})
910
end
1011

lua/luasnip-snippets/snippets/cpp/postfix.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ return {
6363
expr_tsp(".val", "std::declval<?>()"),
6464
expr_tsp(".dt", "decltype(?)"),
6565
expr_tsp(".uu", "(void)?"),
66+
expr_tsp(".single", "ranges::views::single(?)"),
6667

6768
tsp.treesitter_postfix({
6869
trig = ".ts",
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
local Cond = require("luasnip-snippets.utils.cond")
2+
3+
local function line_begin_cond(line_to_cursor, matched_trigger, _)
4+
if matched_trigger == nil or line_to_cursor == nil then
5+
return false
6+
end
7+
return line_to_cursor:sub(1, -(#matched_trigger + 1)):match("^%s*$")
8+
end
9+
10+
local function line_begin_show_maker(trig)
11+
local function line_begin_show(line_to_cursor)
12+
if line_to_cursor == nil then
13+
return false
14+
end
15+
local _, col = unpack(vim.api.nvim_win_get_cursor(0))
16+
local line = vim.api.nvim_get_current_line()
17+
local trigger = line:sub(1, col):match("%S+$")
18+
if #trigger > #trig then
19+
return false
20+
end
21+
return trigger == trig:sub(1, #trigger)
22+
end
23+
return line_begin_show
24+
end
25+
26+
---@param trig string
27+
---@return LSSnippets.ConditionObject
28+
local function at_line_begin(trig)
29+
return Cond.make_condition(line_begin_cond, line_begin_show_maker(trig))
30+
end
31+
32+
return {
33+
at_line_begin = at_line_begin,
34+
}

0 commit comments

Comments
 (0)