Add ability to specify defaults for variables
This commit is contained in:
parent
9f57cb0042
commit
aa26d4bc1a
4 changed files with 143 additions and 8 deletions
|
|
@ -12,6 +12,7 @@ for Vimspector.
|
|||
* [Debug profile configuration](#debug-profile-configuration)
|
||||
* [Replacements and variables](#replacements-and-variables)
|
||||
* [The splat operator](#the-splat-operator)
|
||||
* [Default values](#default-values)
|
||||
* [Configuration Format](#configuration-format)
|
||||
* [Files and locations](#files-and-locations)
|
||||
* [Adapter configurations](#adapter-configurations)
|
||||
|
|
@ -28,7 +29,7 @@ for Vimspector.
|
|||
* [Appendix: Configuration file format](#appendix-configuration-file-format)
|
||||
* [Appendix: Editor configuration](#appendix-editor-configuration)
|
||||
|
||||
<!-- Added by: ben, at: Sun 12 Jul 2020 16:46:18 BST -->
|
||||
<!-- Added by: ben, at: Fri 31 Jul 2020 22:13:39 BST -->
|
||||
|
||||
<!--te-->
|
||||
|
||||
|
|
@ -204,6 +205,37 @@ You can also combine with static values:
|
|||
This would yield the intuitive result:
|
||||
`[ "First", "one", "two three", "four", "Last" ]`
|
||||
|
||||
### Default values
|
||||
|
||||
You can specify replacesments with default values. In this case if the user has
|
||||
not specified a value, they are prompted but with the default value
|
||||
pre-populated, allowing them to just press return to accept the default.
|
||||
|
||||
The syntax is `${variableName:default value}`. The default value can contain any
|
||||
character, but to include a `}` you must escape it with a backslash. To include
|
||||
a backslash in the JSON you must write `\\`, as in:
|
||||
|
||||
```json
|
||||
{ "key": "${value:default {\\} stuff}" }
|
||||
```
|
||||
|
||||
The default value can also be a replacement variable. However, this _must_ be a
|
||||
veriable that's already defined, such as one of the [predefined
|
||||
variables](#predefined-variables), or one speified in a `variables` block. In
|
||||
order to reference them, you _must_ use `${var}` syntax and you _must_ escape
|
||||
the closing `}`. For example, the is a common and useful case:
|
||||
|
||||
```json
|
||||
{
|
||||
"configuration": {
|
||||
"program": "${script:${file\\}}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This will prompt the user to specify `script`, but it will default to the path
|
||||
to the current file.
|
||||
|
||||
## Configuration Format
|
||||
|
||||
All Vimspector configuration is defined in a JSON object. The complete
|
||||
|
|
|
|||
25
docs/custom_gadget_file.md
Normal file
25
docs/custom_gadget_file.md
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
title: Configuration
|
||||
---
|
||||
|
||||
This document describes how to use vimspector's `install_gadget.py` to install
|
||||
custom debug adapters. This can be useful as a way to get an adapter working
|
||||
that isn't officially supported by Vimspector, but otherwise can be made to work
|
||||
by simply downloading the VScode extension into the gadget directory.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
./install_gadget.py --enable-custom=/path/to/a.json \
|
||||
--enable-custom=/path/to/b.json`
|
||||
```
|
||||
|
||||
This tells `install_gadget.py` to read `a.json` and `b.json` as _gadget
|
||||
definitions_ and download/unpack the specified gadgets into the gadget dir, just
|
||||
like the supported adapters.
|
||||
|
||||
## Gadget Definitions
|
||||
|
||||
A _gadget definition_ is a file containing a single JSON object definition,
|
||||
describing the debug adapter and how to download and install it. This mechanism
|
||||
is crude but can be effective.
|
||||
|
|
@ -19,11 +19,11 @@ import os
|
|||
import contextlib
|
||||
import vim
|
||||
import json
|
||||
import string
|
||||
import functools
|
||||
import subprocess
|
||||
import shlex
|
||||
import collections
|
||||
import re
|
||||
|
||||
|
||||
LOG_FILE = os.path.expanduser( os.path.join( '~', '.vimspector.log' ) )
|
||||
|
|
@ -435,6 +435,60 @@ def ExpandReferencesInObject( obj, mapping, calculus, user_choices ):
|
|||
return obj
|
||||
|
||||
|
||||
# Based on the python standard library string.Template().substitue, enhanced to
|
||||
# add ${name:default} parsing, and to remove the unnecessary generality.
|
||||
VAR_MATCH = re.compile(
|
||||
r"""
|
||||
\$(?: # A dollar, followed by...
|
||||
(?P<escaped>\$) | # Another doller = escaped
|
||||
(?P<named>[_a-z][_a-z0-9]*) | # or An identifier - named param
|
||||
{(?P<braced>[_a-z][_a-z0-9]*)} | # or An {identifier} - braced param
|
||||
{(?P<braceddefault> # or An {id:default} - default param, as
|
||||
(?P<defname>[_a-z][a-z0-9]*) # an ID
|
||||
: # then a colon
|
||||
(?P<default>(?:[^}]|\})*) # then anything up to }, or a \}
|
||||
)} | #
|
||||
(?P<invalid>) # or Something else - invalid
|
||||
)
|
||||
""",
|
||||
re.IGNORECASE | re.VERBOSE )
|
||||
|
||||
|
||||
class MissingSubstitution( Exception ):
|
||||
def __init__( self, name, default_value = None ):
|
||||
self.name = name
|
||||
self.default_value = default_value
|
||||
|
||||
|
||||
def _Substitute( template, mapping ):
|
||||
def convert( mo ):
|
||||
# Check the most common path first.
|
||||
named = mo.group( 'named' ) or mo.group( 'braced' )
|
||||
if named is not None:
|
||||
if named not in mapping:
|
||||
raise MissingSubstitution( named )
|
||||
return str( mapping[ named ] )
|
||||
|
||||
if mo.group( 'escaped' ) is not None:
|
||||
return '$'
|
||||
|
||||
if mo.group( 'braceddefault' ) is not None:
|
||||
named = mo.group( 'defname' )
|
||||
if named not in mapping:
|
||||
''
|
||||
raise MissingSubstitution(
|
||||
named,
|
||||
mo.group( 'default' ).replace( '\\}', '}' ) )
|
||||
return str( mapping[ named ] )
|
||||
|
||||
if mo.group( 'invalid' ) is not None:
|
||||
raise ValueError( f"Invalid placeholder in string { template }" )
|
||||
|
||||
raise ValueError( 'Unrecognized named group in pattern', VAR_MATCH )
|
||||
|
||||
return VAR_MATCH.sub( convert, template )
|
||||
|
||||
|
||||
def ExpandReferencesInString( orig_s,
|
||||
mapping,
|
||||
calculus,
|
||||
|
|
@ -449,17 +503,23 @@ def ExpandReferencesInString( orig_s,
|
|||
++bug_catcher
|
||||
|
||||
try:
|
||||
s = string.Template( s ).substitute( mapping )
|
||||
s = _Substitute( s, mapping )
|
||||
break
|
||||
except KeyError as e:
|
||||
# HACK: This is seemingly the only way to get the key. str( e ) returns
|
||||
# the key surrounded by '' for unknowable reasons.
|
||||
key = e.args[ 0 ]
|
||||
except MissingSubstitution as e:
|
||||
key = e.name
|
||||
|
||||
if key in calculus:
|
||||
mapping[ key ] = calculus[ key ]()
|
||||
else:
|
||||
default_value = user_choices.get( key, None )
|
||||
default_value = user_choices.get( key )
|
||||
# Allow _one_ level of additional substitution. This allows a very real
|
||||
# use case of "program": ${prgram:${file\\}}
|
||||
if default_value is None and e.default_value is not None:
|
||||
try:
|
||||
default_value = _Substitute( e.default_value, mapping )
|
||||
except MissingSubstitution:
|
||||
default_value = e.default_value
|
||||
|
||||
mapping[ key ] = AskForInput( 'Enter value for {}: '.format( key ),
|
||||
default_value )
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,24 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"run - default": {
|
||||
"adapter": "debugpy",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"type": "python",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"program": "${program:${file\\}}",
|
||||
"stopOnEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
"breakpoints": {
|
||||
"exception": {
|
||||
"raised": "N",
|
||||
"uncaught": "",
|
||||
"userUnhandled": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"run - main.py": {
|
||||
"adapter": "debugpy",
|
||||
"configuration": {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue