Example #1
0
def InstallGagdet(name, gadget, succeeded, failed, all_adapters):
    try:
        print(f"Installing {name}...")
        v = {}
        v.update(gadget.get('all', {}))
        v.update(gadget.get(install.GetOS(), {}))

        if 'download' in gadget:
            if 'file_name' not in v:
                raise RuntimeError("Unsupported OS {} for gadget {}".format(
                    install.GetOS(), name))

            destination = os.path.join(
                install.GetGadgetDir(options.vimspector_base), 'download',
                name, v['version'])

            url = string.Template(gadget['download']['url']).substitute(v)

            file_path = DownloadFileTo(
                url,
                destination,
                file_name=gadget['download'].get('target'),
                checksum=v.get('checksum'),
                check_certificate=not options.no_check_certificate)

            root = os.path.join(destination, 'root')
            ExtractZipTo(file_path,
                         root,
                         format=gadget['download'].get('format', 'zip'))
        elif 'repo' in gadget:
            url = string.Template(gadget['repo']['url']).substitute(v)
            ref = string.Template(gadget['repo']['ref']).substitute(v)

            destination = os.path.join(
                install.GetGadgetDir(options.vimspector_base), 'download',
                name)
            CloneRepoTo(url, ref, destination)
            root = destination

        if 'do' in gadget:
            gadget['do'](name, root, v)
        else:
            InstallGeneric(name, root, v)

        # Allow per-OS adapter overrides. v already did that for us...
        all_adapters.update(v.get('adapters', {}))
        # Add any other "all" adapters
        all_adapters.update(gadget.get('adapters', {}))

        succeeded.append(name)
        print(f" - Done installing {name}")
    except Exception as e:
        if not options.quiet:
            traceback.print_exc()
        failed.append(name)
        print(f" - FAILED installing {name}: {e}".format(name, e))
Example #2
0
def InstallTclProDebug(name, root, gadget):
    configure = ['sh', './configure']

    if install.GetOS() == 'macos':
        # Apple removed the headers from system frameworks because they are
        # determined to make life difficult. And the TCL configure scripts are super
        # old so don't know about this. So we do their job for them and try and find
        # a tclConfig.sh.
        #
        # NOTE however that in Apple's infinite wisdom, installing the "headers" in
        # the other location is actually broken because the paths in the
        # tclConfig.sh are pointing at the _old_ location. You actually do have to
        # run the package installation which puts the headers back in order to work.
        # This is why the below list is does not contain stuff from
        # /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform
        #  '/Applications/Xcode.app/Contents/Developer/Platforms'
        #    '/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System'
        #    '/Library/Frameworks/Tcl.framework',
        #  '/Applications/Xcode.app/Contents/Developer/Platforms'
        #    '/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System'
        #    '/Library/Frameworks/Tcl.framework/Versions'
        #    '/Current',
        for p in ['/usr/local/opt/tcl-tk/lib']:
            if os.path.exists(os.path.join(p, 'tclConfig.sh')):
                configure.append('--with-tcl=' + p)
                break

    with CurrentWorkingDir(os.path.join(root, 'lib', 'tclparser')):
        CheckCall(configure)
        CheckCall(['make'])

    MakeSymlink(name, root)
Example #3
0
def FindExecutable(executable: str, paths=None):
    if not paths:
        paths = GetPATHAsList()

    if install.GetOS() == 'windows':
        extensions = ['.exe', '.bat', '.cmd']
    else:
        extensions = ['']

    for extension in extensions:
        if executable.endswith(extension):
            candidate = executable
        else:
            candidate = executable + extension

        for path in paths:
            filename = os.path.abspath(os.path.join(path, candidate))
            if not os.path.isfile(filename):
                continue
            if not os.access(filename, os.F_OK | os.X_OK):
                continue

            return filename

    raise MissingExecutable(
        f"Unable to find executable { executable } in path")
