@@ -11,6 +11,8 @@ import (
11
11
"net/url"
12
12
"path/filepath"
13
13
"regexp"
14
+ "strings"
15
+ "unicode"
14
16
15
17
"github.com/arduino/go-paths-helper"
16
18
"go.bug.st/json"
@@ -29,7 +31,11 @@ type DocumentURI struct {
29
31
// NilURI is the empty DocumentURI
30
32
var NilURI = DocumentURI {}
31
33
32
- var expDriveID = regexp .MustCompile ("^/[a-zA-Z]:" )
34
+ // for example, `"/c:"` or `"/A:"`
35
+ var expDriveWithLeadingSlashID = regexp .MustCompile ("^/[a-zA-Z]:" )
36
+
37
+ // for example, `"C:"` or `"A:"`
38
+ var expUppercaseDriveID = regexp .MustCompile ("^[A-Z]:" )
33
39
34
40
// AsPath convert the DocumentURI to a paths.Path
35
41
func (uri DocumentURI ) AsPath () * paths.Path {
@@ -39,12 +45,26 @@ func (uri DocumentURI) AsPath() *paths.Path {
39
45
// unbox convert the DocumentURI to a file path string
40
46
func (uri DocumentURI ) unbox () string {
41
47
path := uri .url .Path
42
- if expDriveID .MatchString (path ) {
48
+ if expDriveWithLeadingSlashID .MatchString (path ) {
43
49
return path [1 :]
44
50
}
45
51
return path
46
52
}
47
53
54
+ // Converts `"C:"` to `"c:"` to be compatible with VS Code URI's drive letter casing
55
+ // https://github.com/Microsoft/vscode/issues/68325#issuecomment-462239992
56
+ func lowercaseDriveSegment (pathSegment string ) string {
57
+ if len (pathSegment ) == 0 {
58
+ return pathSegment
59
+ }
60
+ if expUppercaseDriveID .MatchString (pathSegment ) {
61
+ chars := []rune (pathSegment )
62
+ chars [0 ] = unicode .ToLower (chars [0 ])
63
+ return string (chars )
64
+ }
65
+ return pathSegment
66
+ }
67
+
48
68
func (uri DocumentURI ) String () string {
49
69
return uri .url .String ()
50
70
}
@@ -68,11 +88,30 @@ func NewDocumentURI(path string) DocumentURI {
68
88
if len (path ) == 0 || path [0 ] != '/' {
69
89
path = "/" + path
70
90
}
71
- uri , err := NewDocumentURIFromURL ("file://" )
91
+ segments := strings .Split (path , "/" )
92
+ encodedSegments := make ([]string , len (segments ))
93
+ for i , segment := range segments {
94
+ if len (segment ) == 0 {
95
+ encodedSegments [i ] = segment
96
+ } else {
97
+ segment = lowercaseDriveSegment (segment )
98
+ chars := strings .SplitAfter (segment , "" )
99
+ for i , c := range chars {
100
+ // Spaces must be turned into `%20`. Otherwise, `url.QueryEscape`` encodes them to `+`.
101
+ if c == " " {
102
+ chars [i ] = "%20"
103
+ } else {
104
+ chars [i ] = url .QueryEscape (c )
105
+ }
106
+ }
107
+ encodedSegments [i ] = strings .Join (chars , "" )
108
+ }
109
+ }
110
+ urlPath := strings .Join (encodedSegments , "/" )
111
+ uri , err := NewDocumentURIFromURL ("file://" + urlPath )
72
112
if err != nil {
73
113
panic (err )
74
114
}
75
- uri .url .Path = path
76
115
return uri
77
116
}
78
117
@@ -89,7 +128,7 @@ func NewDocumentURIFromURL(inURL string) (DocumentURI, error) {
89
128
func (uri * DocumentURI ) UnmarshalJSON (data []byte ) error {
90
129
var s string
91
130
if err := json .Unmarshal (data , & s ); err != nil {
92
- return fmt .Errorf ("expoected JSON string for DocumentURI: %s" , err )
131
+ return fmt .Errorf ("expected JSON string for DocumentURI: %s" , err )
93
132
}
94
133
95
134
newDocURI , err := NewDocumentURIFromURL (s )
0 commit comments