highlight based on external file search - vim

I have two text files, ones is the file I'm currently working, the other is kind of dictionary. What I would like to do is to search the first one using the latter as input. I'd like to highlight all matching lines.
E.g.:
File1:
I like eggs
I like meat
I don't like eggplant
My mom likes chocolate
I like chocolate too
File2:
meat
chocolate
In this example the those lines should be highlighted:
I like meat
My mom likes chocolate
I like chocolate too

The approach is similar to the answer I've given to your related question: Use readfile(), join() the lines to a pattern, then use :match.
Here's how I would build this interactively on the command-line:
:match Search /.*\%(<C-R>=join(readfile('file2'), '\|')<CR>\).*/<CR>
Note that this quick one-liner omits error handling, regular expression escaping, etc. In case you need to do this often, I'd suggest you turn this into a custom command, just like I have shown you in the linked answer.

Related

vim: Run multiple commands based off of one :global command

Apologies if this has been posted already, for I cannot find an answer, even on the vim wiki.
Is there a way I can run multiple commands in vim command-line mode off of a single :g search?
For example,
:%g/foo/ s/bar/\=#a/g | exe "norm /cat\<enter>\"ayiw"
Which (for what I intend it to do) should, on every line matching foo, replace bar with the contents of register a, and then find the next iteration of cat (even if it is many lines ahead), and put the surrounding word into register a.
Instead, this specific syntax completes the subsitution command using the current contents of the initial a register, and then executes the normal mode command on a single line (after the substitution has been completed).
This example is not my specific use-case but shows one instance where this functionality is useful. I realize I could put it all into a single exe, i.e., %g/foo/exe "norm :s/bar/\\=#a/g\<enter>/cat\<enter>\"ayiw", but I would like to do it the first way, as I feel it is more flexible.
I would prefer to do this using vanilla vim, but if a plugin exists for this, that is an okay alternative. Does anybody know if there is syntax to do such a thing?
Okay a "little bit" dirty, but does this work for you?
:let list = split(execute('g/cat/p'), '\n') | g/foo/ s/bar/\=matchstr(remove(list, 0), '\s\d\+\s\zs.*')/g
It first reads all occurences of cat save them in a list.
Then replace the first bar with the first cat... and so on.
The dirty part ist the matchstr command. the g//p also returns a number for the result so the list looks like this:
1 cat
2 cat
3 cat
...
that's why we have to remove a bit from the front. I would love to hear if someone knows a clean solution for that (I am also interested in a clean vimscript solution, does not have to be a oneliner).
You can do this (at least for multiple :s commands applied to a single :g). Example:
" SHORT STORY TITLES to single word of CapitalizedWords within <h3>s
.,$g/^\L\+$/s/[^A-Z0-9 ]\+//ge|s/\u\+/\L&/ge|s/\<\l\+\>/\u&/ge|s/ \+//ge|s/.*/<h3>&<\/h3>/

does vimdiff support merging diffs

Can vimdiff support a merge of diffs that are on the same line (so that I get the aggregate of them?)
example: starting with the following conflict markers:
I
like
apples
peaches
<<<<<<< HEAD
bananas
=======
cherries
>>>>>>> diverge
for supper
in the example above, can I use the do and dp commands to actually merge the diffs, or can I only end up with one of the other?
put another way, If I'd like to end up with
I
like
apples
peaches
bananas
cherries
for supper
then can I do this with diffpush and get, or do I have to drop back to basic vim commands to select the hunks to merge? as bananas and cherries are on the same line, diffget and push can control which I pick, but I dont seem to be able to have both and merge.
Not without a plugin/mapping. By default, you will need to resort to normal editing commands.
It looks like the "Splice" plugin ( https://github.com/sjl/splice.vim ) provides mappings to select hunks from multiple files; I haven't used it though so it may not work the way I assume.

What is the use case of marks?

Both Sublime Text 2 and VIM have a feature called marks. However, I've not been able to find a use case for it. It feels like everything you can do with it can also be done with other things, often even better.
So the question is: what is the use case of marks?
If you mean marking text lines as in vim, I use it quite a bit.
For example, if you want to quickly go look at something else, you can use ma to mark the current line as a, then go check out something else in the file, then return to where you were with a simple 'a.
Similarly, if you want to delete an unknown number of lines between your current position and somewhere else, use ma, go to that "somewhere else, and just use d'a.
There are many more things you can do with them (such as changing text between your current position and a mark), those two are just the most common ones I use (and I use them a lot).

vim substitute mulitple characters in a line

Command :%s:a:b will modify line aaa to line baa. The question is how to get result bbb using only one command (not using :%s:a:b 3 times, what I am doing now :-) ).
You need to add g flag at the end, like this:
:%s:a:b:g
When working with regular expressions this flag commonly means a "global" replacement, i.e. replace all occurrences.
The same technique usually works in other tools too that use regular expressions, for example sed, perl, etc.
UPDATE
I am surprised that such a simple answer still keeps receiving upvotes... So for you vim fans out there I recommend this great site where I still keep learning interesting new stuff: http://vimcasts.org/
remember the 'e' flag
:%s:a:b:e
Have a look at this answer Multiple search and replace in one line

