-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path4coder_clang_format.cpp
More file actions
156 lines (138 loc) · 5.57 KB
/
4coder_clang_format.cpp
File metadata and controls
156 lines (138 loc) · 5.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
CUSTOM_ID(attachment, clang_format_task);
function i64
clang_format_parse_cursor_string(String_Const_u8 json_str)
{
json_str = string_skip(json_str, string_find_first(json_str, 0, ':') + 1);
json_str = string_skip_whitespace(json_str);
json_str = string_prefix(json_str, string_find_first(json_str, 0, ','));
json_str = string_chop_whitespace(json_str);
i64 new_cursor = string_to_integer(json_str, 10);
return new_cursor;
}
function void
clang_format_buffer__inner(Application_Links* app, Buffer_ID buffer, b32 is_async)
{
Scratch_Block file_scratch(app);
String_Const_u8 file_path = push_buffer_file_name(app, file_scratch, buffer);
String_Const_u8 parent_dir = string_remove_last_folder(file_path);
String_Const_u8 file_name = string_skip(file_path, parent_dir.size);
String_Const_u8 tmp_file_path = push_stringf(file_scratch, "%.*s._tmp_clang.fmt%.*s", string_expand(parent_dir), string_expand(file_name));
View_ID view = 0;
i64 cursor_pos = 0;
// NOTE(fakhri): check if the buffer is attached to any view
{
for (View_ID view_it = get_view_next(app, 0, Access_Always);
view_it != 0;
view_it = get_view_next(app, view_it, Access_Always)) {
Buffer_ID view_buffer = view_get_buffer(app, view_it, Access_ReadWriteVisible);
if (view_buffer == buffer) {
view = view_it;
cursor_pos = view_get_cursor_pos(app, view);
break;
}
}
}
if (is_async)
acquire_global_frame_mutex(app);
Scratch_Block scratch(app);
String_Const_u8 old_buffer_contents = push_whole_buffer(app, scratch, buffer);
if (is_async)
release_global_frame_mutex(app);
system_save_file(scratch, (char*)tmp_file_path.str, old_buffer_contents);
String_Const_u8 cmd = push_stringf(scratch, "clang-format --cursor=%lld %.*s", cursor_pos, string_expand(tmp_file_path));
String_Const_u8 path_n = push_string_copy(scratch, parent_dir);
String_Const_u8 cmd_n = push_string_copy(scratch, cmd);
CLI_Handles cli_handles = {};
if (system_cli_call(scratch, (char*)path_n.str, (char*)cmd_n.str, &cli_handles)) {
List_String_Const_u8 list = {};
u32 tmp_buffer_capacity = KB(128);
char* tmp_buffer = push_array(scratch, char, tmp_buffer_capacity);
for (;;) {
system_cli_begin_update(&cli_handles);
u32 amount = 0;
if (system_cli_update_step(&cli_handles, tmp_buffer, tmp_buffer_capacity, &amount)) {
string_list_push(scratch, &list, push_string_copy(scratch, SCu8(tmp_buffer, amount)));
}
if (system_cli_end_update(&cli_handles)) {
break;
}
}
if (is_async)
acquire_global_frame_mutex(app);
String_Const_u8 new_content = string_list_flatten(scratch, list, StringFill_NoTerminate);
if (new_content.size) {
if (!cli_handles.exit) {
i64 eol_pos = string_find_first(new_content, 0, '\n');
String_Const_u8 cursor_new_pos_string = string_prefix(new_content, eol_pos);
new_content = string_skip(new_content, eol_pos + 1);
Range_i64 range = buffer_range(app, buffer);
History_Group group = history_group_begin(app, buffer);
buffer_replace_range(app, buffer, range, new_content);
history_group_end(group);
if (view) {
i64 new_cursor_pos = clang_format_parse_cursor_string(cursor_new_pos_string);
view_set_cursor(app, view, seek_pos(new_cursor_pos));
}
} else {
// NOTE(fakhri): error
printf_message(app, scratch, "clang-format error: %.*s", string_expand(new_content));
}
}
if (is_async)
release_global_frame_mutex(app);
}
delete_file_base(app, tmp_file_path, 0);
}
function void
clang_format_buffer_async__inner(Async_Context* actx, String_Const_u8 data)
{
if (data.size == sizeof(Buffer_ID)) {
Buffer_ID buffer = *(Buffer_ID*)data.str;
clang_format_buffer__inner(actx->app, buffer, true);
}
}
function void
clang_format_buffer_async(Application_Links* app, Buffer_ID buffer)
{
Managed_Scope scope = buffer_get_managed_scope(app, buffer);
Async_Task* clang_format_task_ptr = scope_attachment(app, scope, clang_format_task, Async_Task);
*clang_format_task_ptr = async_task_no_dep(&global_async_system, clang_format_buffer_async__inner, make_data_struct(&buffer));
}
CUSTOM_COMMAND_SIG(clang_format_current_buffer)
CUSTOM_DOC("Formats the current buffer using clang-format")
{
View_ID view = get_active_view(app, Access_ReadWriteVisible);
Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible);
if (buffer)
clang_format_buffer_async(app, buffer);
}
CUSTOM_COMMAND_SIG(clang_format_dirty_buffers)
CUSTOM_DOC("Formats all dirty buffers using clang-format")
{
for (Buffer_ID buffer_it = get_buffer_next(app, 0, Access_ReadWriteVisible);
buffer_it != 0;
buffer_it = get_buffer_next(app, buffer_it, Access_ReadWriteVisible)) {
Dirty_State dirty = buffer_get_dirty_state(app, buffer_it);
if (dirty == DirtyState_UnsavedChanges) {
clang_format_buffer_async(app, buffer_it);
}
}
}
CUSTOM_COMMAND_SIG(clang_format_all_buffers)
CUSTOM_DOC("Formats all the buffers using clang-format")
{
for (Buffer_ID buffer_it = get_buffer_next(app, 0, Access_ReadWriteVisible);
buffer_it != 0;
buffer_it = get_buffer_next(app, buffer_it, Access_ReadWriteVisible)) {
clang_format_buffer_async(app, buffer_it);
}
}
BUFFER_HOOK_SIG(clang_file_save)
{
default_file_save(app, buffer_id);
b32 auto_format_with_clang_on_save = def_get_config_b32(vars_save_string_lit("auto_format_with_clang_on_save"));
if (auto_format_with_clang_on_save) {
clang_format_buffer__inner(app, buffer_id, false);
}
return 0;
}