0

I have a log file in which some lines are just a few characters while other lines are about a thousand. Is there a way to view the ends of each line without modifying the file?

I have two sub-optimal solutions.

Right-align via awk

:%!awk '{d[i++]=$0}x<t=length($0){x=t}END{while(j<i)printf "\%*s\n",x,d[j++]}'

... that's pretty golfed. Here's a cleaner version of what I'm doing:

{ data[i] = $0; i++ }
{ tmp = length($0); if (max < tmp) { max = tmp } }
END { while (j < i) { printf "\%*s\n", max, data[j]; j++ } }

This saves each line in an array, notes the line length and saves it if it's bigger than the previous biggest, and then iterates through each saved line, printing it out right-aligned to that max length.

This presents my data the way I want to, but it modifies the data and I need to :set sidescroll=1 and then scroll left so the end of each line is at the rightmost edge of vim's viewport.

Right-align via right-to-left

This one's pretty alienating since it swaps ^ and $ and therefore D and other commands don't operate as expected, but visually it's close (yet it also modifies the contents):

:set rightleft|%!rev

This the display orientation to right-to-left and then reverses the contents with a filter calling rev (part of GNU coreutils, which you'll have to install if you're on a Mac or BSD). I no longer have to play with sidescroll but it's still very awkward (and it modifies the file).

1 Answer 1

1

You can use matchadd() to conceal start of long lines:

let [b:logCols, b:minCols] = [80, 10]
let b:match_id = -1

function! UpdateConceal()
  if b:match_id != -1 | call matchdelete(b:match_id) | endif
  let b:logCols = max([b:logCols, b:minCols])
  echo 'log columns : ' . b:logCols
  let b:match_id =  matchadd('Conceal', printf('\v^.+\ze.{%d}$', b:logCols), 10, -1)
endfunction

call UpdateConceal()
nnoremap <silent> <buffer> <c-right> :let b:logCols += 1 \| call UpdateConceal()<cr>
nnoremap <silent> <buffer> <c-left> :let b:logCols -= 1 \| call UpdateConceal()<cr>

Copy above script and source it, play around with <c-right> and <c-left>

  • Pattern highlighted with Conceal highlight group will be concealed.

  • \v^.+\ze.{80}$ find lines that's longer then 80 characters, match from beginning of line until (not include) the last 80th character.

check

:h matchadd()
:h hl-Conceal
:h 'conceallevel'
:h 'concealcursor'

Note that this solution works on characters, not screen columns.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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