Example #4
0
    def _CreateBuffer(self,
                      category,
                      file_name=None,
                      cmd=None,
                      completion_handler=None,
                      syntax=None):

        buf_to_delete = None
        if (not self._buffers and self._window is not None
                and self._window.valid and not self._window.buffer.name):
            # If there's an empty buffer in the current window that we're not using,
            # delete it. We could try and use it, but that complicates the call to
            # SetUpCommandBuffer
            buf_to_delete = self._window.buffer

        if file_name is not None:
            assert cmd is None
            if install.GetOS() == "windows":
                # FIXME: Can't display fiels in windows (yet?)
                return

            cmd = ['tail', '-F', '-n', '+1', '--', file_name]

        if cmd is not None:
            out = utils.SetUpCommandBuffer(
                cmd,
                category,
                self._api_prefix,
                completion_handler=completion_handler)

            self._buffers[category] = TabBuffer(out, len(self._buffers))
            self._buffers[category].is_job = True
            self._RenderWinBar(category)
        else:
            if category == 'Console':
                name = 'vimspector.Console'
            else:
                name = 'vimspector.Output:{0}'.format(category)

            tab_buffer = TabBuffer(utils.NewEmptyBuffer(), len(self._buffers))

            self._buffers[category] = tab_buffer

            if category == 'Console':
                utils.SetUpPromptBuffer(tab_buffer.buf, name, '> ',
                                        'vimspector#EvaluateConsole',
                                        'vimspector#OmniFuncConsole')
            else:
                utils.SetUpHiddenBuffer(tab_buffer.buf, name)

            self._RenderWinBar(category)

        self._buffers[category].syntax = utils.SetSyntax(
            self._buffers[category].syntax, syntax,
            self._buffers[category].buf)

        if buf_to_delete:
            with utils.RestoreCurrentWindow():
                self._ShowOutput(category)
            utils.CleanUpHiddenBuffer(buf_to_delete)
Example #5
0
def InstallCppTools( name, root, gadget ):
  extension = os.path.join( root, 'extension' )

  # It's hilarious, but the execute bits aren't set in the vsix. So they
  # actually have javascript code which does this. It's just a horrible horrible
  # hack that really is not funny.
  for binary in [ 'OpenDebugAD7', 'OpenDebugAD7.exe' ]:
    path = os.path.join( extension, 'debugAdapters', 'bin', binary )
    if os.path.exists( path ):
      MakeExecutable( path )

  # See makeBinariesExecutable from the cpptools extension code:
  # https://github.com/microsoft/vscode-cpptools/blob/main/Extension/src/main.ts#L97

  if install.GetOS() == 'macos':
    MakeExecutable( os.path.join( extension,
                                  'debugAdapters',
                                  'lldb-mi',
                                  'bin',
                                  'lldb-mi' ) )
    if install.GetPlatform() == 'x86_64':
      for binary in [ "debugserver",
                      "lldb-mi",
                      "lldb-argdumper",
                      "lldb-launcher" ]:
        MakeExecutable( os.path.join( extension,
                                      'debugAdapters',
                                      'bin',
                                      binary ) )

  MakeExtensionSymlink( name, root )
Example #6
0
  def __init__( self, api_prefix ):
    self._logger = logging.getLogger( __name__ )
    utils.SetUpLogging( self._logger )

    self._api_prefix = api_prefix

    self._logger.info( "**** INITIALISING NEW VIMSPECTOR SESSION ****" )
    self._logger.info( "API is: {}".format( api_prefix ) )
    self._logger.info( 'VIMSPECTOR_HOME = %s', VIMSPECTOR_HOME )
    self._logger.info( 'gadgetDir = %s',
                       install.GetGadgetDir( VIMSPECTOR_HOME,
                                             install.GetOS() ) )

    self._uiTab = None
    self._stackTraceView = None
    self._variablesView = None
    self._outputView = None
    self._breakpoints = breakpoints.ProjectBreakpoints()
    self._splash_screen = None

    self._run_on_server_exit = None

    self._configuration = None
    self._adapter = None

    self._ResetServerState()
Example #7
0
def PathToAnyWorkingPython3():
    # We can't rely on sys.executable because it's usually 'vim' (fixme, not with
    # neovim?)
    paths = os.environ['PATH'].split(os.pathsep)

    if install.GetOS() == 'windows':
        paths.insert(0, os.getcwd())
        candidates = [
            os.path.join(sys.exec_prefix, 'python.exe'), 'python.exe'
        ]
    else:
        candidates = [
            os.path.join(sys.exec_prefix, 'bin', 'python3'), 'python3',
            'python'
        ]

    for candidate in candidates:
        for path in paths:
            filename = os.path.abspath(os.path.join(path, candidate))
            if not os.path.isfile(filename):
                continue
            if not os.access(filename, os.F_OK | os.X_OK):
                continue

            return filename

    raise RuntimeError("Unable to find a working python3")
Example #8
0
def FindGadgetForAdapter(adapter_name):
    candidates = []
    for name, gadget in gadgets.GADGETS.items():
        v = {}
        v.update(gadget.get('all', {}))
        v.update(gadget.get(install.GetOS(), {}))

        adapters = {}
        adapters.update(v.get('adapters', {}))
        adapters.update(gadget.get('adapters', {}))

        if adapter_name in adapters:
            candidates.append(name)

    return candidates
