Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions LSP-css.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
"syntaxes": ["Packages/LESS/Syntaxes/LESS.sublime-syntax"]
}
],
"initializationOptions": {},
"initializationOptions": {
"dataPaths": [],
},
"settings": {}
}
}
}
74 changes: 0 additions & 74 deletions package-lock.json

This file was deleted.

22 changes: 0 additions & 22 deletions package.json

This file was deleted.

98 changes: 34 additions & 64 deletions plugin.py
Original file line number Diff line number Diff line change
@@ -1,106 +1,76 @@
import shutil
import os
import sublime
import threading
import subprocess

from LSP.plugin.core.handlers import LanguageHandler
from LSP.plugin.core.settings import ClientConfig, LanguageConfig, read_client_config
from LSP.plugin.core.settings import ClientConfig, read_client_config
from .utils.resources import ServerNpmResource

PACKAGE_NAME = 'LSP-css'
SETTINGS_FILENAME = 'LSP-css.sublime-settings'
SERVER_DIRECTORY = 'vscode-css'
SERVER_BINARY_PATH = os.path.join(SERVER_DIRECTORY, 'out', 'cssServerMain.js')

package_path = os.path.dirname(__file__)
server_path = os.path.join(package_path, 'node_modules', 'vscode-css-languageserver-bin', 'cssServerMain.js')
server = ServerNpmResource(PACKAGE_NAME, SERVER_DIRECTORY, SERVER_BINARY_PATH)


def plugin_loaded():
is_server_installed = os.path.isfile(server_path)
print('LSP-css: Server {} installed.'.format('is' if is_server_installed else 'is not' ))

# install the node_modules if not installed
if not is_server_installed:
# this will be called only when the plugin gets:
# - installed for the first time,
# - or when updated on package control
logAndShowMessage('LSP-css: Installing server.')

runCommand(
onCommandDone,
["npm", "install", "--verbose", "--prefix", package_path, package_path]
)


def onCommandDone():
logAndShowMessage('LSP-css: Server installed.')


def runCommand(onExit, popenArgs):
"""
Runs the given args in a subprocess.Popen, and then calls the function
onExit when the subprocess completes.
onExit is a callable object, and popenArgs is a list/tuple of args that
would give to subprocess.Popen.
"""
def runInThread(onExit, popenArgs):
try:
if sublime.platform() == 'windows':
subprocess.check_call(popenArgs, shell=True)
else:
subprocess.check_call(popenArgs)
onExit()
except subprocess.CalledProcessError as error:
logAndShowMessage('LSP-css: Error while installing the server.', error)
return
thread = threading.Thread(target=runInThread, args=(onExit, popenArgs))
thread.start()
# returns immediately after the thread starts
return thread
server.setup()


def is_node_installed():
return shutil.which('node') is not None
def plugin_unloaded():
server.cleanup()


def logAndShowMessage(msg, additional_logs=None):
print(msg, '\n', additional_logs) if additional_logs else print(msg)
sublime.active_window().status_message(msg)
def is_node_installed():
return shutil.which('node') is not None


class LspCssPlugin(LanguageHandler):
@property
def name(self) -> str:
return 'lsp-css'
return PACKAGE_NAME.lower()

@property
def config(self) -> ClientConfig:
settings = sublime.load_settings("LSP-css.sublime-settings")
settings = sublime.load_settings(SETTINGS_FILENAME)
client_configuration = settings.get('client')
if client_configuration is None:
client_configuration = {}

# Calling setup() also here as this might run before `plugin_loaded`.
# Will be a no-op if already ran.
# See https://github.com/sublimelsp/LSP/issues/899
server.setup()

default_configuration = {
"command": [
'node',
server_path,
'--stdio'
],
"enabled": True,
"command": ['node', server.binary_path, '--stdio'],
"languages": [
{
"languageId": "css",
"scopes": ["source.css"],
"syntaxes": [
"Packages/CSS/CSS.sublime-syntax",
"Packages/CSS3/CSS3.sublime-syntax"
]
"Packages/CSS3/CSS3.sublime-syntax",
],
},
{
"languageId": "scss",
"scopes": ["source.scss"],
"syntaxes": ["Packages/Sass/Syntaxes/SCSS.sublime-syntax"]
"syntaxes": ["Packages/Sass/Syntaxes/SCSS.sublime-syntax"],
},
{
"languageId": "less",
"scopes": ["source.less"],
"syntaxes": ["Packages/LESS/Syntaxes/LESS.sublime-syntax"]
}
]
"syntaxes": ["Packages/LESS/Syntaxes/LESS.sublime-syntax"],
},
],
"initializationOptions": {
"dataPaths": [],
},
}

