Apply a Vim macro to multiple lines - json

I made a simple macro to increment a number in a json object like this:
{
image: 'images/2.jpg',
thumb: 'images/2-thumb.jpg',
big: 'images/2.jpg',
title: '',
description: '',
link: 'images/2.jpg'
},
with:
q, n, shift-v, down-till-end, p, move-to-numbers, c-a, return-to-top, q, 150#n
(Sorry if that's not the appropriate syntax to post vim macros here in SE)
And it works, but it makes the increment just until the 9th. What am I missing?
Thanks in advance.
EDIT:
I'm trying to reach something like this:
{
image: 'images/3.jpg',
thumb: 'images/3-thumb.jpg',
big: 'images/3.jpg',
title: '',
description: '',
link: 'images/3.jpg'
},
{
image: 'images/4.jpg',
thumb: 'images/4-thumb.jpg',
big: 'images/4.jpg',
title: '',
description: '',
link: 'images/4.jpg'
},
... until *nth* value

Assuming your cursor is on the first opening bracket, here is one way to do it:
qn " start recording in register n
V% " select from here to the closing bracket, linewise
y " yank the selection
% " jump to the closing bracket
p " paste after the current line
:'[,']norm <C-v><C-a> " executing the normal mode command <C-a>(1) on all the lines that we just pasted
q " stop recording
then do 150#n.
(1) <C-v><C-a> is used to insert a literal ^A.

Try this:
Enter visual mode and select the lines to be included in the macro execution an type:
:normal #n
Then, when you hit enter, the macro will be applied to selected lines