Book translation data format

I'm thinking of translating a book from English to my native language. I can translate just fine, and I'm happy with vim as a text editor. My problem is that I'd like to somehow preserve the semantics, i.e. which parts of my translation correspond to the original.
I could basically create a simple XML-based markup language, that'd look something like
<book>
<chapter>
<paragraph>
<sentence>
<original>This is an example sentence.</original>
<translation lang="fi">Tämä on esimerkkilause.</translation>
</sentence>
</paragraph>
</chapter>
</book>
Now, that would probably have its benefits but I don't think editing that would be very fun.
Another possibility that I can think of would be to keep the original and translation in separate files. If I add a newline after each translation chunk and keep line numbering consistent, editing would be easy and I'd be able to programmatically match the original and translation.
original.txt:
This is an example sentence.
In this format editing is easy.
translation-fi.txt:
Tämä on esimerkkilause.
Tässä muodossa muokkaaminen on helppoa.
However, this doesn't seem very robust. It would be easy to mess up. Probably someone has better ideas. Thus the question:
What would be the best data format for making a book translation with a text editor?
EDIT: added tag vim, since I'd prefer to do this with vim and believe that some vim guru might have ideas.
EDIT2: started a bounty on this. I'm currently leaning to the second idea I describe, but I hope to get something about as easy to edit (and quite easy to implement) but more robust.
One thought: if you keep each translatable chunk (one or more sentences) in its own line, vim's option scrollbind, cursorbind and a simple vertical split would help you keeping the chunks "synchronized". It looks very much like to what vimdiff does by default. The files should then have the same amount of lines and you don't even need to switch windows!
But, this isn't quite perfect because wrapped lines tend to mess up a little bit. If your translation wraps over two or three more virtual lines than the original text, the visual correlation fades as the lines aren't one-on-one anymore. I couldn't find a solution or a script for fixing that behavior.
Other suggestion I would propose is to interlace the translation into the original. This approaches the diff method of Benoit's suggestion. After the original is split up into chunks (one chunk per line), I would prepend a >> or similar on every line. A translation of one chunk would begin by o. The file would look like this:
>> This is an example sentence.
Tämä on esimerkkilause.
>> In this format editing is easy.
Tässä muodossa muokkaaminen on helppoa.
And I would enhance the readability by doing a :match Comment /^>>.*$/ or similar, whatever looks nice with your colorscheme. Probably it would be worthwhile to write a :syn region that disables spell checking for the original text. Finally, as a detail, I'd bind <C-j> to do 2j and <C-k> to 2k to allow easy jumping between the parts that matter.
Pros for this latter approach also include that you could wrap things in 80 columns if you feel like I do :) It would still be trivial to write <C-j/k> to jump between translations.
Cons: buffer-completion suffers as now it completes both original and translated words. English words don't hopefully occur in the translations that often! :) But this is as robust as it gets. A simple grep will peel the original text off after you are done.
Why not use a simplified diff format?
it is linewise which is suitable for whole sentences.
The first character is significant (space, special, + or -)
It will be quite compact
Maybe you needn't those ## parts
Vim will support it and color the English sentence and the Finnish sentence in distinct colors.
Assuming you want to keep the 1 - 1 relationship between the original text and the translated text, a database table makes the most sense.
You'd have one table with the following columns:
id - Integer - Autonum
original_text - Text - Not null
translated_text - Text - Nullable
You'd need a process to load the original text, and a process to show you one line of the original text and allow you to type the translated text. Perhaps the second process could show you 5 lines (2 before, the line you want to translate, and 2 after) to give you context.

Resources