Module: Pikuri::Lsp::Uris

Defined in:
lib/pikuri/lsp/uris.rb

Overview

file: URI ↔ local path, plus the scheme sniff that decides whether a result is a path at all:

Uris.for_path('/home/m/my repo/a.rb')   # => "file:///home/m/my%20repo/a.rb"
Uris.to_path('file:///home/m/a%23b.rb') # => "/home/m/a#b.rb"
Uris.scheme('jdt://contents/rt.jar/java.lang/String.class?=…')  # => "jdt"
Uris.to_path('jdt://contents/…')        # => nil

Uris.to_path answering nil is the load-bearing half: a server's answer is routinely not a file (jdtls hands back jdt: URIs for anything inside a jar), and a client that assumes otherwise ends up denylist-checking a path that never existed.

Class Method Summary collapse

Class Method Details

.for_path(path) ⇒ String

Returns the file: URI a didOpen carries.

Parameters:

  • path (String, Pathname)

    an absolute local path.

Returns:

  • (String)

    the file: URI a didOpen carries.

Raises:

  • (ArgumentError)

    if path is relative — a server resolves URIs against nothing, so a relative one is a silently wrong document.



33
34
35
36
37
38
# File 'lib/pikuri/lsp/uris.rb', line 33

def for_path(path)
  str = path.to_s
  raise ArgumentError, "path must be absolute, got #{str.inspect}" unless str.start_with?('/')

  "file://#{URI::DEFAULT_PARSER.escape(str, PATH_SAFE)}"
end

.scheme(uri) ⇒ String?

Returns the lowercased scheme, or nil if uri carries none.

Parameters:

  • uri (String)

Returns:

  • (String, nil)

    the lowercased scheme, or nil if uri carries none.



56
57
58
# File 'lib/pikuri/lsp/uris.rb', line 56

def scheme(uri)
  uri[/\A([A-Za-z][A-Za-z0-9+.\-]*):/, 1]&.downcase
end

.to_path(uri) ⇒ String?

Local path behind a file: URI.

Parameters:

  • uri (String)

    any URI a server answered with.

Returns:

  • (String, nil)

    the percent-decoded path, or nil when uri is not a file: URI or names a remote host (+file://host/p+ is a UNC path; pikuri is Linux-first and has no way to read one).



46
47
48
49
50
51
# File 'lib/pikuri/lsp/uris.rb', line 46

def to_path(uri)
  match = %r{\Afile://([^/]*)(/.*)\z}.match(uri)
  return nil unless match && ['', 'localhost'].include?(match[1].downcase)

  URI::DEFAULT_PARSER.unescape(match[2]).force_encoding(Encoding::UTF_8)
end