I gave it a try:
qqv%:s/\d\+/\=submatch(0)+1/^M[[yGGp
short explanation
qq "recording to register q
v% "select things between { and }
:s/\d\+/\=submatch(0)+1/^M "just do +1 to all numbers (selected range)
[[ "back to begin {
yG "yank till the end
Gp "paste at the end
then do 150#q
if you record the same macro, type ^M simply by Enter
if you assign the macro to #q type ^M by <c-v><enter>
btw, this won't win golf, since the function name submatch(0) is too long...:)

With my UnconditionalPaste plugin, once you have yanked the original block into a register, you can paste [N] auto-incremented blocks simply with [N]gPp (paste linewise with all numbers incremented).
The plugin also allows several other manipulations of the way the text is pasted.

Related

Customize protractor-html-screenshot-reporter

I'm generating an HTML report using protractor-html-screenshot-reporter.
I get false/true under the Passed column but I want Passed/Failed instead.
Expected - Failed(in red) or Passed(in green)
Actual - False(in red) or True(in green)
Code Snippet -
function defaultMetaDataBuilder(spec, descriptions, results, capabilities) {
var metaData = {
description: descriptions.join(' ')
, passed: results.passed()
, os: capabilities.caps_.platform
, browser: {
name: capabilities.caps_.browserName
, version: capabilities.caps_.version
}
, message: ''
}
If I replace passed: results.passed() by this code -
passed: results.passed() ? 'Passed' : 'Failed'.
I get Passed/Failed instead of True/False but Failed also comes in Green.
How should I handle this scenario. Any suggestions are always welcome
You have to alter how the page is rendered. Looking at source code for protractor-html-screenshot-reporter I can see that the page is fully created in javascript file.
Go to this library source code to jsonparser.js(protractor-html-screenshot-reporter/lib/jsonparser.js) and modify function generateHTML(data). Currently it looks at data.passed to see if this boolean is true or false. Based on that it generates color and prints this value to the column. You want to edit this line to something like this:
str += '<td class="status-col" style="color:#fff;background-color: '+ bgColor+'">' + (data.passed ? "Passed" : "Failed") + '</td>';
Personally if you expect to modify this page even more, I would advice you to move this code into html page instead of generating it inside javascript file.

Sublime text 2 completions

Making the *.sublime-completions file, I found the "bug" which occurs when typing a long function like:
one.two.three.four.five(One := One_var, Two := Two_Var);
So if you type the whole function:
"one.two.three.four.five" and then press tab - it will paste another part of functions without issues.
But, if you type "one.two.thr" - and then in pop-up hint see that function and hit "Enter" it will replaces like:
one.two.one.two.three.four.five(One := One_var, Two := Two_Var);
How can I configure trigger to replace "one.two.thr" to correct function format?
This is my trigger.
{ "trigger": "one.two.three.four.five", "contents": "${TM_CURRENT_LINE/(.*)/(one.two.three.four.five)/}(One := One_var, Two := Two_Var);" },
This is not a bug, but a default setting of Sublime Text. By default, dots are treated as word_separators. Hence every time you type ., the completion trigger will be reset.
Example:
Let's assume we have only the following completions available:
{
"trigger": "one.two.three",
"contents": "one.two.three.four.five"
},
{
"trigger": "two",
"contents": "it_takes_two"
}
Now, let's type them in Sublime Text (the | marks the cursor position!)
one| -> will trigger "one.two.three.four.five"
one.| -> new word, forgot about "one.two.three.four.five"
one.two| -> will trigger "it_takes_two"
In the last case, both completions will be listed in the completion popup does to the fuzzy match for ”two”. However, the closer match ”two” will have a higher priority.
To fix this, you can edit the word_separators setting in a package setting or your global user settings. By default the setting treats the following characters as word separators:
./\\()\"'-:,.;<>~!##$%^&*|+=[]{}`~?
Alternatively, you ommit the dots from your completion triggers, e.g. use one-two-three instead of one.two.three.

vim keep cursor position when counting matches

I have a function to count and return the number of matches of some text:
function! count_matches()
redir => matches_cnt
silent! %s/\[\d*\]//gn
redir END
return split(matches_cnt)[0]
endfunction
I created a map to insert the return value of count_matches() at the current position:
noremap <C-A> Go[foo<C-R>=count_matches()<CR>]
However the cursor jumps to the beginning of the line after executing the silent %s/[\d*]//gn command. So when I press control+a vim inserts "[foo", then the function is being executed, the search command resets the cursor position and the return value is inserted at the beginning of the line resulting in "1][foo" instead of "[foo1]".
Can I somehow prevent count from changing the cursor position, or reset the cursor position after counting the matches?
The script also leads to an error, if the pattern is not found. How can I get the function to return 1 without an error for zero matches?
Even better then just to save the cursor position, is to save the complete viewport. (But that only works, if you do not change the window layout)
See :help winsaveview()
let wsv = winsaveview()
MoveTheCursorAround
call winrestview(wsv)
In your particular case, I would take another approach:
inoremap <expr> <f3> len(split(join(getline(1,'$'),"\n"), '\[\d\+\]',1))
Which takes the whole text, and splits it on the pattern \[\d\+\] and then counts how many elements there are. Or if you like to add some text:
inoremap <expr> <f3> '['.len(split(join(getline(1,'$'),"\n"), '\[\d\+\]',1)).']'
This will add the [ in front and ] after the number. Adjust the mapping key and text to your personal taste. (Note, you do not need the winsaveview() function, cause the cursor won't move).
It is perhaps not such a good idea to use that function on a multi MB text size. ;)
This is the same function, reworked to return 1 when there's no match:
function! count_matches()
redir => matches_cnt
try
silent! %s/\[\d*\]//gn
catch
echo 1
endtry
redir END
return split(matches_cnt)[0]
endfunction
See :help getpos()
let save_cursor = getpos(".")
MoveTheCursorAround
call setpos('.', save_cursor)
My solution:
function! CountWithCursorKeep(...)
let currentCursor = getcurpos()
let pattern = expand('<cword>')
if a:0 > 0 | let pattern = a:1 | endif
execute(':%s#' . pattern . '##gn')
call setpos('.', currentCursor)
endfunction
nmap ,ns :call CountWithCursorKeep(<C-R>/)<cr>
nmap ,nw :call CountWithCursorKeep(expand('<cword>'))<cr>
nmap ,nW :call CountWithCursorKeep(expand('<cWORD>'))<cr>
command! -nargs=? -bar -complete=tag CountMatch call CountWithCursorKeep(<f-args>)
You can use :CountMatch pattern to get how many times pattern occurs in current file.

preg_replace not working

I have this function in my website.
function autolink($content) {
$pattern = "/>>[0-9]/i" ;
$replacement = ">>$0";
return preg_replace($pattern, $replacement, $content, -1);
This is for making certain characters into a clickable hyperlink.
For example, (on a thread) when a user inputs '>>4' to denote to the another reply number 4, the function can be useful.
But it's not working. the characters are not converted into a hyperlink. They just remain as plain text. Not clickable.
Could someone tell me what is wrong with the function?
So the objective is to convert:
This is a reference to the >>4 reply
...into:
This is a reference to the >>4 reply
...where ">" is the HTML UTF-8 equivalent of ">". (remember, you don't want to create HTML issues)
The problems: (1) you forgot to escape the quotes in the replacement (2) since you want to isolate the number, you need to use parentheses to create a sub-pattern for later reference.
Once you do this, you arrive at:
function autolink($contents) {
return preg_replace( "/>>([0-9])/i",
">>$1",
$contents,
-1
);
}
Good luck

Why does this function "skip" on line 63?

I am trying to modify this terrific VIM script however both the original and my modified version have a maddening bug in which sometimes the cursor is shown in the wrong place. The simplest example that I could make is the 71 line text file below. Note that whitespace is important when copying the file.
<?php
/**
* Some silly method
*
* #param string Some silly string
*/
function someFunction()
{
global $class, $cv, $go, $pae;
global $messages, $counters, $ltn;
global $sh, $sub, $temp;
$charsets = array(
'us',
'si',
'pr',
'op',
'co',
'pa',
'av',
'pr',
'al',
'pc',
'pe',
'pi',
'pp',
'su',
'qu',
'de',
'ze',
'xo',
'mo',
'wo',
'de',
'mo',
'de',
'mo',
'dr',
'mo',
'de',
'mo',
'ev',
'pa',
'so',
'ms',
'bu',
'at',
'cu',
'pr',
'de',
'mo',
'nv',
'nl',
'nf',
'ne',
'nq',
'nt'
);
}
This is the relevant .vimrc file with the function:
set cul
hi CursorLine term=none cterm=none ctermbg=20
set nu
set statusline+=%{WhatFunctionAreWeIn()}
set laststatus=2
fun WhatFunctionAreWeIn()
let strList = ["while", "foreach", "ifelse", "if else", "for", "if", "else", "try", "catch", "case"]
let foundcontrol = 1
let position = ""
normal mz
while (foundcontrol)
let foundcontrol = 0
" The idea here is to go back to non-whitespace character before
" the last hanging open { and to check if it is a close paran.
" If so, then go to the matching open paren and search for the
" preceding it.
" If not, then go ahead and check the keyword right there.
normal [{
?\S
let tempchar = getline(".")[col(".") - 1]
if (match(tempchar, ")") >=0 )
normal %
?\S
endif
let tempstring = getline(".")
for item in strList
if( match(tempstring,item) >= 0 )
let position = item . " - " . position
let foundcontrol = 1
break
endif
endfor
if(foundcontrol == 0)
normal `z
return tempstring.position
endif
endwhile
normal `z
return tempstring.position
endfun
Starting from the beginning of the file, press j repeatedly until you get to line 63. Note that the highlighted cursorline stays on the correct line (63) but the cursor is shown on line 55. Jumping directly to line 63 won't trigger the bug, only pressing j repeatedly until you get to that line will.
Why does that happen, and how can I fix it? Note that when the cursor appears to be in the wrong place, pressing ``z` does in fact snap the cursor to the correct location. This is on VIM 7.3.154 on Kubuntu 11.10.
EDIT:
I notice by testing in other installs (Debian, CentOS) that the bug is not determinate, it happens occasionally but not in the same place on every system! You can test this code by pressing j and paying attention to the cursor location in whatever PHP files that you might have strung about. I would say that about one line out of every hundred lines triggers the bug in which the cursor appears to be in the wrong place.
I'm slightly confused by the logic of this function, but I suspect it is the ?\S which is causing the problems. It is searching backwards for a non-whitespace character, and wrapping around to the bottom of the file once it has reached the top.
Try replacing both occurrences of ?\S with
call search('\S','bW')
(Here the b flag searches backwards, and W prevents wrapping around the file.)
EDIT (2nd attempt)
The function also causes lots of jumping around of the view. The root of this is continually setting the mark mz and jumping to and fro. A better approach in vimscripts is to use the following commands to save the current view (instead of normal mz):
let pos=getpos(".") " This saves the cursor position
let view=winsaveview() " This saves the window view
You can then use these to restore the view:
call cursor(pos) " This restores the cursor position to that of "pos"
call winrestview(view) " This restores the window view to that of "view"
So I would use call cursor(pos) instead of `z and call winrestview(view) just before the return commands. This ensures that the function doesn't modify the appearance of the window, and makes for more pleasant usage.
Hope this helps!