Mercurial > vim
comparison src/textprop.c @ 19100:91bb12995034 v8.2.0110
patch 8.2.0110: prop_find() is not implemented
Commit: https://github.com/vim/vim/commit/e05a89ac6399a8c7d164c99fdab6841d999a9128
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri Jan 10 19:56:46 2020 +0100
patch 8.2.0110: prop_find() is not implemented
Problem: prop_find() is not implemented.
Solution: Implement prop_find(). (Ryan Hackett, closes https://github.com/vim/vim/issues/5421, closes https://github.com/vim/vim/issues/4970)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Fri, 10 Jan 2020 20:00:04 +0100 |
parents | e47b04b01793 |
children | 36ec10251b2b |
comparison
equal
deleted
inserted
replaced
19099:1a951a4beee3 | 19100:91bb12995034 |
---|---|
467 } | 467 } |
468 return NULL; | 468 return NULL; |
469 } | 469 } |
470 | 470 |
471 /* | 471 /* |
472 * Fill 'dict' with text properties in 'prop'. | |
473 */ | |
474 static void | |
475 prop_fill_dict(dict_T *dict, textprop_T *prop, buf_T *buf) | |
476 { | |
477 proptype_T *pt; | |
478 | |
479 dict_add_number(dict, "col", prop->tp_col); | |
480 dict_add_number(dict, "length", prop->tp_len); | |
481 dict_add_number(dict, "id", prop->tp_id); | |
482 dict_add_number(dict, "start", !(prop->tp_flags & TP_FLAG_CONT_PREV)); | |
483 dict_add_number(dict, "end", !(prop->tp_flags & TP_FLAG_CONT_NEXT)); | |
484 pt = text_prop_type_by_id(buf, prop->tp_type); | |
485 if (pt != NULL) | |
486 dict_add_string(dict, "type", pt->pt_name); | |
487 } | |
488 | |
489 /* | |
472 * Find a property type by ID in "buf" or globally. | 490 * Find a property type by ID in "buf" or globally. |
473 * Returns NULL if not found. | 491 * Returns NULL if not found. |
474 */ | 492 */ |
475 proptype_T * | 493 proptype_T * |
476 text_prop_type_by_id(buf_T *buf, int id) | 494 text_prop_type_by_id(buf_T *buf, int id) |
535 } | 553 } |
536 redraw_buf_later(buf, NOT_VALID); | 554 redraw_buf_later(buf, NOT_VALID); |
537 } | 555 } |
538 | 556 |
539 /* | 557 /* |
558 * prop_find({props} [, {direction}]) | |
559 */ | |
560 void | |
561 f_prop_find(typval_T *argvars, typval_T *rettv) | |
562 { | |
563 pos_T *cursor = &curwin->w_cursor; | |
564 dict_T *dict; | |
565 buf_T *buf = curbuf; | |
566 dictitem_T *di; | |
567 int lnum_start; | |
568 int start_pos_has_prop = 0; | |
569 int seen_end = 0; | |
570 int id = -1; | |
571 int type_id = -1; | |
572 int skipstart = 0; | |
573 int lnum = -1; | |
574 int col = -1; | |
575 int dir = 1; // 1 = forward, -1 = backward | |
576 | |
577 if (argvars[0].v_type != VAR_DICT || argvars[0].vval.v_dict == NULL) | |
578 { | |
579 emsg(_(e_invarg)); | |
580 return; | |
581 } | |
582 dict = argvars[0].vval.v_dict; | |
583 | |
584 if (get_bufnr_from_arg(&argvars[0], &buf) == FAIL) | |
585 return; | |
586 if (buf->b_ml.ml_mfp == NULL) | |
587 return; | |
588 | |
589 if (argvars[1].v_type != VAR_UNKNOWN) | |
590 { | |
591 char_u *dir_s = tv_get_string(&argvars[1]); | |
592 | |
593 if (*dir_s == 'b') | |
594 dir = -1; | |
595 else if (*dir_s != 'f') | |
596 { | |
597 emsg(_(e_invarg)); | |
598 return; | |
599 } | |
600 } | |
601 | |
602 di = dict_find(dict, (char_u *)"lnum", -1); | |
603 if (di != NULL) | |
604 lnum = tv_get_number(&di->di_tv); | |
605 | |
606 di = dict_find(dict, (char_u *)"col", -1); | |
607 if (di != NULL) | |
608 col = tv_get_number(&di->di_tv); | |
609 | |
610 if (lnum == -1) | |
611 { | |
612 lnum = cursor->lnum; | |
613 col = cursor->col + 1; | |
614 } | |
615 else if (col == -1) | |
616 col = 1; | |
617 | |
618 if (lnum < 1 || lnum > buf->b_ml.ml_line_count) | |
619 { | |
620 emsg(_(e_invrange)); | |
621 return; | |
622 } | |
623 | |
624 di = dict_find(dict, (char_u *)"skipstart", -1); | |
625 if (di != NULL) | |
626 skipstart = tv_get_number(&di->di_tv); | |
627 | |
628 if (dict_find(dict, (char_u *)"id", -1) != NULL) | |
629 id = dict_get_number(dict, (char_u *)"id"); | |
630 if (dict_find(dict, (char_u *)"type", -1)) | |
631 { | |
632 char_u *name = dict_get_string(dict, (char_u *)"type", FALSE); | |
633 proptype_T *type = lookup_prop_type(name, buf); | |
634 | |
635 if (type == NULL) | |
636 return; | |
637 type_id = type->pt_id; | |
638 } | |
639 if (id == -1 && type_id == -1) | |
640 { | |
641 emsg(_("E968: Need at least one of 'id' or 'type'")); | |
642 return; | |
643 } | |
644 | |
645 lnum_start = lnum; | |
646 | |
647 if (rettv_dict_alloc(rettv) == FAIL) | |
648 return; | |
649 | |
650 while (1) | |
651 { | |
652 char_u *text = ml_get_buf(buf, lnum, FALSE); | |
653 size_t textlen = STRLEN(text) + 1; | |
654 int count = (int)((buf->b_ml.ml_line_len - textlen) | |
655 / sizeof(textprop_T)); | |
656 int i; | |
657 textprop_T prop; | |
658 int prop_start; | |
659 int prop_end; | |
660 | |
661 for (i = 0; i < count; ++i) | |
662 { | |
663 mch_memmove(&prop, text + textlen + i * sizeof(textprop_T), | |
664 sizeof(textprop_T)); | |
665 | |
666 if (prop.tp_id == id || prop.tp_type == type_id) | |
667 { | |
668 // Check if the starting position has text props. | |
669 if (lnum_start == lnum) | |
670 { | |
671 if (col >= prop.tp_col | |
672 && (col <= prop.tp_col + prop.tp_len-1)) | |
673 start_pos_has_prop = 1; | |
674 } | |
675 else | |
676 { | |
677 // Not at the first line of the search so adjust col to | |
678 // indicate that we're continuing from prev/next line. | |
679 if (dir < 0) | |
680 col = buf->b_ml.ml_line_len; | |
681 else | |
682 col = 1; | |
683 } | |
684 | |
685 prop_start = !(prop.tp_flags & TP_FLAG_CONT_PREV); | |
686 prop_end = !(prop.tp_flags & TP_FLAG_CONT_NEXT); | |
687 if (!prop_start && prop_end && dir > 0) | |
688 seen_end = 1; | |
689 | |
690 // Skip lines without the start flag. | |
691 if (!prop_start) | |
692 { | |
693 // Always search backwards for start when search started | |
694 // on a prop and we're not skipping. | |
695 if (start_pos_has_prop && !skipstart) | |
696 dir = -1; | |
697 break; | |
698 } | |
699 | |
700 // If skipstart is true, skip the prop at start pos (even if | |
701 // continued from another line). | |
702 if (start_pos_has_prop && skipstart && !seen_end) | |
703 { | |
704 start_pos_has_prop = 0; | |
705 break; | |
706 } | |
707 | |
708 if (dir < 0) | |
709 { | |
710 if (col < prop.tp_col) | |
711 break; | |
712 } | |
713 else | |
714 { | |
715 if (col > prop.tp_col + prop.tp_len-1) | |
716 break; | |
717 } | |
718 | |
719 prop_fill_dict(rettv->vval.v_dict, &prop, buf); | |
720 dict_add_number(rettv->vval.v_dict, "lnum", lnum); | |
721 | |
722 return; | |
723 } | |
724 } | |
725 | |
726 if (dir > 0) | |
727 { | |
728 if (lnum >= buf->b_ml.ml_line_count) | |
729 break; | |
730 lnum++; | |
731 } | |
732 else | |
733 { | |
734 if (lnum <= 1) | |
735 break; | |
736 lnum--; | |
737 } | |
738 } | |
739 } | |
740 | |
741 /* | |
540 * prop_list({lnum} [, {bufnr}]) | 742 * prop_list({lnum} [, {bufnr}]) |
541 */ | 743 */ |
542 void | 744 void |
543 f_prop_list(typval_T *argvars, typval_T *rettv) | 745 f_prop_list(typval_T *argvars, typval_T *rettv) |
544 { | 746 { |
562 size_t textlen = STRLEN(text) + 1; | 764 size_t textlen = STRLEN(text) + 1; |
563 int count = (int)((buf->b_ml.ml_line_len - textlen) | 765 int count = (int)((buf->b_ml.ml_line_len - textlen) |
564 / sizeof(textprop_T)); | 766 / sizeof(textprop_T)); |
565 int i; | 767 int i; |
566 textprop_T prop; | 768 textprop_T prop; |
567 proptype_T *pt; | |
568 | 769 |
569 for (i = 0; i < count; ++i) | 770 for (i = 0; i < count; ++i) |
570 { | 771 { |
571 dict_T *d = dict_alloc(); | 772 dict_T *d = dict_alloc(); |
572 | 773 |
573 if (d == NULL) | 774 if (d == NULL) |
574 break; | 775 break; |
575 mch_memmove(&prop, text + textlen + i * sizeof(textprop_T), | 776 mch_memmove(&prop, text + textlen + i * sizeof(textprop_T), |
576 sizeof(textprop_T)); | 777 sizeof(textprop_T)); |
577 dict_add_number(d, "col", prop.tp_col); | 778 prop_fill_dict(d, &prop, buf); |
578 dict_add_number(d, "length", prop.tp_len); | |
579 dict_add_number(d, "id", prop.tp_id); | |
580 dict_add_number(d, "start", !(prop.tp_flags & TP_FLAG_CONT_PREV)); | |
581 dict_add_number(d, "end", !(prop.tp_flags & TP_FLAG_CONT_NEXT)); | |
582 pt = text_prop_type_by_id(buf, prop.tp_type); | |
583 if (pt != NULL) | |
584 dict_add_string(d, "type", pt->pt_name); | |
585 | |
586 list_append_dict(rettv->vval.v_list, d); | 779 list_append_dict(rettv->vval.v_list, d); |
587 } | 780 } |
588 } | 781 } |
589 } | 782 } |
590 | 783 |