Skip to content

Commit

Permalink
Improve filename completer
Browse files Browse the repository at this point in the history
Add the following improvements to the filename completer:
 - allow completion of paths containing spaces;
 - allow completion of multiple paths on the same line;
 - allow completion of relative paths not starting with ".", "..", or "./";
 - allow completion of Windows environment variables (e.g. %USERPROFILE%).
  • Loading branch information
micbou committed Sep 20, 2018
1 parent 59374e9 commit 3aa8055
Show file tree
Hide file tree
Showing 11 changed files with 488 additions and 503 deletions.
32 changes: 12 additions & 20 deletions ycmd/completers/cpp/flags.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (C) 2011, 2012 Google Inc.
# Copyright (C) 2011-2018 ycmd contributors
#
# This file is part of ycmd.
#
Expand Down Expand Up @@ -27,8 +27,14 @@
import inspect
from future.utils import PY2, native
from ycmd import extra_conf_store
from ycmd.utils import ( re, ToCppStringCompatible, OnMac, OnWindows, ToUnicode,
ToBytes, PathsToAllParentFolders )
from ycmd.utils import ( ListDirectory,
OnMac,
OnWindows,
PathsToAllParentFolders,
re,
ToCppStringCompatible,
ToBytes,
ToUnicode )
from ycmd.responses import NoExtraConfDetected

# -include-pch and --sysroot= must be listed before -include and --sysroot
Expand Down Expand Up @@ -515,26 +521,12 @@ def _SelectMacToolchain():
]

for toolchain in MAC_CLANG_TOOLCHAIN_DIRS:
if _MacClangIncludeDirExists( toolchain ):
if os.path.exists( toolchain ):
return toolchain

return None


# Ultimately, this method exists only for testability
def _GetMacClangVersionList( candidates_dir ):
try:
return os.listdir( candidates_dir )
except OSError:
# Path might not exist, so just ignore
return []


# Ultimately, this method exists only for testability
def _MacClangIncludeDirExists( candidate_include ):
return os.path.exists( candidate_include )


# Add in any clang headers found in the supplied toolchain. These are
# required for the same reasons as described below, but unfortuantely, these
# are in versioned directories and there is no easy way to find the "correct"
Expand All @@ -547,11 +539,11 @@ def _LatestMacClangIncludes( toolchain ):
# It might be possible to extrace this information from xcode-select, though
# xcode-select -p does not point at the toolchain directly
candidates_dir = os.path.join( toolchain, 'usr', 'lib', 'clang' )
versions = _GetMacClangVersionList( candidates_dir )
versions = ListDirectory( candidates_dir )

for version in reversed( sorted( versions ) ):
candidate_include = os.path.join( candidates_dir, version, 'include' )
if _MacClangIncludeDirExists( candidate_include ):
if os.path.exists( candidate_include ):
return [ candidate_include ]

return []
Expand Down
24 changes: 4 additions & 20 deletions ycmd/completers/cpp/include_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@
from ycmd import responses
from ycmd.completers.general.filename_completer import ( GetPathType,
GetPathTypeName )
from ycmd.utils import GetModificationTime, ListDirectory

import logging
_logger = logging.getLogger( __name__ )

""" Represents single include completion candidate.
name is the name/string of the completion candidate,
Expand Down Expand Up @@ -95,7 +94,7 @@ def GetIncludes( self, path ):

def _AddToCache( self, path, includes, mtime = None ):
if not mtime:
mtime = _GetModificationTime( path )
mtime = GetModificationTime( path )
# mtime of 0 is "a magic value" to represent inaccessible directory mtime.
if mtime:
with self._cache_lock:
Expand All @@ -107,7 +106,7 @@ def _GetCached( self, path ):
with self._cache_lock:
cache_entry = self._cache.get( path )
if cache_entry:
mtime = _GetModificationTime( path )
mtime = GetModificationTime( path )
if mtime > cache_entry[ 'mtime' ]:
includes = self._ListIncludes( path )
self._AddToCache( path, includes, mtime )
Expand All @@ -118,25 +117,10 @@ def _GetCached( self, path ):


def _ListIncludes( self, path ):
try:
names = os.listdir( path )
except OSError:
_logger.exception( 'Can not list entries for include path %s.', path )
return []

includes = []
for name in names:
for name in ListDirectory( path ):
inc_path = os.path.join( path, name )
entry_type = GetPathType( inc_path )
includes.append( IncludeEntry( name, entry_type ) )

return includes


def _GetModificationTime( path ):
try:
return os.path.getmtime( path )
except OSError:
_logger.exception( 'Can not get modification time for include path %s.',
path )
return 0
Loading

0 comments on commit 3aa8055

Please sign in to comment.