4

I would like to sort some lines, ignoring a leading part of them.

Here's an example from my .spacemacs file:

'(
     better-defaults
     elixir
     emacs-lisp
     erlang
     evil-commentary
     finance
     git
     haskell
     html
     ivy
     javascript
     lua
     markdown
     my-eshell
     my-org
     nginx
     nixos
     (org :variables org-projectile-file "TODO.org")
     python
     (ruby :variables ruby-test-runner 'rspec)
     shell-scripts
     spell-checking
     (syntax-checking :variables syntax-checking-enable-tooltips nil)
     vinegar
     yaml
)

I would like to sort these, but I need to ignore the leading ( for that.

Similarly, here's an excerpt from my configuration.nix:

packages = with pkgs; [
      ## Basics
      atool
      bashInteractive
      entr
      ethtool
      fasd
      fd
      file
      fzf
      git
      git-crypt
      gitAndTools.hub
      google-cloud-sdk
      gparted
      hdparm
      htop
      i7z
      inotify-tools
      iperf
      lm_sensors
      neovim
      p7zip
      parted
      pwgen
      ripgrep
      sshfs
      # tarsnap
      tmux
      tree
      unzip
      wget
      xclip
      zip
];

Here, I would like to sort the lines, ignoring the leading # part.

How would I do this in Vim?

I'm aware of :sort /\v# /, but that would only sort lines that match the pattern, then ignore the pattern for sorting.

1 Answer 1

5

You can do this with the following command:

:sort /^\s*\(# \)\?/

This skips the # if it exists, and then sorts on the remainder of the line. However, the pattern matches every line, so all lines are sorted into a single group.

You will want to add a range to the start of the command to apply this to the appropriate lines in your file.

The following command also works, coming at it from the opposite direction:

:sort r /\s*\(# \)\?\zs.*/

Instead of skipping the matched part of the line, this sorts on the matched part, but we use \zs to exclude the # from the match, if it exists.

3
  • As far as I can tell, this still does what I hoped it would not: sorting matching lines first, then non-matching ones.
    – mkaito
    Commented Sep 4, 2018 at 14:10
  • @mkaito It's because I didn't notice/failed to account for the whitespace before the prefix in your examples. I've updated with regular expressions that now handle this correctly.
    – Rich
    Commented Sep 4, 2018 at 14:19
  • If you want to include commented-out lines (no space after #): :sort /^\s*\(#\s*\)\?/ Commented Dec 17, 2020 at 0:38

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.