4

Setup

I am using NeoVim v0.7.2 (also tested with v0.6.1) on Windows 10 in git-bash, with vim-dispatch to allow for asynchronous builds (building a C++ codebase with Clang).

I have this option in my init.vim:

set switchbuf=useopen,usetab,newtab

Problem

When there are errors in the build, the quickfix list is correctly populated, but the file paths might not be normalized (e.g. src\lib\..\lib\Header.h).

When Header.h is already opened in another NeoVim window via NerdTree, the window names uses the normalized name src\lib\Header.h.

Then, if I try to jump from an error in the quickfix window, NeoVim attempts to open the same file in another window with a different name (the non normalized path).

This causes a host of issues, notably because the swap file for this file is already present. I would like to have it jump to the already opened window on the file if it exists, or to open it with the normalized name if it does not.

Can it be achieved?

1 Answer 1

0

A question for which there is a very similar answer has been asked 2 weeks ago: Translate file paths in quickfix list

To made it short: 2 solutions

  • a pure vimscript and convoluted one that applies simplify to all buffer names, but this may require completely overriding buffer numbers associated to the quick-entries. I definitively don't recommend this approach -- even if I have some vimscript code on the topic in a plugin of mine: see the other Q/A.

  • filter compilation outputs with a script that applies realpath on all detected filenames -- don't forget to forward execution failure status through pipes (set -o pipefail with bash).

Since my initial answer 2 weeks ago, OP has initiated a PR on my compilation related plugin for his specific problem that requires to use cygpath. I've worked on the related (Perl) script that still need testing. In your specific case,

I guess you should just need the realpath part and ignore the cygpath part -- even if you are on Windows, you haven't expressed the need to do path conversion between unix/windows (neo)vim and unix/windows compilation tools.

The current (untested) perl script looks like

#!/usr/bin/perl
# Author:   Luc Hermitte <EMAIL:hermitte {at} free {dot} fr>
#           <URL:http://hermitte.free.fr/vim>
# Purpose:  Convert plain Winddows pathames to MSYS pathnames.
#           Defined as a filter to use on make's result.
#           Meant to be used by Vim.
# Created:  30th Jun 2022
# Last Update:  30th Jun 2022

### Code {{{1
## Includes   {{{2
use strict                ;
use File::Spec            ; # splitpath()

## Globals    {{{2
# Hash table for the paths already translated with ``realname'', or cygpath
my %h = () ;

## Functions  {{{2
sub parent # {{{3
{
    my ($path) = @_;
    my ($vol,$dir,$file) = File::Spec->splitpath($path);
    # print "vol: '$vol'; dir: '$dir'; file: '$file'\n";
    return ("$vol$dir", $file);
}

# Proxy function: returns the realname of the path
# This function looks for converted paths into the hastable, if nothing is
# found in the table, the result is built and added into the table
# TODO: follow mounted things
sub UnixPath  # {{{3
{
    my ($path) = @_ ;
    # print "testing $path\n";
    if ( exists( $h{$path} ) ) {
        return $h{$path} ;
    } else {
        # Get the real location of the file
        my $upath = `realpath "$path"`;
        chomp ($upath);
        my ($dir, $file) = parent($upath);
        if (exists( $h{$dir} )) {
            my $udir = $h{$dir};
        } else {
            # Convert the dir to UNIX form
            my $udir = `cygpath -u $dir`;
            chomp($udir);
            # Add the dir to the hash-table
            $h{$dir} = $udir;
            # print "cygpath '$dir' --> '$udir'\n";
        }
        $upath = File::Spec->catfile($h{$dir}, $file);
        # Add the path into the hash-table
        $h{$path} = $upath ;
        return $upath ;
    }
}

## Main       {{{2
# Main loop: convert MsWindows paths into Unix paths
while (<>) 
{
    chop;
    if ( m#^( *[A-Za-z]:[\\/].*?)(\:\d*\:?.*$)# ) {
        printf UnixPath($1)."$2\n";
    } else {
        print "$_\n";
    }
}

# ======================================================================
# vim600: set foldmethod=marker:
# vim:et:ts=4:tw=79:

You don't need my plugin to use it (even if it's tailored for adding filters to compilation output (thing vanilla compiler plugins are not designed to support) on top of other compilation related tasks). As long as you have a perl interpreter in your $PATH, you can it use from makeprg vim option:

let &makeprg = 'set -o pipefail ; ninja -C ../build 2>&1 | perl /path/to/win2msys.pl

(and replace ninja by whatever tools you use to compile your code)

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.