0

I want to annotate words /sentences for a "named entity recognition" purpose; inside a text file, I want to annotating words or sentences with this format [pattern](label):

[a word where the cursor is or a selected sentence, a span](entity_name)

Suppose I have this text file:

  # untagged.yaml
  - intent: body_temperature_data
    examples: |
      - il termometro misura 36.3 gradi
      - 36.9
      - 35,9
      - la temperatura è di 36 e 7 gradi
      - 36 , 8

I want by example to tag decimal numbers assigning the entity body_temperature to each of them, transforming the original file in this one:

  # after_tagging.yaml
  - intent: body_temperature_data
    examples: |
      - il termometro misura [36.3](body_temperature) gradi
      - [36.9](body_temperature)
      - temperatura: [35,9](body_temperature)
      - la temperatura è di [36 e 7](body_temperature) gradi
      - [36 , 8](body_temperature)

What I need is a vim way to quickly substitute this line:

  - il termometro misura 36.3 gradi

in this line:

  - il termometro misura [36.3](body_temperature) gradi

Now, suppose I'm with cursor inside a word (a number in fact):

36.3

I want to substitute the (selected) word or sentence, with a keyboard shortcut in

[36.3](body_temperature)

So the original pattern 36.3 would be "decorated" with [pattern](label)

I know the basic substitute command:

s/selected_pattern/replace

and in this special case I want to do something like

s/pattern/[pattern](label)

But i do not know the syntax to make this replacement, maybe something like this (still not working):

'<,'>s/'<,'>/[\0](body_temperature)
  • let assume body_temperature is in a short list of options (label_1, label_2, label_N) maybe stored in a vimscript variable I can assign.
  • I would like to trigger the substitution with a keyboard shortcut (e.g. F1 key).

How can I do that?

BTW, that's part of the bigger problem here detailed: Vim editor entities tagging/annotation tool

thanks

2

Normal mode

with the :substitute command.

nnoremap <leader>t :s/\%#\<<c-r><c-a>\>/[&]()/<cr>f(a

The trick is to use <c-r><c-a> which will insert the :h <cWORD> under the cursor, i.e non-whitespace characters. <c-r><c-w> would insert the <cword>, which respects :h 'iskeyword, and would therefore (with default values) not contain decimals in floating numbers.

:h \%# start the match at the cursor position, so only the current occurrence of the pattern matches. This means the mapping will fail if the cursor is not on the first character of the word.

:h \<and \> match the beginning and end of a word. It's probably unecessary here.

Finally, the & in the string part represent the matched pattern, <cr> launches the command.

f(a places the cursor in insert mode between the parentheses.

"simple" way

nnoremap <leader>t ciW[<c-o>P]()<left>

ciw]: delete the WORD under the cursor and insert [.

<c-o>P: paste what was just deleted before the cursor

](): insert the rest of the decoration

<left>: go between parenthesis

Visual mode

vnoremap <leader>t :s/\%V.*\%V./[&]()/<cr>f(a

The difference is the match pattern: \%V.*\%V. matches the visual selection (:h \%V).

Setting mappings for each label

This script creates a mapping <leader>tX for each 'label' in the 's:labels' variable, X being a number. printf is a convenient way to pass a string to the execute command.

let s:labels = ["label1", "label2", "label3"]
for i in range(len(s:labels))
  exe printf("vnoremap <leader>t%d :s/\\%%V.*\\%%V./[&](%s)/<cr>n:nohl<cr>f)", i+1, s:labels[i])
  exe printf("nnoremap <leader>t%d ciW[<c-o>P](%s)<esc>", i+1, s:labels[i])
endfor

n:nohl<cr>f) tries to place the cursor after the label. It will fail if a ) is in the pattern.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.