Example #9
0
  def _CreateBuffer( self,
                     category,
                     file_name = None,
                     cmd = None,
                     completion_handler = None,
                     syntax = None ):
    if file_name is not None:
      assert cmd is None
      if install.GetOS() == "windows":
        # FIXME: Can't display fiels in windows (yet?)
        return

      cmd = [ 'tail', '-F', '-n', '+1', '--', file_name ]

    if cmd is not None:
      out = utils.SetUpCommandBuffer(
        cmd,
        category,
        self._api_prefix,
        completion_handler = completion_handler )
      self._buffers[ category ] = TabBuffer( out, len( self._buffers ) )
      self._buffers[ category ].is_job = True
      self._RenderWinBar( category )
    else:
      if category == 'Console':
        name = 'vimspector.Console'
      else:
        name = 'vimspector.Output:{0}'.format( category )

      tab_buffer = TabBuffer( utils.NewEmptyBuffer(), len( self._buffers ) )
      self._buffers[ category ] = tab_buffer

      if category == 'Console':
        utils.SetUpPromptBuffer( tab_buffer.buf,
                                 name,
                                 '> ',
                                 'vimspector#EvaluateConsole' )
      else:
        utils.SetUpHiddenBuffer( tab_buffer.buf, name )

      self._RenderWinBar( category )

    self._buffers[ category ].syntax = utils.SetSyntax(
      self._buffers[ category ].syntax,
      syntax,
      self._buffers[ category ].buf )
Example #10
0
    def __init__(self):
        self._logger = logging.getLogger(__name__)
        utils.SetUpLogging(self._logger)

        self._logger.info('VIMSPECTOR_HOME = %s', VIMSPECTOR_HOME)
        self._logger.info(
            'gadgetDir = %s',
            install.GetGadgetDir(VIMSPECTOR_HOME, install.GetOS()))

        self._uiTab = None
        self._stackTraceView = None
        self._variablesView = None
        self._outputView = None
        self._breakpoints = breakpoints.ProjectBreakpoints()

        self._run_on_server_exit = None

        self._ResetServerState()
Example #11
0
def MakeSymlink(in_folder, link, pointing_to):
    RemoveIfExists(os.path.join(in_folder, link))

    in_folder = os.path.abspath(in_folder)
    pointing_to_relative = os.path.relpath(os.path.abspath(pointing_to),
                                           in_folder)
    link_path = os.path.join(in_folder, link)

    if install.GetOS() == 'windows':
        # While symlinks do exist on Windows, they require elevated privileges, so
        # let's use a directory junction which is all we need.
        link_path = os.path.abspath(link_path)
        if os.path.isdir(link_path):
            os.rmdir(link_path)
        subprocess.check_call(
            ['cmd.exe', '/c', 'mklink', '/J', link_path, pointing_to])
    else:
        os.symlink(pointing_to_relative, link_path)
Example #12
0
def SetUpDebugpy(wait=False, port=5678):
    sys.path.insert(
        1,
        os.path.join(
            install.GetGadgetDir(utils.GetVimspectorBase(), install.GetOS()),
            'debugpy', 'build', 'lib'))
    import debugpy

    exe = sys.executable
    try:
        # debugpy uses sys.executable (which is `vim`, so we hack it)
        sys.executable = 'python3'
        debugpy.listen(port)
    finally:
        sys.executable = exe

    if wait:
        debugpy.wait_for_client()
Example #13
0
    def _CreateBuffer(self, category, file_name=None, cmd=None):
        win = self._window
        if not win.valid:
            # We need to borrow the current window
            win = vim.current.window

        with utils.LetCurrentWindow(win):
            with utils.RestoreCurrentBuffer(win):

                if file_name is not None:
                    assert cmd is None
                    if install.GetOS() == "windows":
                        # FIXME: Can't display fiels in windows (yet?)
                        return

                    cmd = ['tail', '-F', '-n', '+1', '--', file_name]

                if cmd is not None:
                    out, err = utils.SetUpCommandBuffer(
                        cmd, category, self._api_prefix)
                    self._buffers[category + '-out'] = TabBuffer(
                        out, len(self._buffers))
                    self._buffers[category + '-out'].is_job = True
                    self._buffers[category + '-out'].job_category = category
                    self._buffers[category + '-err'] = TabBuffer(
                        err, len(self._buffers))
                    self._buffers[category + '-err'].is_job = False
                    self._RenderWinBar(category + '-out')
                    self._RenderWinBar(category + '-err')
                else:
                    vim.command('enew')
                    tab_buffer = TabBuffer(vim.current.buffer,
                                           len(self._buffers))
                    self._buffers[category] = tab_buffer
                    if category == 'Console':
                        utils.SetUpPromptBuffer(tab_buffer.buf,
                                                'vimspector.Console', '> ',
                                                'vimspector#EvaluateConsole')
                    else:
                        utils.SetUpHiddenBuffer(
                            tab_buffer.buf,
                            'vimspector.Output:{0}'.format(category))

                    self._RenderWinBar(category)
