@jupyter-lsp/jupyterlab-lsp
Version:
Language Server Protocol integration for JupyterLab
143 lines • 8.72 kB
JavaScript
import { FormComponent } from '@jupyterlab/ui-components';
import validatorAjv8 from '@rjsf/validator-ajv8';
import React, { useState } from 'react';
import { ServerLinksList } from './utils';
export const renderCollapseConflicts = (props) => {
const conflicts = Object.entries(props.conflicts).map(([server, serverConflicts]) => {
if (Object.keys(serverConflicts).length === 0) {
return null;
}
const listing = Object.entries(serverConflicts).map(([key, values]) => (React.createElement("li", { key: 'lsp-server-setting-conflict-' + key },
React.createElement("code", null, key),
": ",
React.createElement("code", null, JSON.stringify(values)))));
return (React.createElement("div", { key: 'lsp-server-setting-conflict-' + server },
React.createElement("h4", null, server),
React.createElement("ul", null, listing)));
});
return (React.createElement("div", null,
props.trans.__('Multiple distinct values detected for:'),
conflicts,
props.trans.__('Retaining the last value for each of the settings. Please remove the additional values in JSON Settings Editor.')));
};
export const renderLanguageServerSettings = (props) => {
return React.createElement(LanguageServerSettings, { ...props });
};
export class LanguageServerSettings extends React.Component {
constructor(props) {
super(props);
this.state = { ...props.formData };
this._objectTemplate = TabbedObjectTemplateFactory({
baseTemplate: this.props.registry.templates.ObjectFieldTemplate,
objectSelector: props => {
return (props.title === this.props.schema.title &&
props.description === this.props.schema.description);
},
trans: this.props.trans,
languageServerManager: this.props.languageServerManager
});
}
render() {
this.props.schema.description = undefined;
// hide the boilerplate title/description from schema definitions
for (const serverSchema of Object.values(this.props.schema.properties)) {
// note: have to be strings.
serverSchema.title = '';
serverSchema.description = '';
}
const validationErrors = this.props.validationErrors.map(error => (React.createElement("li", { key: 'lsp-validation-error-' + error.instancePath },
React.createElement("b", null, error.keyword),
": ",
error.message,
" in",
' ',
React.createElement("code", null, error.instancePath),
error.params && 'allowedValues' in error.params
? this.props.trans.__('allowed values: %1', JSON.stringify(error.params.allowedValues))
: null)));
const templates = {
...this.props.registry.templates,
ObjectFieldTemplate: this._objectTemplate
};
// remove self field to avoid infinite recursion
const fields = Object.fromEntries(Object.entries(this.props.registry.fields).filter(f => f[0] != 'language_servers'));
return (React.createElement("div", { className: "lsp-ServerSettings" },
React.createElement("h3", { className: "lsp-ServerSettings-title" }, this.props.trans.__('Language servers')),
validationErrors.length > 0 ? (React.createElement("div", { className: "lsp-ServerSettings-validationError" },
React.createElement("h4", null, this.props.trans.__('Validation of user settings for language server failed')),
React.createElement("p", null, this.props.trans.__('Your language server settings do not follow current schema. The LSP configuration graphical interface will run in schema-free mode to enable you to continue using the current settings as-is (in case if the schema is outdated). If this is however an earlier configuration mistake (settings were not validated in earlier versions of jupyterlab-lsp), please correct the following validation errors in JSON Settings Editor, save, and reload application:')),
React.createElement("ul", null, validationErrors))) : null,
React.createElement(FormComponent, { schema: this.props.schema, formData: this.state, validator: validatorAjv8,
// note: default JupyterLab `FieldTemplate` cannot correctly distinguish fields
// modified relative to programatically populated (transformed) schema >of objects<;
// the issue is in lines: https://github.com/jupyterlab/jupyterlab/blob/c2907074e58725942946a73a823fc60e1795da39/packages/settingeditor/src/SettingsFormEditor.tsx#L254-L272
// this is because 1) the schemaIds does not include the object key
// 2) the code assumes all objects on the same have the same defaults
// Probably the solution is to perform modification check on the level of ObjectFieldTemplate instead; this should be implemented upstream in JupyterLab.
// TODO
templates: templates, uiSchema: this.props.uiSchema, fields: fields, formContext: this.props.formContext, liveValidate: true, idPrefix: this.props.idPrefix + '_language_servers', onChange: this._onChange.bind(this) })));
}
_onChange(event) {
if (event.errors.length) {
console.error('Errors in form validation:', event.errors);
}
this.setState(event.formData, () => this.props.onChange(this.state));
}
}
/**
* Template for tabbed interface.
*/
const TabbedObjectTemplateFactory = (options) => {
const factory = (props) => {
if (!options.objectSelector(props)) {
const BaseTemplate = options.baseTemplate;
return React.createElement(BaseTemplate, { ...props });
}
const [tab, setTab] = useState(props.properties.length > 0 ? props.properties[0].name : null);
const renderServerLabels = (options) => {
const retained = options.properties.filter(property => options.filter(property.name));
if (retained.length == 0) {
return null;
}
return (React.createElement(React.Fragment, null,
React.createElement("h4", { className: 'lsp-ServerSettings-list-group' }, options.title),
React.createElement("ul", null, retained.map(property => {
return (React.createElement("li", { onClick: () => setTab(property.name), key: 'tab-' + property.name, "data-tab": property.name, className: property.name === tab ? 'lsp-selected' : undefined }, property.name));
}))));
};
const renderServerMetadata = (spec) => {
const workspaceConfig = spec.workspace_configuration;
return (React.createElement("div", null,
React.createElement("h4", { className: 'lsp-ServerSettings-content-name' }, spec.display_name),
React.createElement(ServerLinksList, { specification: spec }),
workspaceConfig ? (React.createElement("p", { className: 'lsp-ServerSettings-content-specOverrides' }, trans.__('Default values set programatically for: ') +
Object.keys(workspaceConfig).join(', '))) : null));
};
const manager = options.languageServerManager;
const trans = options.trans;
// TODO: expose `specs` upstream
return (React.createElement("fieldset", { id: props.idSchema.$id },
React.createElement("div", { className: 'lsp-ServerSettings-tabs' },
React.createElement("div", { className: 'lsp-ServerSettings-list' },
renderServerLabels({
properties: props.properties,
filter: name => manager.sessions.has(name),
title: trans.__('Available')
}),
renderServerLabels({
properties: props.properties,
filter: name => !manager.sessions.has(name),
title: trans.__('Not installed')
})),
React.createElement("div", { className: 'lsp-ServerSettings-content' },
manager.specs.has(tab)
? renderServerMetadata(manager.specs.get(tab))
: null,
props.properties
.filter(property => property.name === tab)
.map(property => property.content)))));
};
factory.displayName = 'TabbedObjectTemplate';
return factory;
};
//# sourceMappingURL=serverSettings.js.map