@@ -392,9 +392,6 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
392
392
FUNC_API_SINCE(9)
393
393
{
394
394
int64_t autocmd_id = -1;
395
-
396
-
const char_u pattern_buflocal[BUFLOCAL_PAT_LEN];
397
-
int au_group = AUGROUP_DEFAULT;
398
395
char *desc = NULL;
399
396
400
397
Array patterns = ARRAY_DICT_INIT;
@@ -404,7 +401,7 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
404
401
Callback cb = CALLBACK_NONE;
405
402
406
403
407
-
if (!unpack_string_or_array(&event_array, &event, "event", err)) {
404
+
if (!unpack_string_or_array(&event_array, &event, "event", true, err)) {
408
405
goto cleanup;
409
406
}
410
407
@@ -466,84 +463,13 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
466
463
bool is_once = api_object_to_bool(opts->once, "once", false, err);
467
464
bool is_nested = api_object_to_bool(opts->nested, "nested", false, err);
468
465
469
-
switch (opts->group.type) {
470
-
case kObjectTypeNil:
471
-
break;
472
-
case kObjectTypeString:
473
-
au_group = augroup_find(opts->group.data.string.data);
474
-
if (au_group == AUGROUP_ERROR) {
475
-
api_set_error(err,
476
-
kErrorTypeValidation,
477
-
"invalid augroup: %s", opts->group.data.string.data);
478
-
goto cleanup;
479
-
}
480
-
break;
481
-
case kObjectTypeInteger:
482
-
au_group = (int)opts->group.data.integer;
483
-
char *name = augroup_name(au_group);
484
-
if (!augroup_exists(name)) {
485
-
api_set_error(err, kErrorTypeValidation, "invalid augroup: %d", au_group);
486
-
goto cleanup;
487
-
}
488
-
break;
489
-
default:
490
-
api_set_error(err, kErrorTypeValidation, "'group' must be a string or an integer.");
466
+
int au_group = get_augroup_from_object(opts->group, err);
467
+
if (au_group == AUGROUP_ERROR) {
491
468
goto cleanup;
492
469
}
493
470
494
-
if (opts->pattern.type != kObjectTypeNil && opts->buffer.type != kObjectTypeNil) {
495
-
api_set_error(err, kErrorTypeValidation,
496
-
"cannot pass both: 'pattern' and 'buffer' for the same autocmd");
471
+
if (!get_patterns_from_pattern_or_buf(&patterns, opts->pattern, opts->buffer, err)) {
497
472
goto cleanup;
498
-
} else if (opts->pattern.type != kObjectTypeNil) {
499
-
Object *v = &opts->pattern;
500
-
501
-
if (v->type == kObjectTypeString) {
502
-
char_u *pat = (char_u *)v->data.string.data;
503
-
size_t patlen = aucmd_pattern_length(pat);
504
-
while (patlen) {
505
-
ADD(patterns, STRING_OBJ(cbuf_to_string((char *)pat, patlen)));
506
-
507
-
pat = aucmd_next_pattern(pat, patlen);
508
-
patlen = aucmd_pattern_length(pat);
509
-
}
510
-
} else if (v->type == kObjectTypeArray) {
511
-
if (!check_autocmd_string_array(patterns, "pattern", err)) {
512
-
goto cleanup;
513
-
}
514
-
515
-
Array array = v->data.array;
516
-
for (size_t i = 0; i < array.size; i++) {
517
-
char_u *pat = (char_u *)array.items[i].data.string.data;
518
-
size_t patlen = aucmd_pattern_length(pat);
519
-
while (patlen) {
520
-
ADD(patterns, STRING_OBJ(cbuf_to_string((char *)pat, patlen)));
521
-
522
-
pat = aucmd_next_pattern(pat, patlen);
523
-
patlen = aucmd_pattern_length(pat);
524
-
}
525
-
}
526
-
} else {
527
-
api_set_error(err,
528
-
kErrorTypeValidation,
529
-
"'pattern' must be a string");
530
-
goto cleanup;
531
-
}
532
-
} else if (opts->buffer.type != kObjectTypeNil) {
533
-
if (opts->buffer.type != kObjectTypeInteger) {
534
-
api_set_error(err,
535
-
kErrorTypeValidation,
536
-
"'buffer' must be an integer");
537
-
goto cleanup;
538
-
}
539
-
540
-
buf_T *buf = find_buffer_by_handle((Buffer)opts->buffer.data.integer, err);
541
-
if (ERROR_SET(err)) {
542
-
goto cleanup;
543
-
}
544
-
545
-
snprintf((char *)pattern_buflocal, BUFLOCAL_PAT_LEN, "<buffer=%d>", (int)buf->handle);
546
-
ADD(patterns, STRING_OBJ(cstr_to_string((char *)pattern_buflocal)));
547
473
}
548
474
549
475
if (opts->desc.type != kObjectTypeNil) {
@@ -615,6 +541,94 @@ void nvim_del_autocmd(Integer id)
615
541
autocmd_delete_id(id);
616
542
}
617
543
544
+
/// Clear all autocommands that match the corresponding {opts}. To delete
545
+
/// a particular autocmd, see |nvim_del_autocmd|.
546
+
/// @param opts Parameters
547
+
/// - event: (string|table)
548
+
/// Examples:
549
+
/// - event: "pat1"
550
+
/// - event: { "pat1" }
551
+
/// - event: { "pat1", "pat2", "pat3" }
552
+
/// - pattern: (string|table)
553
+
/// - pattern or patterns to match exactly.
554
+
/// - For example, if you have `*.py` as that pattern for the autocmd,
555
+
/// you must pass `*.py` exactly to clear it. `test.py` will not
556
+
/// match the pattern.
557
+
/// - defaults to clearing all patterns.
558
+
/// - NOTE: Cannot be used with {buffer}
559
+
/// - buffer: (bufnr)
560
+
/// - clear only |autocmd-buflocal| autocommands.
561
+
/// - NOTE: Cannot be used with {pattern}
562
+
/// - group: (string|int) The augroup name or id.
563
+
/// - NOTE: If not passed, will only delete autocmds *not* in any group.
564
+
///
565
+
void nvim_clear_autocmd(Dict(clear_autocmd) *opts, Error *err)
566
+
FUNC_API_SINCE(9)
567
+
{
568
+
// TODO(tjdevries): Future improvements:
569
+
// - once: (boolean) - Only clear autocmds with once. See |autocmd-once|
570
+
// - nested: (boolean) - Only clear autocmds with nested. See |autocmd-nested|
571
+
// - group: Allow passing "*" or true or something like that to force doing all
572
+
// autocmds, regardless of their group.
573
+
574
+
Array patterns = ARRAY_DICT_INIT;
575
+
Array event_array = ARRAY_DICT_INIT;
576
+
577
+
if (!unpack_string_or_array(&event_array, &opts->event, "event", false, err)) {
578
+
goto cleanup;
579
+
}
580
+
581
+
if (opts->pattern.type != kObjectTypeNil && opts->buffer.type != kObjectTypeNil) {
582
+
api_set_error(err, kErrorTypeValidation,
583
+
"Cannot use both 'pattern' and 'buffer'");
584
+
goto cleanup;
585
+
}
586
+
587
+
int au_group = get_augroup_from_object(opts->group, err);
588
+
if (au_group == AUGROUP_ERROR) {
589
+
goto cleanup;
590
+
}
591
+
592
+
if (!get_patterns_from_pattern_or_buf(&patterns, opts->pattern, opts->buffer, err)) {
593
+
goto cleanup;
594
+
}
595
+
596
+
// When we create the autocmds, we want to say that they are all matched, so that's *
597
+
// but when we clear them, we want to say that we didn't pass a pattern, so that's NUL
598
+
if (patterns.size == 0) {
599
+
ADD(patterns, STRING_OBJ(STATIC_CSTR_TO_STRING("")));
600
+
}
601
+
602
+
// If we didn't pass any events, that means clear all events.
603
+
if (event_array.size == 0) {
604
+
FOR_ALL_AUEVENTS(event) {
605
+
FOREACH_ITEM(patterns, pat_object, {
606
+
char_u *pat = (char_u *)pat_object.data.string.data;
607
+
if (!clear_autocmd(event, pat, au_group, err)) {
608
+
goto cleanup;
609
+
}
610
+
});
611
+
}
612
+
} else {
613
+
FOREACH_ITEM(event_array, event_str, {
614
+
GET_ONE_EVENT(event_nr, event_str, cleanup);
615
+
616
+
FOREACH_ITEM(patterns, pat_object, {
617
+
char_u *pat = (char_u *)pat_object.data.string.data;
618
+
if (!clear_autocmd(event_nr, pat, au_group, err)) {
619
+
goto cleanup;
620
+
}
621
+
});
622
+
});
623
+
}
624
+
625
+
cleanup:
626
+
api_free_array(event_array);
627
+
api_free_array(patterns);
628
+
629
+
return;
630
+
}
631
+
618
632
/// Create or get an autocommand group |autocmd-groups|.
619
633
///
620
634
/// To get an existing group id, do:
@@ -709,7 +723,7 @@ void nvim_exec_autocmd(Object event, Dict(exec_autocmd) *opts, Error *err)
709
723
710
724
Array event_array = ARRAY_DICT_INIT;
711
725
712
-
if (!unpack_string_or_array(&event_array, &event, "event", err)) {
726
+
if (!unpack_string_or_array(&event_array, &event, "event", true, err)) {
713
727
goto cleanup;
714
728
}
715
729
@@ -808,7 +822,7 @@ static bool check_autocmd_string_array(Array arr, char *k, Error *err)
808
822
return true;
809
823
}
810
824
811
-
static bool unpack_string_or_array(Array *array, Object *v, char *k, Error *err)
825
+
static bool unpack_string_or_array(Array *array, Object *v, char *k, bool required, Error *err)
812
826
{
813
827
if (v->type == kObjectTypeString) {
814
828
ADD(*array, copy_object(*v));
@@ -818,10 +832,119 @@ static bool unpack_string_or_array(Array *array, Object *v, char *k, Error *err)
818
832
}
819
833
*array = copy_array(v->data.array);
820
834
} else {
821
-
api_set_error(err,
822
-
kErrorTypeValidation,
823
-
"'%s' must be an array or a string.",
824
-
k);
835
+
if (required) {
836
+
api_set_error(err,
837
+
kErrorTypeValidation,
838
+
"'%s' must be an array or a string.",
839
+
k);
840
+
return false;
841
+
}
842
+
}
843
+
844
+
return true;
845
+
}
846
+
847
+
// Returns AUGROUP_ERROR if there was a problem with {group}
848
+
static int get_augroup_from_object(Object group, Error *err)
849
+
{
850
+
int au_group = AUGROUP_ERROR;
851
+
852
+
switch (group.type) {
853
+
case kObjectTypeNil:
854
+
return AUGROUP_DEFAULT;
855
+
case kObjectTypeString:
856
+
au_group = augroup_find(group.data.string.data);
857
+
if (au_group == AUGROUP_ERROR) {
858
+
api_set_error(err,
859
+
kErrorTypeValidation,
860
+
"invalid augroup: %s", group.data.string.data);
861
+
862
+
return AUGROUP_ERROR;
863
+
}
864
+
865
+
return au_group;
866
+
case kObjectTypeInteger:
867
+
au_group = (int)group.data.integer;
868
+
char *name = augroup_name(au_group);
869
+
if (!augroup_exists(name)) {
870
+
api_set_error(err, kErrorTypeValidation, "invalid augroup: %d", au_group);
871
+
return AUGROUP_ERROR;
872
+
}
873
+
874
+
return au_group;
875
+
default:
876
+
api_set_error(err, kErrorTypeValidation, "'group' must be a string or an integer.");
877
+
return AUGROUP_ERROR;
878
+
}
879
+
}
880
+
881
+
static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, Object buffer,
882
+
Error *err)
883
+
{
884
+
const char_u pattern_buflocal[BUFLOCAL_PAT_LEN];
885
+
886
+
if (pattern.type != kObjectTypeNil && buffer.type != kObjectTypeNil) {
887
+
api_set_error(err, kErrorTypeValidation,
888
+
"cannot pass both: 'pattern' and 'buffer' for the same autocmd");
889
+
return false;
890
+
} else if (pattern.type != kObjectTypeNil) {
891
+
Object *v = &pattern;
892
+
893
+
if (v->type == kObjectTypeString) {
894
+
char_u *pat = (char_u *)v->data.string.data;
895
+
size_t patlen = aucmd_pattern_length(pat);
896
+
while (patlen) {
897
+
ADD(*patterns, STRING_OBJ(cbuf_to_string((char *)pat, patlen)));
898
+
899
+
pat = aucmd_next_pattern(pat, patlen);
900
+
patlen = aucmd_pattern_length(pat);
901
+
}
902
+
} else if (v->type == kObjectTypeArray) {
903
+
if (!check_autocmd_string_array(*patterns, "pattern", err)) {
904
+
return false;
905
+
}
906
+
907
+
Array array = v->data.array;
908
+
for (size_t i = 0; i < array.size; i++) {
909
+
char_u *pat = (char_u *)array.items[i].data.string.data;
910
+
size_t patlen = aucmd_pattern_length(pat);
911
+
while (patlen) {
912
+
ADD(*patterns, STRING_OBJ(cbuf_to_string((char *)pat, patlen)));
913
+
914
+
pat = aucmd_next_pattern(pat, patlen);
915
+
patlen = aucmd_pattern_length(pat);
916
+
}
917
+
}
918
+
} else {
919
+
api_set_error(err,
920
+
kErrorTypeValidation,
921
+
"'pattern' must be a string");
922
+
return false;
923
+
}
924
+
} else if (buffer.type != kObjectTypeNil) {
925
+
if (buffer.type != kObjectTypeInteger) {
926
+
api_set_error(err,
927
+
kErrorTypeValidation,
928
+
"'buffer' must be an integer");
929
+
return false;
930
+
}
931
+
932
+
buf_T *buf = find_buffer_by_handle((Buffer)buffer.data.integer, err);
933
+
if (ERROR_SET(err)) {
934
+
return false;
935
+
}
936
+
937
+
snprintf((char *)pattern_buflocal, BUFLOCAL_PAT_LEN, "<buffer=%d>", (int)buf->handle);
938
+
ADD(*patterns, STRING_OBJ(cstr_to_string((char *)pattern_buflocal)));
939
+
}
940
+
941
+
return true;
942
+
}
943
+
944
+
static bool clear_autocmd(event_T event, char_u *pat, int au_group, Error *err)
945
+
{
946
+
if (do_autocmd_event(event, pat, false, false, (char_u *)"", true, au_group) == FAIL) {
947
+
api_set_error(err, kErrorTypeException, "Failed to clear autocmd");
825
948
return false;
826
949
}
827
950
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4