3

I'm currently using gVim on Windows XP, and I have 2 follow-ups to my core question:

What is the best method of finding the line with the most characters?

My current method: I use the regex search :/^\(\p\)\{#number#,}$), and I keep increasing the integer #number# until I get just one match. In the case of my file, it is a line of only 81K characters - not 916,657 as I previously thought. I know this because when the cursor is on that line I press g + Ctrl+g and get the column count of 81K.

Followup 1) Is the question "What is the best method of finding the line with the most columns?" the same as #2 above?

Followup 2) What does the second number mean when I open a file and see the following line at the bottom of the screen:

enter image description here

I interpret this to mean that the file has 14,871 lines, and at least one row has 916,657 columns. I checked that the file does have 14,871 lines, but I have not been able to understand the purpose of the second (916K).

2
  • Thanks to all for the answers. Each attacks the problem from a different angle! Shows the versatility of Vim.
    – drapkin11
    Commented Mar 9, 2011 at 23:39
  • 1
    For its simplicity and elegance, I will use Dennis Williamson's approach. From Eelvex's I'll continue to hone my vim commands, and from garyjohn's, my vim scripting.
    – drapkin11
    Commented Mar 10, 2011 at 0:18

6 Answers 6

4

The second number is the total character count in the whole file. If you do:

$ wc -l -c filename

you should see the same two numbers (lines and total characters). In fact, you can do:

:!wc -l -c %

Here's a plugin called textfilter (download) that includes a function to find the longest line.

Or you can use this to find the length of the longest line:

:echo max(map(range(1, line('$')), "col([v:val, '$'])")) - 1

then you can use that number like this:

/^.\{248\}$
5
  • I think you need col() if the number is to be used in conjunction with /^.\{num\} ($ is optional here)
    – Eelvex
    Commented Mar 9, 2011 at 20:53
  • 1
    @Eelvex: I made that correction. Commented Mar 9, 2011 at 21:13
  • very interesting - I've never thought of using Vim in the way of your Line 3, ":echo max(map(range ..."
    – drapkin11
    Commented Mar 9, 2011 at 23:37
  • 1
    @drapkin11: It's from :h virtcol() Commented Mar 9, 2011 at 23:43
  • :!wc % will show you the number of lines, words, and characters in the currently saved version of the current file, along with the filename.  (If you don’t want all three numbers, use options to specify the ones you want.)  To get the number(s) but not show the filename, use :!wc < %.  To get the counts for the text currently in the edit buffer, use :w !wc.  (Of course you can get the same information with g followed by Ctrl+G.) Commented May 14, 2015 at 4:31
4

There must be a better way but the following will also do:

%s/./a/g         "Replace everything with 'a's
sort!            "Sort by column length
ggy$             "Go to first line (longest) and copy it
u                "Undo the sorting
/<c-r>"          "Search for the longest line
mm               "Mark it 'm'
u                "Undo the replace
'm               "Go to the mark - there!
4
  • 1
    garyjohn's is the better way :)
    – Eelvex
    Commented Mar 9, 2011 at 20:34
  • Thanks. Meanwhile, Dennis's also came up and I suppose others will follow :)
    – Eelvex
    Commented Mar 9, 2011 at 20:52
  • /<c-r>"... what does this command do? I looked it up and it means "Redo"? After I press <c-r>, I see a quotes, then when I press ", what I previously copied gets pasted. But I'm not sure what the " actually does here.
    – drapkin11
    Commented Mar 9, 2011 at 23:33
  • 1
    @drapkin11: see help for i_CTRL-R = insert mode <C-R>. It inserts the contents of a register. " is the "last copy or cut" register.
    – Eelvex
    Commented Mar 10, 2011 at 6:18
1

Cam't speak to the first question, but that second number in the file load message is the total number of characters in the file.

1

Here's a function that does that.

function MaxLine()
    let maxcol = 0
    let lnum = 1
    while lnum <= line("$")
        call cursor(lnum, 0)
        if col("$") > maxcol
            let maxcol = col("$")
            let maxline = lnum
        endif
        let lnum += 1
    endwhile
    echo "Line" maxline "has" maxcol - 1 "characters"
endfunction

You can execute it with

:call MaxLine()

or define a command or mapping to call it.

Note that finding the line with the most actual columns is the same as the line with the most characters. That may not be the same as the line with the most bytes. If you want to find the line with the most virtual columns, replace col("$") with virtcol("$").

4
  • this is inspiring me to learn scripting in Vim. The function works, but for some reason, I need to run it twice... first time nothing gets returned, second time, it spits out "Line" maxline "has" maxcol - 1 "characters"... I'm guessing this is intended.
    – drapkin11
    Commented Mar 9, 2011 at 23:35
  • No, it should work the same every time. I can reproduce that behavior on Vim 7.3.125 on a Fedora Linux system, but I can't explain it. I set 'verbose' to 15 and compared the first and second runs--no difference in the logs. Could be a bug in Vim; could be a bug in the function I'm just not seeing.
    – garyjohn
    Commented Mar 10, 2011 at 0:46
  • Ok, it must be my gVim settings. I have it behaving like 'windows', which might account for the behaviour. In any case your response had me hit the reference books which is good.
    – drapkin11
    Commented Mar 10, 2011 at 0:50
  • On scripting: Once you get the hang of it, it is really neat. There is a lot I can do from within Vim with just a few keystrokes. It's like shell scripting: after doing the same task a few times you realize that you do it all in one step and without having to type options and file names every time with just a few lines of shell script or Vim script.
    – garyjohn
    Commented Mar 10, 2011 at 0:50
1

Not so vim-centric, and similar to some other answers, but maybe more intuitive for some people. This assumes you're ok with calling some external programs from within vim.

I have the following in file test_file:

hello world
helloooooooooooooo world !!!
yo, world!
helloooOoooOooooOo World ! !

The wc command sometimes has an -L option that prints the size of the longest line. 28 test_file is the output for my example.

You could print these 28 character lines (and their line nums) with grep -nP ".{28}" test_file.

2:helloooooooooooooo world !!!
4:helloooOoooOooooOo World ! !

You could parse the wc output with cut. Putting it all together and sticking one command into another, it's:

grep -nP ".{$(wc -L test_file | cut -f 1 -d ' ')}" test_file
0

For whole file:

max(map(getline(0, "$"), "len(v:val)"))

For selection:

max(map(getline("'<", "'>"), "len(v:val)"))

If you have multi-bytes in the file replace len() with strchars(), strwidth(), strdisplaywidth() or what fit's ones needs.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .