2

I'm creating a new function to justify text. I know there are a few plugins but they don't do what I want to do so I decided to create a function myself.

before:

text_text_text_text_____

after:

text__text___text___text

What I did first is to find the number of words and the number of non space characters (for every line in my text):

let @e = '' | redir @e | silent exe i.'s/'.cols.'\(\S\+\)/&/gne' | redir END
     if matchstr(@e, 'match') != '' | let nrwords   = matchstr(@e, '\d\+\ze') | else | continue          | endif
let @e = '' | redir @e | silent exe i.'s/'.cols.'\S/&/gne'   | redir END
     if matchstr(@e, 'match') != '' | let nonspaces = matchstr(@e, '\d\+\ze') | else | let nonspaces = 0 | endif

Then to find the spaces:

let spaces = textwidth_I_want - nonspaces

I have to divide the spaces between the words:

let SpacesBetweenWords = spaces/(str2float(nrwords)-1)   

However often it is a float number.
p.e. spaces = 34
nr.words-1 = 10
SpacesBetweenWords = 3.4

What I want to do is to divide the spaces between the word, like this:
Spaces between words:
4 3 3 4 3 3 4 3 3 4
and put them in a list 'SpaceList'

and then insert them between the words

 for m in range(1,len(SpaceList))
    exe i 's/^'.cols.'\(\S\+\zs\s\+\ze\S\+\)\{'.m.'}/'.repeat(' ', SpaceList[m-1]).'/'
 endfor

(cols = my block selection OR entire line)

It is easy to create a list with all integers p.e. in my example
3 3 3 3 3 3 3 3 3 3 (Spaces = 30)
but there are still 4 spaces to divide between the words.
My problem is "how can I divide these spaces between the number of words"?

Xavier T.
  • 40,509
  • 10
  • 68
  • 97
Reman
  • 7,931
  • 11
  • 55
  • 97

2 Answers2

1

The result is 3.4, it means, you cannot make all distances between words with same length. You have to either adjust the textwidth_I_want value to make the result an integer, or you set the distance as 3, and calculate how many spaces you still need (10*(3.4-3)=4). You can add these 4 spaces to 4 distances.

Kent
  • 189,393
  • 32
  • 233
  • 301
  • Thanks Kent, do you have any idea how to distribute random these 4 spaces (in a formule)? – Reman Dec 17 '15 at 13:45
  • does it make any difference? put each space in the first 4 distances or last 4 or randomly? – Kent Dec 17 '15 at 21:54
  • oh yes it does. I'll see more empty spaces at the left side of the text if I put each extra space in the first 4 distances. – Reman Dec 18 '15 at 07:54
0

Found the solution using python

let r = float2nr(SpacesBetweenWords)
let places = nrwords-1
"the extra spaces to put between words
let extraspaces2divide = float2nr(spaces-r*places)
"find randomly with the help of python a serie of (unique) numbers for every space to divide, numbers between 1 and the number of words
exe "py import vim,random;  Listvalue = random.sample(xrange(1,".(places+1).",1),".extraspaces2divide.");vim.command(\"let randomlist = '%s'\"% Listvalue)"

"the result of python is a string like this [1, 3, 6, 9]: remove the brackets and spaces and split the result to a list
let randomlist = substitute(randomlist, '[\[\] ]', '', 'g')
"this list is the serie of random numbers (= the place between words) where to add an extra space
let list = sort(split(randomlist, ','))

for s in range(1,nrwords-1)
  if (index(list, ''.s.'') != -1)
    let r2 = r+1
  else
    let r2 = r
  endif
  call add(SpaceList, r2)
endfor
Reman
  • 7,931
  • 11
  • 55
  • 97