Example #14
0
def PathToAnyWorkingPython3():
  # We can't rely on sys.executable because it's usually 'vim' (fixme, not with
  # neovim?)
  paths = GetPATHAsList()

  if install.GetOS() == 'windows':
    candidates = [ os.path.join( sys.exec_prefix, 'python.exe' ),
                   'python.exe' ]
  else:
    candidates = [ os.path.join( sys.exec_prefix, 'bin', 'python3' ),
                   'python3',
                   'python' ]

  for candidate in candidates:
    try:
      return FindExecutable( candidate, paths=paths )
    except MissingExecutable:
      pass

  raise RuntimeError( "Unable to find a working python3" )
Example #15
0
def MakeSymlink(link, pointing_to, in_folder=None):
    if not in_folder:
        in_folder = install.GetGadgetDir(options.vimspector_base)

    RemoveIfExists(os.path.join(in_folder, link))

    in_folder = os.path.abspath(in_folder)
    pointing_to_relative = os.path.relpath(os.path.abspath(pointing_to),
                                           in_folder)
    link_path = os.path.join(in_folder, link)

    if install.GetOS() == 'windows':
        # While symlinks do exist on Windows, they require elevated privileges, so
        # let's use a directory junction which is all we need.
        link_path = os.path.abspath(link_path)
        if os.path.isdir(link_path):
            os.rmdir(link_path)
        CheckCall(['cmd.exe', '/c', 'mklink', '/J', link_path, pointing_to])
    else:
        os.symlink(pointing_to_relative, link_path)
    def Start(self, launch_variables=None):
        # We mutate launch_variables, so don't mutate the default argument.
        # https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments
        if launch_variables is None:
            launch_variables = {}

        self._logger.info("User requested start debug session with %s",
                          launch_variables)
        self._configuration = None
        self._adapter = None

        current_file = utils.GetBufferFilepath(vim.current.buffer)
        filetypes = utils.GetBufferFiletypes(vim.current.buffer)
        configurations = {}
        adapters = {}

        glob.glob(install.GetGadgetDir(VIMSPECTOR_HOME, install.GetOS()))
        for gadget_config_file in PathsToAllGadgetConfigs(
                VIMSPECTOR_HOME, current_file):
            self._logger.debug(f'Reading gadget config: {gadget_config_file}')
            if not gadget_config_file or not os.path.exists(
                    gadget_config_file):
                continue

            with open(gadget_config_file, 'r') as f:
                adapters.update(json.load(f).get('adapters') or {})

        for launch_config_file in PathsToAllConfigFiles(
                VIMSPECTOR_HOME, current_file, filetypes):
            self._logger.debug(
                f'Reading configurations from: {launch_config_file}')
            if not launch_config_file or not os.path.exists(
                    launch_config_file):
                continue

            with open(launch_config_file, 'r') as f:
                database = json.load(f)
                adapters.update(database.get('adapters') or {})
                configurations.update(database.get('configurations' or {}))

        if not configurations:
            utils.UserMessage('Unable to find any debug configurations. '
                              'You need to tell vimspector how to launch your '
                              'application.')
            return

        if 'configuration' in launch_variables:
            configuration_name = launch_variables.pop('configuration')
        elif len(configurations) == 1:
            configuration_name = next(iter(configurations.keys()))
        else:
            configuration_name = utils.SelectFromList(
                'Which launch configuration?', sorted(configurations.keys()))

        if not configuration_name or configuration_name not in configurations:
            return

        if launch_config_file:
            self._workspace_root = os.path.dirname(launch_config_file)
        else:
            self._workspace_root = os.path.dirname(current_file)

        configuration = configurations[configuration_name]
        adapter = configuration.get('adapter')
        if isinstance(adapter, str):
            adapter = adapters.get(adapter)

        # TODO: Do we want some form of persistence ? e.g. self._staticVariables,
        # set from an api call like SetLaunchParam( 'var', 'value' ), perhaps also a
        # way to load .vimspector.local.json which just sets variables
        #
        # Additional vars as defined by VSCode:
        #
        # ${workspaceFolder} - the path of the folder opened in VS Code
        # ${workspaceFolderBasename} - the name of the folder opened in VS Code
        #                              without any slashes (/)
        # ${file} - the current opened file
        # ${relativeFile} - the current opened file relative to workspaceFolder
        # ${fileBasename} - the current opened file's basename
        # ${fileBasenameNoExtension} - the current opened file's basename with no
        #                              file extension
        # ${fileDirname} - the current opened file's dirname
        # ${fileExtname} - the current opened file's extension
        # ${cwd} - the task runner's current working directory on startup
        # ${lineNumber} - the current selected line number in the active file
        # ${selectedText} - the current selected text in the active file
        # ${execPath} - the path to the running VS Code executable

        def relpath(p, relative_to):
            if not p:
                return ''
            return os.path.relpath(p, relative_to)

        def splitext(p):
            if not p:
                return ['', '']
            return os.path.splitext(p)

        self._variables = {
            'dollar': '$',  # HACK. Hote '$$' also works.
            'workspaceRoot': self._workspace_root,
            'workspaceFolder': self._workspace_root,
            'gadgetDir': install.GetGadgetDir(VIMSPECTOR_HOME,
                                              install.GetOS()),
            'file': current_file,
            'relativeFile': relpath(current_file, self._workspace_root),
            'fileBasename': os.path.basename(current_file),
            'fileBasenameNoExtension':
            splitext(os.path.basename(current_file))[0],
            'fileDirname': os.path.dirname(current_file),
            'fileExtname': splitext(os.path.basename(current_file))[1],
            # NOTE: this is the window-local cwd for the current window, *not* Vim's
            # working directory.
            'cwd': os.getcwd(),
        }

        # Pretend that vars passed to the launch command were typed in by the user
        # (they may have been in theory)
        USER_CHOICES.update(launch_variables)
        self._variables.update(launch_variables)

        self._variables.update(
            utils.ParseVariables(adapter.get('variables', {}), self._variables,
                                 USER_CHOICES))
        self._variables.update(
            utils.ParseVariables(configuration.get('variables', {}),
                                 self._variables, USER_CHOICES))

        utils.ExpandReferencesInDict(configuration, self._variables,
                                     USER_CHOICES)
        utils.ExpandReferencesInDict(adapter, self._variables, USER_CHOICES)

        if not adapter:
            utils.UserMessage(
                'No adapter configured for {}'.format(configuration_name),
                persist=True)
            return

        self._StartWithConfiguration(configuration, adapter)
