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