default_configuration.update(client_configuration)
return read_client_config('lsp-css', default_configuration)

Expand Down
Empty file added utils/__init__.py
Empty file.
106 changes: 106 additions & 0 deletions utils/resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import json
import os
import shutil
import sublime
import subprocess
import threading

from sublime_lib import ResourcePath


def run_command(on_exit, on_error, popen_args):
"""
Runs the given args in a subprocess.Popen, and then calls the function
on_exit when the subprocess completes.
on_exit is a callable object, and popen_args is a list/tuple of args that
on_error when the subprocess throws an error
would give to subprocess.Popen.
"""
def run_in_thread(on_exit, on_error, popen_args):
try:
subprocess.check_call(popen_args, shell=sublime.platform() == 'windows')
on_exit()
except subprocess.CalledProcessError as error:
on_error(error)

thread = threading.Thread(target=run_in_thread, args=(on_exit, on_error, popen_args))
thread.start()
# returns immediately after the thread starts
return thread


def log_and_show_message(msg, additional_logs=None):
print(msg, '\n', additional_logs) if additional_logs else print(msg)
sublime.active_window().status_message(msg)


class ServerNpmResource(object):
"""Global object providing paths to server resources.
Also handles the installing and updating of the server in cache.

setup() needs to be called during (or after) plugin_loaded() for paths to be valid.
"""

def __init__(self, package_name, server_directory, server_binary_path):
self._initialized = False
self._package_name = package_name
self._server_directory = server_directory
self._binary_path = server_binary_path
self._package_cache_path = None

@property
def binary_path(self):
return os.path.join(self._package_cache_path, self._binary_path)

def setup(self):
if self._initialized:
return

self._initialized = True
self._package_cache_path = os.path.join(sublime.cache_path(), self._package_name)

self._copy_to_cache()

def cleanup(self):
if os.path.isdir(self._package_cache_path):
shutil.rmtree(self._package_cache_path)

def _copy_to_cache(self):
src_path = 'Packages/{}/{}/'.format(self._package_name, self._server_directory)
dst_path = 'Cache/{}/{}/'.format(self._package_name, self._server_directory)
cache_server_path = os.path.join(self._package_cache_path, self._server_directory)

if os.path.isdir(cache_server_path):
# Server already in cache. Check if version has changed and if so, delete existing copy in cache.
try:
src_package_json = json.loads(ResourcePath(src_path, 'package.json').read_text())
dst_package_json = json.loads(ResourcePath(dst_path, 'package.json').read_text())

if src_package_json['version'] != dst_package_json['version']:
shutil.rmtree(cache_server_path)
except FileNotFoundError:
shutil.rmtree(cache_server_path)

if not os.path.isdir(cache_server_path):
# create cache folder
ResourcePath(src_path).copytree(cache_server_path, exist_ok=True)

self._install_dependencies(cache_server_path)

def _install_dependencies(self, cache_server_path):
dependencies_installed = os.path.isdir(os.path.join(cache_server_path, 'node_modules'))
print('{}: Server {} installed.'.format(self._package_name, 'is' if dependencies_installed else 'is not'))

if not dependencies_installed:
# this will be called only when the plugin gets:
# - installed for the first time,
# - or when updated on package control
log_and_show_message('{}: Installing server.'.format(self._package_name))

run_command(
lambda: log_and_show_message(
'{}: Server installed.'.format(self._package_name)),
lambda error: log_and_show_message(
'{}: Error while installing the server.'.format(self._package_name), error),
["npm", "install", "--verbose", "--production", "--prefix", cache_server_path, cache_server_path]
)
2 changes: 2 additions & 0 deletions vscode-css/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# download source codes
/vscode-css-languageserver/
11 changes: 11 additions & 0 deletions vscode-css/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
This repo contains built [vscode-css-languageserver](https://github.com/vscode-langservers/vscode-css-languageserver).


# Build

Just run `compile-vscode-css-languageserver.sh`. The built result will be in `out/`.


# References

- https://github.com/mattn/vim-lsp-settings/pull/48
Loading