Example #17
0
        if 'do' in gadget:
            gadget['do'](name, root, v)
        else:
            installer.MakeExtensionSymlink(vimspector_base, name, root)

        all_adapters.update(gadget.get('adapters', {}))

        print("Done installing {}".format(name))
    except Exception as e:
        traceback.print_exc()
        failed.append(name)
        print("FAILED installing {}: {}".format(name, e))


vimspector_base = os.path.dirname(__file__)
OS = install.GetOS()
gadget_dir = install.GetGadgetDir(vimspector_base, OS)

print('OS = ' + OS)
print('gadget_dir = ' + gadget_dir)

parser = argparse.ArgumentParser(
    formatter_class=argparse.RawDescriptionHelpFormatter,
    description='Install DAP Servers for use with Vimspector.',
    epilog="""
    If you're not sure, normally --all is enough to get started.

    Custom server definitions can be defined in JSON files, allowing
    installation of arbitrary servers packaged in one of the ways that this
    installer understands.
Example #18
0
  def Start( self, launch_variables = None ):
    # We mutate launch_variables, so don't mutate the default argument.
    # https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments
    if launch_variables is None:
      launch_variables = {}

    self._logger.info( "User requested start debug session with %s",
                       launch_variables )
    self._configuration = None
    self._adapter = None

    current_file = utils.GetBufferFilepath( vim.current.buffer )
    filetypes = utils.GetBufferFiletypes( vim.current.buffer )
    configurations = {}
    adapters = {}

    glob.glob( install.GetGadgetDir( VIMSPECTOR_HOME, install.GetOS() ) )
    for gadget_config_file in PathsToAllGadgetConfigs( VIMSPECTOR_HOME,
                                                       current_file ):
      self._logger.debug( f'Reading gadget config: {gadget_config_file}' )
      if not gadget_config_file or not os.path.exists( gadget_config_file ):
        continue

      with open( gadget_config_file, 'r' ) as f:
        a =  json.loads( minify( f.read() ) ).get( 'adapters' ) or {}
        adapters.update( a )

    for launch_config_file in PathsToAllConfigFiles( VIMSPECTOR_HOME,
                                                     current_file,
                                                     filetypes ):
      self._logger.debug( f'Reading configurations from: {launch_config_file}' )
      if not launch_config_file or not os.path.exists( launch_config_file ):
        continue

      with open( launch_config_file, 'r' ) as f:
        database = json.loads( minify( f.read() ) )
        adapters.update( database.get( 'adapters' ) or {} )
        configurations.update( database.get( 'configurations' or {} ) )

    if not configurations:
      utils.UserMessage( 'Unable to find any debug configurations. '
                         'You need to tell vimspector how to launch your '
                         'application.' )
      return

    if 'configuration' in launch_variables:
      configuration_name = launch_variables.pop( 'configuration' )
    elif ( len( configurations ) == 1 and
           next( iter( configurations.values() ) ).get( "autoselect", True ) ):
      configuration_name = next( iter( configurations.keys() ) )
    else:
      # Find a single configuration with 'default' True and autoselect not False
      defaults = { n: c for n, c in configurations.items()
                   if c.get( 'default', False ) is True
                   and c.get( 'autoselect', True ) is not False }

      if len( defaults ) == 1:
        configuration_name = next( iter( defaults.keys() ) )
      else:
        configuration_name = utils.SelectFromList(
          'Which launch configuration?',
          sorted( configurations.keys() ) )

    if not configuration_name or configuration_name not in configurations:
      return

    if launch_config_file:
      self._workspace_root = os.path.dirname( launch_config_file )
    else:
      self._workspace_root = os.path.dirname( current_file )

    configuration = configurations[ configuration_name ]
    adapter = configuration.get( 'adapter' )
    if isinstance( adapter, str ):
      adapter_dict = adapters.get( adapter )

      if adapter_dict is None:
        utils.UserMessage( f"The specified adapter '{adapter}' is not "
                           "available. Did you forget to run "
                           "'install_gadget.py'?",
                           persist = True,
                           error = True )
        return

      adapter = adapter_dict

    # Additional vars as defined by VSCode:
    #
    # ${workspaceFolder} - the path of the folder opened in VS Code
    # ${workspaceFolderBasename} - the name of the folder opened in VS Code
    #                              without any slashes (/)
    # ${file} - the current opened file
    # ${relativeFile} - the current opened file relative to workspaceFolder
    # ${fileBasename} - the current opened file's basename
    # ${fileBasenameNoExtension} - the current opened file's basename with no
    #                              file extension
    # ${fileDirname} - the current opened file's dirname
    # ${fileExtname} - the current opened file's extension
    # ${cwd} - the task runner's current working directory on startup
    # ${lineNumber} - the current selected line number in the active file
    # ${selectedText} - the current selected text in the active file
    # ${execPath} - the path to the running VS Code executable

    def relpath( p, relative_to ):
      if not p:
        return ''
      return os.path.relpath( p, relative_to )

    def splitext( p ):
      if not p:
        return [ '', '' ]
      return os.path.splitext( p )

    variables = {
      'dollar': '$', # HACK. Hote '$$' also works.
      'workspaceRoot': self._workspace_root,
      'workspaceFolder': self._workspace_root,
      'gadgetDir': install.GetGadgetDir( VIMSPECTOR_HOME, install.GetOS() ),
      'file': current_file,
    }

    calculus = {
      'relativeFile': lambda: relpath( current_file,
                                       self._workspace_root ),
      'fileBasename': lambda: os.path.basename( current_file ),
      'fileBasenameNoExtension':
        lambda: splitext( os.path.basename( current_file ) )[ 0 ],
      'fileDirname': lambda: os.path.dirname( current_file ),
      'fileExtname': lambda: splitext( os.path.basename( current_file ) )[ 1 ],
      # NOTE: this is the window-local cwd for the current window, *not* Vim's
      # working directory.
      'cwd': os.getcwd,
      'unusedLocalPort': utils.GetUnusedLocalPort,
    }

    # Pretend that vars passed to the launch command were typed in by the user
    # (they may have been in theory)
    USER_CHOICES.update( launch_variables )
    variables.update( launch_variables )

    try:
      variables.update(
        utils.ParseVariables( adapter.get( 'variables', {} ),
                              variables,
                              calculus,
                              USER_CHOICES ) )
      variables.update(
        utils.ParseVariables( configuration.get( 'variables', {} ),
                              variables,
                              calculus,
                              USER_CHOICES ) )


      utils.ExpandReferencesInDict( configuration,
                                    variables,
                                    calculus,
                                    USER_CHOICES )
      utils.ExpandReferencesInDict( adapter,
                                    variables,
                                    calculus,
                                    USER_CHOICES )
    except KeyboardInterrupt:
      self._Reset()
      return

    if not adapter:
      utils.UserMessage( 'No adapter configured for {}'.format(
        configuration_name ), persist=True )
      return

    self._StartWithConfiguration( configuration, adapter )
Example #19
0
  def Start( self, launch_variables = {} ):
    self._logger.info( "User requested start debug session with %s",
                       launch_variables )
    self._configuration = None
    self._adapter = None

    launch_config_file = utils.PathToConfigFile( '.vimspector.json' )

    if not launch_config_file:
      utils.UserMessage( 'Unable to find .vimspector.json. You need to tell '
                         'vimspector how to launch your application' )
      return

    with open( launch_config_file, 'r' ) as f:
      database = json.load( f )

    configurations = database.get( 'configurations' )
    adapters = {}

    for gadget_config_file in [ install.GetGadgetConfigFile( VIMSPECTOR_HOME ),
                                utils.PathToConfigFile( '.gadgets.json' ) ]:
      if gadget_config_file and os.path.exists( gadget_config_file ):
        with open( gadget_config_file, 'r' ) as f:
          adapters.update( json.load( f ).get( 'adapters' ) or {} )

    adapters.update( database.get( 'adapters' ) or {} )

    if len( configurations ) == 1:
      configuration_name = next( iter( configurations.keys() ) )
    else:
      configuration_name = utils.SelectFromList(
        'Which launch configuration?',
        sorted( list( configurations.keys() ) ) )

    if not configuration_name or configuration_name not in configurations:
      return

    self._workspace_root = os.path.dirname( launch_config_file )

    configuration = configurations[ configuration_name ]
    adapter = configuration.get( 'adapter' )
    if isinstance( adapter, str ):
      adapter = adapters.get( adapter )

    # TODO: Do we want some form of persistence ? e.g. self._staticVariables,
    # set from an api call like SetLaunchParam( 'var', 'value' ), perhaps also a
    # way to load .vimspector.local.json which just sets variables
    #
    # Additional vars as defined by VSCode:
    #
    # ${workspaceFolder} - the path of the folder opened in VS Code
    # ${workspaceFolderBasename} - the name of the folder opened in VS Code
    #                              without any slashes (/)
    # ${file} - the current opened file
    # ${relativeFile} - the current opened file relative to workspaceFolder
    # ${fileBasename} - the current opened file's basename
    # ${fileBasenameNoExtension} - the current opened file's basename with no
    #                              file extension
    # ${fileDirname} - the current opened file's dirname
    # ${fileExtname} - the current opened file's extension
    # ${cwd} - the task runner's current working directory on startup
    # ${lineNumber} - the current selected line number in the active file
    # ${selectedText} - the current selected text in the active file
    # ${execPath} - the path to the running VS Code executable

    current_file = utils.GetBufferFilepath( vim.current.buffer )

    self._variables = {
      'dollar': '$', # HACK. Hote '$$' also works.
      'workspaceRoot': self._workspace_root,
      'workspaceFolder': self._workspace_root,
      'gadgetDir': install.GetGadgetDir( VIMSPECTOR_HOME, install.GetOS() ),
      'file': current_file,
      'relativeFile': os.path.relpath( current_file, self._workspace_root ),
      'fileBasename': os.path.basename( current_file ),
      'fileBasenameNoExtension':
        os.path.splitext( os.path.basename( current_file ) )[ 0 ],
      'fileDirname': os.path.dirname( current_file ),
      'fileExtname':
        os.path.splitext( os.path.basename( current_file ) )[ 1 ],
      'cwd': os.getcwd(),
    }
    self._variables.update(
      utils.ParseVariables( adapter.get( 'variables', {} ),
                            self._variables ) )
    self._variables.update(
      utils.ParseVariables( configuration.get( 'variables', {} ),
                            self._variables ) )
    self._variables.update( launch_variables )

    utils.ExpandReferencesInDict( configuration, self._variables )
    utils.ExpandReferencesInDict( adapter, self._variables )

    if not adapter:
      utils.UserMessage( 'No adapter configured for {}'.format(
        configuration_name ), persist=True )
      return

    self._StartWithConfiguration( configuration, adapter )
Example #20
0
def MakeExtensionSymlink( vimspector_base, name, root ):
  MakeSymlink( install.GetGadgetDir( vimspector_base,
                                     install.GetOS() ),
               name,
               os.path.join( root, 'extension' ) ),
Example #21
0
def GetPATHAsList():
    paths = os.environ['PATH'].split(os.pathsep)
    if install.GetOS() == 'windows':
        paths.insert(0, os.getcwd())
    return paths
Example #22
0
def InstallGagdet(name: str, gadget: dict, manifest: Manifest, succeeded: list,
                  failed: list, all_adapters: dict):

    try:
        # Spec is an os-specific definition of the gadget
        spec = {}
        spec.update(gadget.get('all', {}))
        spec.update(gadget.get(install.GetOS(), {}))

        def save_adapters():
            # allow per-os adapter overrides. v already did that for us...
            all_adapters.update(spec.get('adapters', {}))
            # add any other "all" adapters
            all_adapters.update(gadget.get('adapters', {}))

        if 'download' in gadget:
            if 'file_name' not in spec:
                raise RuntimeError("Unsupported OS {} for gadget {}".format(
                    install.GetOS(), name))

            print(f"Installing {name}@{spec[ 'version' ]}...")
            spec['download'] = gadget['download']
            if not manifest.RequiresUpdate(name, spec):
                save_adapters()
                print(" - Skip - up to date")
                return

            destination = os.path.join(
                install.GetGadgetDir(options.vimspector_base), 'download',
                name, spec['version'])

            url = string.Template(gadget['download']['url']).substitute(spec)

            file_path = DownloadFileTo(
                url,
                destination,
                file_name=gadget['download'].get('target'),
                checksum=spec.get('checksum'),
                check_certificate=not options.no_check_certificate)

            root = os.path.join(destination, 'root')
            ExtractZipTo(file_path,
                         root,
                         format=gadget['download'].get('format', 'zip'))
        elif 'repo' in gadget:
            url = string.Template(gadget['repo']['url']).substitute(spec)
            ref = string.Template(gadget['repo']['ref']).substitute(spec)

            print(f"Installing {name}@{ref}...")
            spec['repo'] = gadget['repo']
            if not manifest.RequiresUpdate(name, spec):
                save_adapters()
                print(" - Skip - up to date")
                return

            destination = os.path.join(
                install.GetGadgetDir(options.vimspector_base), 'download',
                name)
            CloneRepoTo(url, ref, destination)
            root = destination

        if 'do' in gadget:
            gadget['do'](name, root, spec)
        else:
            InstallGeneric(name, root, spec)

        save_adapters()
        manifest.Update(name, spec)
        succeeded.append(name)
        print(f" - Done installing {name}")
    except Exception as e:
        if not options.quiet:
            traceback.print_exc()
        failed.append(name)
        print(f" - FAILED installing {name}: {e}".format(name, e))
Example #23
0
    def Start(self, launch_variables={}):
        self._configuration = None
        self._adapter = None

        launch_config_file = utils.PathToConfigFile('.vimspector.json')

        if not launch_config_file:
            utils.UserMessage(
                'Unable to find .vimspector.json. You need to tell '
                'vimspector how to launch your application')
            return

        with open(launch_config_file, 'r') as f:
            database = json.load(f)

        configurations = database.get('configurations')
        adapters = {}

        for gadget_config_file in [
                install.GetGadgetConfigFile(VIMSPECTOR_HOME),
                utils.PathToConfigFile('.gadgets.json')
        ]:
            if gadget_config_file and os.path.exists(gadget_config_file):
                with open(gadget_config_file, 'r') as f:
                    adapters.update(json.load(f).get('adapters') or {})

        adapters.update(database.get('adapters') or {})

        if len(configurations) == 1:
            configuration_name = next(iter(configurations.keys()))
        else:
            configuration_name = utils.SelectFromList(
                'Which launch configuration?',
                sorted(list(configurations.keys())))

        if not configuration_name or configuration_name not in configurations:
            return

        self._workspace_root = os.path.dirname(launch_config_file)

        configuration = configurations[configuration_name]
        adapter = configuration.get('adapter')
        if isinstance(adapter, str):
            adapter = adapters.get(adapter)

        # TODO: Do we want some form of persistence ? e.g. self._staticVariables,
        # set from an api call like SetLaunchParam( 'var', 'value' ), perhaps also a
        # way to load .vimspector.local.json which just sets variables
        self._variables = {
            'dollar': '$',  # HACK. Hote '$$' also works.
            'workspaceRoot': self._workspace_root,
            'gadgetDir': install.GetGadgetDir(VIMSPECTOR_HOME, install.GetOS())
        }
        self._variables.update(
            utils.ParseVariables(adapter.get('variables', {})))
        self._variables.update(
            utils.ParseVariables(configuration.get('variables', {})))
        self._variables.update(launch_variables)

        utils.ExpandReferencesInDict(configuration, self._variables)
        utils.ExpandReferencesInDict(adapter, self._variables)

        if not adapter:
            utils.UserMessage(
                'No adapter configured for {}'.format(configuration_name),
                persist=True)
            return

        self._StartWithConfiguration(configuration, adapter)