sublimelsp / LSP-vue

Vue support for Sublime's LSP plugin
MIT License
29 stars 3 forks source link

Can't get document formatting to work #102

Closed bjesus closed 3 years ago

bjesus commented 3 years ago

Hi! Thanks for LSP-vue - I'm really excited about the idea of getting a similar Vetur experience inside ST.

I can't get LSP-vue to format my documents, and more specifically, to format on save. My Vue files are using pug, typescript and scss.

I've set lsp_format_on_save": true in the LSP settings as well as Sublime general settings.

Upon save, nothing gets formatted in my file. I get this at the log:

::  -> LSP-vue textDocument/didSave: {'textDocument': {'uri': 'file:///my/project/pages/category/_id/setup.vue'}}
:: --> LSP-vue textDocument/codeAction(6): {'textDocument': {'uri': 'file:///my/project/pages/category/_id/setup.vue'}, 'range': {'end': {'line': 222, 'character': 0}, 'start': {'line': 0, 'character': 0}}, 'context': {'diagnostics': [], 'only': ['source.organizeImports']}}

I don't see any way to manually trigger a "Format Document" command either.

Some debugging information The full init log is as follows: ``` :: --> LSP-vue initialize(1): {'workspaceFolders': [{'name': 'dashboard', 'uri': 'file:///my/project'}], 'rootPath': '/my/project', 'capabilities': {'textDocument': {'declaration': {'dynamicRegistration': True, 'linkSupport': True}, 'implementation': {'dynamicRegistration': True, 'linkSupport': True}, 'completion': {'dynamicRegistration': True, 'completionItemKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]}, 'completionItem': {'resolveSupport': {'properties': ['detail', 'documentation', 'additionalTextEdits']}, 'snippetSupport': True, 'documentationFormat': ['markdown', 'plaintext'], 'tagSupport': {'valueSet': [1]}, 'deprecatedSupport': True}}, 'synchronization': {'dynamicRegistration': True, 'willSave': True, 'didSave': True, 'willSaveWaitUntil': True}, 'formatting': {'dynamicRegistration': True}, 'references': {'dynamicRegistration': True}, 'colorProvider': {'dynamicRegistration': True}, 'rangeFormatting': {'dynamicRegistration': True}, 'codeLens': {'dynamicRegistration': True}, 'selectionRange': {'dynamicRegistration': True}, 'publishDiagnostics': {'relatedInformation': True, 'versionSupport': True, 'tagSupport': {'valueSet': [1, 2]}, 'dataSupport': True, 'codeDescriptionSupport': True}, 'documentSymbol': {'dynamicRegistration': True, 'symbolKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]}, 'tagSupport': {'valueSet': [1]}, 'hierarchicalDocumentSymbolSupport': True}, 'rename': {'dynamicRegistration': True, 'prepareSupport': True}, 'codeAction': {'dynamicRegistration': True, 'resolveSupport': {'properties': ['edit']}, 'codeActionLiteralSupport': {'codeActionKind': {'valueSet': ['quickfix', 'refactor', 'refactor.extract', 'refactor.inline', 'refactor.rewrite', 'source.organizeImports']}}, 'dataSupport': True}, 'signatureHelp': {'dynamicRegistration': True, 'signatureInformation': {'documentationFormat': ['markdown', 'plaintext'], 'parameterInformation': {'labelOffsetSupport': True}}}, 'typeDefinition': {'dynamicRegistration': True, 'linkSupport': True}, 'documentHighlight': {'dynamicRegistration': True}, 'hover': {'dynamicRegistration': True, 'contentFormat': ['markdown', 'plaintext']}, 'definition': {'dynamicRegistration': True, 'linkSupport': True}}, 'experimental': {}, 'general': {'regularExpressions': {'engine': 'ECMAScript'}, 'markdown': {'version': '3.2.2', 'parser': 'Python-Markdown'}}, 'workspace': {'workspaceFolders': True, 'didChangeConfiguration': {'dynamicRegistration': True}, 'workspaceEdit': {'failureHandling': 'abort', 'documentChanges': True}, 'configuration': True, 'executeCommand': {}, 'symbol': {'dynamicRegistration': True, 'symbolKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]}, 'tagSupport': {'valueSet': [1]}}, 'applyEdit': True}, 'window': {'workDoneProgress': True, 'showMessage': {'messageActionItem': {'additionalPropertiesSupport': True}}, 'showDocument': {'support': True}}}, 'initializationOptions': {'config': {'emmet': {}, 'javascript': {'format': {}}, 'css': {'lint': {'float': 'ignore', 'validProperties': [], 'unknownAtRules': 'warning', 'important': 'ignore', 'idSelector': 'ignore', 'zeroUnits': 'ignore', 'duplicateProperties': 'ignore', 'boxModel': 'ignore', 'fontFaceProperties': 'warning', 'unknownProperties': 'warning', 'vendorPrefix': 'warning', 'importStatement': 'ignore', 'compatibleVendorPrefixes': 'ignore', 'hexColorLength': 'error', 'universalSelector': 'ignore', 'unknownVendorSpecificProperties': 'ignore', 'ieHack': 'ignore', 'emptyRules': 'warning', 'propertyIgnoredDueToDisplay': 'warning', 'argumentsInColorFunction': 'error'}, 'validate': True, 'customData': [], 'completion': {'completePropertyWithSemicolon': True, 'triggerPropertyValueCompletion': True}}, 'typescript': {'format': {}}, 'vetur': {'format': {'enable': True, 'styleInitialIndent': False, 'defaultFormatterOptions': {}, 'scriptInitialIndent': False, 'defaultFormatter': {'less': 'prettier', 'pug': 'prettier', 'postcss': 'prettier', 'js': 'prettier', 'css': 'prettier', 'ts': 'prettier', 'scss': 'prettier', 'html': 'prettier', 'sass': 'sass-formatter', 'stylus': 'stylus-supremacy'}, 'options': {'tabSize': 2, 'useTabs': False}}, 'languageFeatures': {'codeActions': True}, 'completion': {'autoImport': False, 'scaffoldSnippetSources': {'vetur': '✌', 'workspace': '💼', 'user': '\U0001f5d2️'}, 'tagCasing': 'kebab'}, 'ignoreProjectWarning': False, 'experimental': {'templateInterpolationService': False}, 'validation': {'interpolation': True, 'script': True, 'style': True, 'templateProps': False, 'template': True}, 'useWorkspaceDependencies': False}, 'html': {'suggest': {}}, 'stylusSupremacy': {}}}, 'processId': 1211400, 'clientInfo': {'version': '1.3.1', 'name': 'Sublime Text LSP'}, 'rootUri': 'file:///my/project'} LSP-vue: Vetur initialized :: <- LSP-vue window/logMessage: {'message': 'Vetur initialized', 'type': 4} :: <<< LSP-vue 1: {'capabilities': {'documentHighlightProvider': True, 'workspace': {'workspaceFolders': {'changeNotifications': True, 'supported': True}, 'fileOperations': {'willRename': {'filters': [{'pattern': {'glob': '**/*.{ts,js,vue}'}}]}}}, 'completionProvider': {'triggerCharacters': ['.', ':', '<', '"', "'", '/', '@', '*', ' '], 'resolveProvider': True}, 'documentSymbolProvider': True, 'hoverProvider': True, 'textDocumentSync': {'change': {'syncKind': 2}, 'didClose': {}, 'didOpen': {}, 'save': {}}, 'executeCommandProvider': {'commands': []}, 'colorProvider': True, 'codeActionProvider': {'codeActionKinds': ['quickfix', 'refactor', 'refactor.extract', 'refactor.inline', 'refactor.rewrite', 'source', 'source.organizeImports'], 'resolveProvider': True}, 'definitionProvider': True, 'foldingRangeProvider': True, 'documentLinkProvider': {'resolveProvider': False}, 'referencesProvider': True, 'signatureHelpProvider': {'triggerCharacters': ['(']}, 'documentFormattingProvider': False}} :: -> LSP-vue initialized: {} :: -> LSP-vue textDocument/didOpen: {'textDocument': {'languageId': 'vue', 'version': 55, 'uri': 'file:///my/project/pages/category/_id/setup.vue', 'text': 'MY_FILE_CONTENT'}} :: --> LSP-vue textDocument/documentColor(2): {'textDocument': {'uri': 'file:///my/project/pages/category/_id/setup.vue'}} :: <-- LSP-vue client/registerCapability(0): {'registrations': [{'id': '3aa37a8e-3b20-4b26-b816-2c9806d2def2', 'method': 'workspace/didChangeWorkspaceFolders', 'registerOptions': {}}]} :: >>> LSP-vue 0: None :: <-- LSP-vue window/workDoneProgress/create(1): {'token': 'b2eb564e-0860-4de3-9d76-4db2e08a4767'} :: >>> LSP-vue 1: None LSP-vue: [INFO ] Find node_modules paths in /my/project - 156ms LSP-vue: [INFO ] Loaded bundled typescript@4.2.4. LSP-vue: [INFO ] Loaded bundled prettier. LSP-vue: [INFO ] Loaded bundled @starptech/prettyhtml. LSP-vue: [INFO ] Loaded bundled prettier-eslint. LSP-vue: [INFO ] Loaded bundled prettier-tslint. LSP-vue: [INFO ] Loaded bundled stylus-supremacy. LSP-vue: [INFO ] Loaded bundled @prettier/plugin-pug. LSP-vue: (node:1211904) [DEP0148] DeprecationWarning: Use of deprecated folder mapping "./" in the "exports" field module resolution of the package at /my/project/node_modules/@nuxtjs/composition-api/package.json. Update this package.json to use a subpath pattern like "./*". (Use `node --trace-deprecation ...` to show where the warning was created) :: <- LSP-vue $/progress: {'value': {'title': 'Load project: /my/project', 'kind': 'begin'}, 'token': 'b2eb564e-0860-4de3-9d76-4db2e08a4767'} :: <- LSP-vue window/logMessage: {'message': '[INFO ] Find node_modules paths in /my/project - 156ms', 'type': 4} :: <- LSP-vue window/logMessage: {'message': '[INFO ] Loaded bundled typescript@4.2.4.', 'type': 4} :: <- LSP-vue window/logMessage: {'message': '[INFO ] Loaded bundled prettier.', 'type': 4} :: <- LSP-vue window/logMessage: {'message': '[INFO ] Loaded bundled @starptech/prettyhtml.', 'type': 4} :: <- LSP-vue window/logMessage: {'message': '[INFO ] Loaded bundled prettier-eslint.', 'type': 4} :: <- LSP-vue window/logMessage: {'message': '[INFO ] Loaded bundled prettier-tslint.', 'type': 4} :: <- LSP-vue window/logMessage: {'message': '[INFO ] Loaded bundled stylus-supremacy.', 'type': 4} :: <- LSP-vue window/logMessage: {'message': '[INFO ] Loaded bundled @prettier/plugin-pug.', 'type': 4} :: <- LSP-vue $/progress: {'value': {'kind': 'end'}, 'token': 'b2eb564e-0860-4de3-9d76-4db2e08a4767'} :: <<< LSP-vue 2: [{'range': {'end': {'line': 176, 'character': 21}, 'start': {'line': 176, 'character': 16}}, 'color': {'blue': 1, 'red': 1, 'alpha': 1, 'green': 1}}, {'range': {'end': {'line': 178, 'character': 31}, 'start': {'line': 178, 'character': 22}}, 'color': {'blue': 0.8274509803921568, 'red': 0.8274509803921568, 'alpha': 1, 'green': 0.8274509803921568}}, {'range': {'end': {'line': 207, 'character': 18}, 'start': {'line': 207, 'character': 13}}, 'color': {'blue': 1, 'red': 1, 'alpha': 1, 'green': 1}}] :: <- LSP-vue window/logMessage: {'message': '(node:1211904) [DEP0148] DeprecationWarning: Use of deprecated folder mapping "./" in the "exports" field module resolution of the package at /my/project/node_modules/@nuxtjs/composition-api/package.json.\nUpdate this package.json to use a subpath pattern like "./*".\n(Use `node --trace-deprecation ...` to show where the warning was created)', 'type': 1} ``` The troubleshooting information is as follows: # Troubleshooting: LSP-vue ## Version - LSP: 1.3.1 - Sublime Text: 4107 ## Server Test Run - exit code: 0 - output ``` ``` ## Server Configuration - command ```json [ "/usr/bin/node", "/home/user/.nvm/versions/node/v15.14.0/bin/vls", "--stdio" ] ``` - shell command ```sh /usr/bin/node /home/user/.nvm/versions/node/v15.14.0/bin/vls --stdio ``` - selector ``` (text.html.vue) ``` - priority_selector ``` (text.html.vue) ``` - init_options ```json { "config": { "css": { "completion": { "completePropertyWithSemicolon": true, "triggerPropertyValueCompletion": true }, "customData": [], "lint": { "argumentsInColorFunction": "error", "boxModel": "ignore", "compatibleVendorPrefixes": "ignore", "duplicateProperties": "ignore", "emptyRules": "warning", "float": "ignore", "fontFaceProperties": "warning", "hexColorLength": "error", "idSelector": "ignore", "ieHack": "ignore", "importStatement": "ignore", "important": "ignore", "propertyIgnoredDueToDisplay": "warning", "universalSelector": "ignore", "unknownAtRules": "warning", "unknownProperties": "warning", "unknownVendorSpecificProperties": "ignore", "validProperties": [], "vendorPrefix": "warning", "zeroUnits": "ignore" }, "validate": true }, "emmet": {}, "html": { "suggest": {} }, "javascript": { "format": {} }, "stylusSupremacy": {}, "typescript": { "format": {} }, "vetur": { "completion": { "autoImport": false, "scaffoldSnippetSources": { "user": "🗒️", "vetur": "✌", "workspace": "💼" }, "tagCasing": "kebab" }, "experimental": { "templateInterpolationService": false }, "format": { "defaultFormatter": { "css": "prettier", "html": "prettier", "js": "prettier", "less": "prettier", "postcss": "prettier", "pug": "prettier", "sass": "sass-formatter", "scss": "prettier", "stylus": "stylus-supremacy", "ts": "prettier" }, "defaultFormatterOptions": {}, "enable": true, "options": { "tabSize": 2, "useTabs": false }, "scriptInitialIndent": false, "styleInitialIndent": false }, "ignoreProjectWarning": false, "languageFeatures": { "codeActions": true }, "useWorkspaceDependencies": false, "validation": { "interpolation": true, "script": true, "style": true, "template": true, "templateProps": false } } } } ``` - settings ```json {} ``` - env ```json {} ``` ## Active view - File name ``` /my/project/pages/category/_id/setup.vue ``` - Settings ```json { "auto_complete_selector": "meta.tag, source - comment - string.quoted.double.block - string.quoted.single.block - string.unquoted.heredoc", "lsp_active": true, "syntax": "Packages/Vue Syntax Highlight/Vue Component.sublime-syntax" } ``` - base scope ``` text.html.vue ``` ## Project / Workspace - folders ```json [ "/my/project" ] ``` - is project: False ## LSP configuration ```json { "log_debug": true, "log_server": [ "panel" ], "lsp_code_actions_on_save": { "source.fixAll": true, "source.organizeImports": true }, "lsp_format_on_save": true, "only_show_lsp_completions": true, "show_diagnostics_count_in_view_status": true } ``` ## System PATH - /usr/local/bin - /usr/bin
rchl commented 3 years ago

I know what's the problem and I already had it fixed locally. Will create a PR soon.

bjesus commented 3 years ago

Great, thank you very much. Will wait for the next release then!

rchl commented 3 years ago

Released version 2.0.0. Should appear on PC shortly.

Note that there might be a bug in vetur because trying it on my code that uses 4 spaces, it gets reformatted to 2 spaces even though the formatting params specify 4 spaces:

:: --> LSP-vue textDocument/formatting(24): {'options': {'trimFinalNewlines': True, 'trimTrailingWhitespace': False, 'insertSpaces': True, 'tabSize': 4, 'insertFinalNewline': True}, 'workDoneToken': 'wd24', 'textDocument': {'uri': 'file:///Users/rafal/workspace/web/project/edit.vue'}}
rchl commented 3 years ago

Actually that was my bug. Sort of, vetur should follow the options from the formatting request but it uses global options which I forgot to update. Fixing in https://github.com/sublimelsp/LSP-vue/pull/104

bjesus commented 3 years ago

I must be doing something wrong because the formatting still doesn't work for me. I do get "LSP: Format File" in the command menu, but it seems to be doing nothing. The log shows :: --> LSP-vue textDocument/formatting(175): {'workDoneToken': 'wd175', 'options': {'insertFinalNewline': False, 'tabSize': 2, 'insertSpaces': True, 'trimTrailingWhitespace': False, 'trimFinalNewlines': False}, 'textDocument': {'uri': 'file:///home/user/myproject/_id/setup.vue'}} but nothing changes in the document. I have really really long lines that don't get broken into multiple lines, and many empty lines between functions that don't disappear. Noting in the document changes, at all.

My LSP-vue config is:

{
  "command": ["/usr/bin/node", "/home/path/to/node/v15.14.0/bin/vls", "--stdio"],
  "initializationOptions": {
    "config": {
      "vetur.format.defaultFormatter.js": "prettier",
      "vetur.format.defaultFormatter.ts": "prettier"
    }
  }
}

And the LSP settings are:

{
  "lsp_format_on_save": true,
  "log_server": ["panel"],
  "log_debug": false,
  "show_diagnostics_count_in_view_status": true,
  "log_debug": true,
  "only_show_lsp_completions": true,
  "lsp_code_actions_on_save": {
    "source.fixAll": true,
    "source.organizeImports": true
  }
}

Am I missing some important setting? I'm using LSP-vue 2.0.1 now.

rchl commented 3 years ago

initializationOptions is replaced by settings but that shouldn't matter as you are trying to format a vue file.

Also, why have you customized the command? Your should be using the default command and bundled VLS.

Please paste the whole log from the "LSP Log Panel" from initialization to the save being triggered.

bjesus commented 3 years ago

Sorry, I originally hard-coded the VLS path because I was worried it might not be getting loaded. I removed that line from my settings now and I've changed initializationOptions to settings.

This is the log (I just cleaned some paths and removed the file content itself):

:: --> LSP-vue initialize(1): {'processId': 1552169, 'initializationOptions': {}, 'rootUri': 'file:///home/user/project', 'rootPath': '/home/user/project', 'workspaceFolders': [{'name': 'configs', 'uri': 'file:///home/user/project'}], 'clientInfo': {'name': 'Sublime Text LSP', 'version': '1.3.1'}, 'capabilities': {'experimental': {}, 'textDocument': {'documentHighlight': {'dynamicRegistration': True}, 'typeDefinition': {'dynamicRegistration': True, 'linkSupport': True}, 'signatureHelp': {'signatureInformation': {'documentationFormat': ['markdown', 'plaintext'], 'parameterInformation': {'labelOffsetSupport': True}}, 'dynamicRegistration': True}, 'declaration': {'dynamicRegistration': True, 'linkSupport': True}, 'rangeFormatting': {'dynamicRegistration': True}, 'selectionRange': {'dynamicRegistration': True}, 'colorProvider': {'dynamicRegistration': True}, 'rename': {'dynamicRegistration': True, 'prepareSupport': True}, 'formatting': {'dynamicRegistration': True}, 'references': {'dynamicRegistration': True}, 'synchronization': {'willSave': True, 'dynamicRegistration': True, 'willSaveWaitUntil': True, 'didSave': True}, 'publishDiagnostics': {'codeDescriptionSupport': True, 'relatedInformation': True, 'dataSupport': True, 'versionSupport': True, 'tagSupport': {'valueSet': [2, 1]}}, 'definition': {'dynamicRegistration': True, 'linkSupport': True}, 'hover': {'dynamicRegistration': True, 'contentFormat': ['markdown', 'plaintext']}, 'codeLens': {'dynamicRegistration': True}, 'completion': {'dynamicRegistration': True, 'completionItemKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]}, 'completionItem': {'documentationFormat': ['markdown', 'plaintext'], 'snippetSupport': True, 'resolveSupport': {'properties': ['detail', 'documentation', 'additionalTextEdits']}, 'deprecatedSupport': True, 'tagSupport': {'valueSet': [1]}}}, 'documentSymbol': {'symbolKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]}, 'dynamicRegistration': True, 'hierarchicalDocumentSymbolSupport': True, 'tagSupport': {'valueSet': [1]}}, 'codeAction': {'dynamicRegistration': True, 'resolveSupport': {'properties': ['edit']}, 'dataSupport': True, 'codeActionLiteralSupport': {'codeActionKind': {'valueSet': ['quickfix', 'refactor', 'refactor.extract', 'refactor.inline', 'refactor.rewrite', 'source.organizeImports']}}}, 'implementation': {'dynamicRegistration': True, 'linkSupport': True}}, 'window': {'workDoneProgress': True, 'showDocument': {'support': True}, 'showMessage': {'messageActionItem': {'additionalPropertiesSupport': True}}}, 'workspace': {'executeCommand': {}, 'configuration': True, 'applyEdit': True, 'symbol': {'symbolKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]}, 'dynamicRegistration': True, 'tagSupport': {'valueSet': [1]}}, 'didChangeConfiguration': {'dynamicRegistration': True}, 'workspaceFolders': True, 'workspaceEdit': {'documentChanges': True, 'failureHandling': 'abort'}}, 'general': {'regularExpressions': {'engine': 'ECMAScript'}, 'markdown': {'version': '3.2.2', 'parser': 'Python-Markdown'}}}}
LSP-vue: Vetur initialized
:: <-  LSP-vue window/logMessage: {'message': 'Vetur initialized', 'type': 4}
:: <<< LSP-vue 1: {'capabilities': {'documentSymbolProvider': True, 'documentFormattingProvider': False, 'colorProvider': True, 'executeCommandProvider': {'commands': []}, 'textDocumentSync': {'didOpen': {}, 'didClose': {}, 'change': {'syncKind': 2}, 'save': {}}, 'definitionProvider': True, 'workspace': {'workspaceFolders': {'changeNotifications': True, 'supported': True}, 'fileOperations': {'willRename': {'filters': [{'pattern': {'glob': '**/*.{ts,js,vue}'}}]}}}, 'hoverProvider': True, 'foldingRangeProvider': True, 'completionProvider': {'triggerCharacters': ['.', ':', '<', '"', "'", '/', '@', '*', ' '], 'resolveProvider': True}, 'documentLinkProvider': {'resolveProvider': False}, 'signatureHelpProvider': {'triggerCharacters': ['(']}, 'referencesProvider': True, 'codeActionProvider': {'codeActionKinds': ['quickfix', 'refactor', 'refactor.extract', 'refactor.inline', 'refactor.rewrite', 'source', 'source.organizeImports'], 'resolveProvider': True}, 'documentHighlightProvider': True}}
::  -> LSP-vue initialized: {}
::  -> LSP-vue workspace/didChangeConfiguration: {'settings': {'vetur': {'experimental': {'templateInterpolationService': False}, 'ignoreProjectWarning': False, 'validation': {'script': True, 'template': True, 'interpolation': True, 'templateProps': False, 'style': True}, 'useWorkspaceDependencies': False, 'format': {'scriptInitialIndent': False, 'options': {'tabSize': 2, 'useTabs': False}, 'defaultFormatter': {'scss': 'prettier', 'pug': 'prettier', 'stylus': 'stylus-supremacy', 'sass': 'sass-formatter', 'html': 'prettier', 'postcss': 'prettier', 'less': 'prettier', 'ts': 'none', 'css': 'prettier', 'js': 'none'}, 'enable': True, 'defaultFormatterOptions': {}, 'styleInitialIndent': False}, 'completion': {'autoImport': False, 'tagCasing': 'kebab', 'scaffoldSnippetSources': {'vetur': '✌', 'user': '\U0001f5d2️', 'workspace': '💼'}}, 'languageFeatures': {'codeActions': True, 'updateImportOnFileMove': True}}, 'stylusSupremacy': {}, 'html': {'suggest': {}}, 'emmet': {}, 'typescript': {'format': {}}, 'config': {'vetur': {'format': {'defaultFormatter': {'ts': 'prettier', 'js': 'prettier'}}}}, 'css': {'validate': True, 'lint': {'unknownVendorSpecificProperties': 'ignore', 'duplicateProperties': 'ignore', 'compatibleVendorPrefixes': 'ignore', 'importStatement': 'ignore', 'emptyRules': 'warning', 'important': 'ignore', 'hexColorLength': 'error', 'vendorPrefix': 'warning', 'idSelector': 'ignore', 'unknownProperties': 'warning', 'fontFaceProperties': 'warning', 'boxModel': 'ignore', 'universalSelector': 'ignore', 'argumentsInColorFunction': 'error', 'ieHack': 'ignore', 'unknownAtRules': 'warning', 'zeroUnits': 'ignore', 'float': 'ignore', 'validProperties': [], 'propertyIgnoredDueToDisplay': 'warning'}, 'completion': {'completePropertyWithSemicolon': True, 'triggerPropertyValueCompletion': True}, 'customData': []}, 'javascript': {'format': {}}}}
::  -> LSP-vue textDocument/didOpen: {'textDocument': {'text': 'MY_FILE_CONTENT', 'uri': 'file:///home/user/project/pages/items/_id/setup.vue', 'languageId': 'vue', 'version': 0}}
:: --> LSP-vue textDocument/documentColor(2): {'textDocument': {'uri': 'file:///home/user/project/pages/items/_id/setup.vue'}}
:: <-- LSP-vue client/registerCapability(0): {'registrations': [{'id': 'aa11b416-7abd-40c0-a22b-d38ed759f0f3', 'registerOptions': {}, 'method': 'workspace/didChangeWorkspaceFolders'}]}
:: >>> LSP-vue 0: None
:: <-- LSP-vue client/registerCapability(1): {'registrations': [{'id': '66687c2b-23df-4e3c-a8af-3ca7e0b4162a', 'registerOptions': {'documentSelector': [{'language': 'vue'}]}, 'method': 'textDocument/formatting'}]}
:: >>> LSP-vue 1: None
:: <<< LSP-vue 2: []
:: --> LSP-vue textDocument/codeAction(3): {'textDocument': {'uri': 'file:///home/user/project/pages/items/_id/setup.vue'}, 'context': {'diagnostics': [], 'only': ['source.organizeImports']}, 'range': {'end': {'character': 0, 'line': 221}, 'start': {'character': 0, 'line': 0}}}
:: <<< LSP-vue 3: []
:: --> LSP-vue textDocument/formatting(4): {'textDocument': {'uri': 'file:///home/user/project/pages/items/_id/setup.vue'}, 'workDoneToken': 'wd4', 'options': {'tabSize': 2, 'trimFinalNewlines': False, 'insertFinalNewline': False, 'insertSpaces': True, 'trimTrailingWhitespace': False}}
:: <<< LSP-vue 4: []
::  -> LSP-vue textDocument/didSave: {'textDocument': {'uri': 'file:///home/user/project/pages/items/_id/setup.vue'}}

Note that my Vue file is made of a Pug template, TypeScript and SCSS. I'm thinking that perhaps that has something to do with the issue? I have enabled prettier for pug and ts in my settings however.

rchl commented 3 years ago

It seems like vetur is not able to find dependencies in your project. Are you using npm or something fancy like yarn pnp?

For me I get various messages about detected formatter/linters:

:: --> LSP-vue initialize(1): {'workspaceFolders': [{'name': 'project', 'uri': 'file:///Users/rafal/workspace/web/project'}], 'clientInfo': {'name': 'Sublime Text LSP', 'version': '1.3.1'}, 'processId': 12390, 'capabilities': {'general': {'regularExpressions': {'engine': 'ECMAScript'}, 'markdown': {'version': '3.2.2', 'parser': 'Python-Markdown'}}, 'workspace': {'workspaceFolders': True, 'configuration': True, 'symbol': {'dynamicRegistration': True, 'tagSupport': {'valueSet': [1]}, 'symbolKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]}}, 'didChangeConfiguration': {'dynamicRegistration': True}, 'workspaceEdit': {'documentChanges': True, 'failureHandling': 'abort'}, 'didChangeWatchedFiles': {'dynamicRegistration': True}, 'executeCommand': {}, 'applyEdit': True}, 'experimental': {}, 'textDocument': {'selectionRange': {'dynamicRegistration': True}, 'codeLens': {'dynamicRegistration': True}, 'references': {'dynamicRegistration': True}, 'hover': {'dynamicRegistration': True, 'contentFormat': ['markdown', 'plaintext']}, 'documentSymbol': {'dynamicRegistration': True, 'tagSupport': {'valueSet': [1]}, 'hierarchicalDocumentSymbolSupport': True, 'symbolKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]}}, 'rename': {'dynamicRegistration': True, 'prepareSupport': True}, 'declaration': {'dynamicRegistration': True, 'linkSupport': True}, 'synchronization': {'dynamicRegistration': True, 'willSave': True, 'willSaveWaitUntil': True, 'didSave': True}, 'publishDiagnostics': {'relatedInformation': True, 'tagSupport': {'valueSet': [2, 1]}, 'dataSupport': True, 'codeDescriptionSupport': True, 'versionSupport': True}, 'documentHighlight': {'dynamicRegistration': True}, 'colorProvider': {'dynamicRegistration': True}, 'rangeFormatting': {'dynamicRegistration': True}, 'formatting': {'dynamicRegistration': True}, 'signatureHelp': {'dynamicRegistration': True, 'signatureInformation': {'parameterInformation': {'labelOffsetSupport': True}, 'documentationFormat': ['markdown', 'plaintext']}}, 'definition': {'dynamicRegistration': True, 'linkSupport': True}, 'completion': {'dynamicRegistration': True, 'completionItemKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]}, 'completionItem': {'tagSupport': {'valueSet': [1]}, 'snippetSupport': True, 'deprecatedSupport': True, 'resolveSupport': {'properties': ['detail', 'documentation', 'additionalTextEdits']}, 'documentationFormat': ['markdown', 'plaintext']}}, 'codeAction': {'dynamicRegistration': True, 'codeActionLiteralSupport': {'codeActionKind': {'valueSet': ['quickfix', 'refactor', 'refactor.extract', 'refactor.inline', 'refactor.rewrite', 'source.organizeImports']}}, 'resolveSupport': {'properties': ['edit']}, 'dataSupport': True}, 'onTypeFormatting': {'dynamicRegistration': True}, 'typeDefinition': {'dynamicRegistration': True, 'linkSupport': True}, 'implementation': {'dynamicRegistration': True, 'linkSupport': True}}, 'window': {'workDoneProgress': True, 'showDocument': {'support': True}, 'showMessage': {'messageActionItem': {'additionalPropertiesSupport': True}}}}, 'rootPath': '/Users/rafal/workspace/web/project', 'initializationOptions': {}, 'rootUri': 'file:///Users/rafal/workspace/web/project'}
LSP-vue: Vetur initialized
:: <-  LSP-vue window/logMessage: {'type': 4, 'message': 'Vetur initialized'}
:: <<< LSP-vue 1: {'capabilities': {'documentFormattingProvider': False, 'workspace': {'workspaceFolders': {'changeNotifications': True, 'supported': True}, 'fileOperations': {'willRename': {'filters': [{'pattern': {'glob': '**/*.{ts,js,vue}'}}]}}}, 'foldingRangeProvider': True, 'documentLinkProvider': {'resolveProvider': False}, 'executeCommandProvider': {'commands': []}, 'codeActionProvider': {'resolveProvider': True, 'codeActionKinds': ['quickfix', 'refactor', 'refactor.extract', 'refactor.inline', 'refactor.rewrite', 'source', 'source.organizeImports']}, 'completionProvider': {'resolveProvider': True, 'triggerCharacters': ['.', ':', '<', '"', "'", '/', '@', '*', ' ']}, 'definitionProvider': True, 'documentSymbolProvider': True, 'colorProvider': True, 'documentHighlightProvider': True, 'textDocumentSync': {'change': {'syncKind': 2}, 'didClose': {}, 'save': {}, 'didOpen': {}}, 'referencesProvider': True, 'hoverProvider': True, 'signatureHelpProvider': {'triggerCharacters': ['(']}}}
::  -> LSP-vue initialized: {}
::  -> LSP-vue workspace/didChangeConfiguration: {'settings': {'css': {'lint': {'unknownProperties': 'warning', 'compatibleVendorPrefixes': 'ignore', 'duplicateProperties': 'ignore', 'propertyIgnoredDueToDisplay': 'warning', 'unknownVendorSpecificProperties': 'ignore', 'important': 'ignore', 'boxModel': 'ignore', 'fontFaceProperties': 'warning', 'validProperties': [], 'idSelector': 'ignore', 'importStatement': 'ignore', 'unknownAtRules': 'warning', 'float': 'ignore', 'hexColorLength': 'error', 'zeroUnits': 'ignore', 'ieHack': 'ignore', 'emptyRules': 'warning', 'vendorPrefix': 'warning', 'universalSelector': 'ignore', 'argumentsInColorFunction': 'error'}, 'customData': [], 'validate': True, 'completion': {'triggerPropertyValueCompletion': True, 'completePropertyWithSemicolon': True}}, 'emmet': {}, 'typescript': {'format': {}}, 'javascript': {'format': {}}, 'stylusSupremacy': {}, 'file_watcher': {'glob': '{**/*.js,**/*.ts,**/*.json}', 'kind': ['create', 'change']}, 'html': {'suggest': {}}, 'vetur': {'languageFeatures': {'codeActions': True, 'updateImportOnFileMove': True}, 'useWorkspaceDependencies': True, 'validation': {'interpolation': True, 'script': True, 'templateProps': True, 'style': True, 'template': True}, 'completion': {'scaffoldSnippetSources': {'workspace': '💼', 'user': '\U0001f5d2️', 'vetur': '✌'}, 'tagCasing': 'kebab', 'autoImport': True}, 'format': {'scriptInitialIndent': False, 'enable': True, 'defaultFormatterOptions': {}, 'defaultFormatter': {'scss': 'prettier', 'css': 'prettier', 'ts': 'none', 'sass': 'sass-formatter', 'less': 'prettier', 'js': 'none', 'pug': 'prettier', 'postcss': 'prettier', 'html': 'prettier', 'stylus': 'stylus-supremacy'}, 'options': {'useTabs': False, 'tabSize': 4}, 'styleInitialIndent': False}, 'experimental': {'templateInterpolationService': True}, 'ignoreProjectWarning': False}}}
:: <-- LSP-vue client/registerCapability(0): {'registrations': [{'id': 'f9495a04-7a89-429d-be55-0062268043ea', 'registerOptions': {}, 'method': 'workspace/didChangeWorkspaceFolders'}]}
:: >>> LSP-vue 0: None
::  -> LSP-vue textDocument/didOpen: {...}
:: --> LSP-vue textDocument/documentColor(2): {'textDocument': {'uri': 'file:///Users/../edit.vue'}}
:: --> LSP-eslint initialize(1): {'workspaceFolders': [{'name': 'project', 'uri': 'file:///Users/rafal/workspace/web/project'}], 'clientInfo': {'name': 'Sublime Text LSP', 'version': '1.3.1'}, 'processId': 12390, 'capabilities': {'general': {'regularExpressions': {'engine': 'ECMAScript'}, 'markdown': {'version': '3.2.2', 'parser': 'Python-Markdown'}}, 'workspace': {'workspaceFolders': True, 'configuration': True, 'symbol': {'dynamicRegistration': True, 'tagSupport': {'valueSet': [1]}, 'symbolKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]}}, 'didChangeConfiguration': {'dynamicRegistration': True}, 'workspaceEdit': {'documentChanges': True, 'failureHandling': 'abort'}, 'didChangeWatchedFiles': {'dynamicRegistration': True}, 'executeCommand': {}, 'applyEdit': True}, 'experimental': {}, 'textDocument': {'selectionRange': {'dynamicRegistration': True}, 'codeLens': {'dynamicRegistration': True}, 'references': {'dynamicRegistration': True}, 'hover': {'dynamicRegistration': True, 'contentFormat': ['markdown', 'plaintext']}, 'documentSymbol': {'dynamicRegistration': True, 'tagSupport': {'valueSet': [1]}, 'hierarchicalDocumentSymbolSupport': True, 'symbolKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]}}, 'rename': {'dynamicRegistration': True, 'prepareSupport': True}, 'declaration': {'dynamicRegistration': True, 'linkSupport': True}, 'synchronization': {'dynamicRegistration': True, 'willSave': True, 'willSaveWaitUntil': True, 'didSave': True}, 'publishDiagnostics': {'relatedInformation': True, 'tagSupport': {'valueSet': [2, 1]}, 'dataSupport': True, 'codeDescriptionSupport': True, 'versionSupport': True}, 'documentHighlight': {'dynamicRegistration': True}, 'colorProvider': {'dynamicRegistration': True}, 'rangeFormatting': {'dynamicRegistration': True}, 'formatting': {'dynamicRegistration': True}, 'signatureHelp': {'dynamicRegistration': True, 'signatureInformation': {'parameterInformation': {'labelOffsetSupport': True}, 'documentationFormat': ['markdown', 'plaintext']}}, 'definition': {'dynamicRegistration': True, 'linkSupport': True}, 'completion': {'dynamicRegistration': True, 'completionItemKind': {'valueSet': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]}, 'completionItem': {'tagSupport': {'valueSet': [1]}, 'snippetSupport': True, 'deprecatedSupport': True, 'resolveSupport': {'properties': ['detail', 'documentation', 'additionalTextEdits']}, 'documentationFormat': ['markdown', 'plaintext']}}, 'codeAction': {'dynamicRegistration': True, 'codeActionLiteralSupport': {'codeActionKind': {'valueSet': ['quickfix', 'refactor', 'refactor.extract', 'refactor.inline', 'refactor.rewrite', 'source.organizeImports']}}, 'resolveSupport': {'properties': ['edit']}, 'dataSupport': True}, 'onTypeFormatting': {'dynamicRegistration': True}, 'typeDefinition': {'dynamicRegistration': True, 'linkSupport': True}, 'implementation': {'dynamicRegistration': True, 'linkSupport': True}}, 'window': {'workDoneProgress': True, 'showDocument': {'support': True}, 'showMessage': {'messageActionItem': {'additionalPropertiesSupport': True}}}}, 'rootPath': '/Users/rafal/workspace/web/project', 'initializationOptions': {}, 'rootUri': 'file:///Users/rafal/workspace/web/project'}
:: <-- LSP-vue client/registerCapability(1): {'registrations': [{'id': 'f939c846-6dcb-450a-8f64-0cae066e675f', 'registerOptions': {'documentSelector': [{'language': 'vue'}]}, 'method': 'textDocument/formatting'}]}
:: >>> LSP-vue 1: None
:: <-- LSP-vue window/workDoneProgress/create(2): {'token': 'eeb89378-02e6-481e-8b6d-9e5197bf6e66'}
:: >>> LSP-vue 2: None
LSP-eslint: ESLint server running in node v12.20.2
:: <-  LSP-eslint window/logMessage: {'type': 3, 'message': 'ESLint server running in node v12.20.2'}
:: <<< LSP-eslint 1: {'capabilities': {'workspace': {'workspaceFolders': {'supported': True}}, 'executeCommandProvider': {'commands': ['eslint.applySingleFix', 'eslint.applySuggestion', 'eslint.applySameFixes', 'eslint.applyAllFixes', 'eslint.applyDisableLine', 'eslint.applyDisableFile', 'eslint.openRuleDoc']}, 'textDocumentSync': {'change': {'syncKind': 2}, 'didClose': {}, 'save': {'includeText': False}, 'didOpen': {}}, 'codeActionProvider': {'codeActionKinds': ['quickfix', 'source.fixAll.eslint']}}}
::  -> LSP-eslint initialized: {}
::  -> LSP-eslint workspace/didChangeConfiguration: {'settings': {'quiet': False, 'rulesCustomizations': [{'rule': 'semi', 'severity': 'info'}], 'onIgnoredFiles': 'off', 'nodePath': None, 'format': False, 'codeActionOnSave': {'mode': 'all', 'enable': True}, 'packageManager': 'npm', 'validate': ['javascript', 'javascriptreact'], 'probe': ['javascript', 'javascriptreact', 'typescript', 'typescriptreact', 'html', 'vue', 'markdown'], 'codeAction': {'disableRuleComment': {'location': 'separateLine', 'enable': True}, 'showDocumentation': {'enable': True}}, 'options': {}, 'run': 'onType'}}
::  -> LSP-eslint textDocument/didOpen: {...}
:: --> LSP-vue textDocument/documentColor(3): {'textDocument': {'uri': 'file:///Users/../edit.vue'}}
:: <-- LSP-eslint client/registerCapability(0): {'registrations': [{'id': 'ca9248f0-0a7f-41e4-9d41-00d6f3cd81d6', 'registerOptions': {}, 'method': 'workspace/didChangeConfiguration'}]}
:: >>> LSP-eslint 0: None
:: <-- LSP-eslint client/registerCapability(1): {'registrations': [{'id': '7560ac36-73ff-43a7-8e08-6245740f52ed', 'registerOptions': {}, 'method': 'workspace/didChangeWorkspaceFolders'}]}
:: >>> LSP-eslint 1: None
:: <-- LSP-eslint workspace/configuration(2): {'items': [{'scopeUri': 'file:///Users/../edit.vue', 'section': ''}]}
:: >>> LSP-eslint 2: [{'quiet': False, 'rulesCustomizations': [{'rule': 'semi', 'severity': 'info'}], 'onIgnoredFiles': 'off', 'nodePath': None, 'format': False, 'codeActionOnSave': {'mode': 'all', 'enable': True}, 'packageManager': 'npm', 'validate': 'probe', 'workspaceFolder': {'name': 'project', 'uri': 'file:///Users/rafal/workspace/web/project'}, 'codeAction': {'disableRuleComment': {'location': 'separateLine', 'enable': True}, 'showDocumentation': {'enable': True}}, 'options': {}, 'run': 'onType'}]
:: <-- LSP-eslint eslint/confirmESLintExecution(3): {'libraryPath': '/Users/rafal/workspace/web/project/node_modules/eslint/lib/api.js', 'uri': 'file:///Users/../edit.vue', 'scope': 'local'}
:: >>> LSP-eslint 3: 4
LSP-eslint: ESLint library loaded from: /Users/rafal/workspace/web/project/node_modules/eslint/lib/api.js
:: <-  LSP-eslint window/logMessage: {'type': 3, 'message': 'ESLint library loaded from: /Users/rafal/workspace/web/project/node_modules/eslint/lib/api.js'}
LSP-vue: [INFO ] Find node_modules paths in /Users/rafal/workspace/web/project - 1530ms
:: <-  LSP-vue $/progress: {'value': {'title': 'Load project: /Users/rafal/workspace/web/project', 'kind': 'begin'}, 'token': 'eeb89378-02e6-481e-8b6d-9e5197bf6e66'}
:: <-  LSP-vue window/logMessage: {'type': 4, 'message': '[INFO ] Find node_modules paths in /Users/rafal/workspace/web/project - 1530ms'}
:: <-  LSP-eslint textDocument/publishDiagnostics: {'diagnostics': [], 'uri': 'file:///Users/../edit.vue'}
:: --> LSP-vue textDocument/codeAction(4): {'context': {'diagnostics': []}, 'textDocument': {'uri': 'file:///Users/../edit.vue'}, 'range': {'end': {'character': 0, 'line': 0}, 'start': {'character': 0, 'line': 0}}}
:: --> LSP-eslint textDocument/codeAction(2): {'context': {'diagnostics': []}, 'textDocument': {'uri': 'file:///Users/../edit.vue'}, 'range': {'end': {'character': 0, 'line': 0}, 'start': {'character': 0, 'line': 0}}}
:: <-  LSP-eslint eslint/status: {'uri': 'file:///Users/../edit.vue', 'state': 1}
:: <<< LSP-eslint 2: []
LSP-vue: [INFO ] Loaded typescript@4.2.4 from /Users/rafal/workspace/web/project/node_modules/typescript.
:: <-  LSP-vue window/logMessage: {'type': 4, 'message': '[INFO ] Loaded typescript@4.2.4 from /Users/rafal/workspace/web/project/node_modules/typescript.'}
LSP-vue: [INFO ] Loaded prettier@1.19.1 from /Users/rafal/workspace/web/project/node_modules/prettier.
LSP-vue: [INFO ] Loaded bundled @starptech/prettyhtml.
:: <-  LSP-vue window/logMessage: {'type': 4, 'message': '[INFO ] Loaded prettier@1.19.1 from /Users/rafal/workspace/web/project/node_modules/prettier.'}
:: <-  LSP-vue window/logMessage: {'type': 4, 'message': '[INFO ] Loaded bundled @starptech/prettyhtml.'}
LSP-vue: [INFO ] Loaded bundled prettier-eslint.
LSP-vue: [INFO ] Loaded bundled prettier-tslint.
LSP-vue: [INFO ] Loaded bundled stylus-supremacy.
:: <-  LSP-vue window/logMessage: {'type': 4, 'message': '[INFO ] Loaded bundled prettier-eslint.'}
:: <-  LSP-vue window/logMessage: {'type': 4, 'message': '[INFO ] Loaded bundled prettier-tslint.'}
:: <-  LSP-vue window/logMessage: {'type': 4, 'message': '[INFO ] Loaded bundled stylus-supremacy.'}
LSP-vue: [INFO ] Loaded bundled @prettier/plugin-pug.
:: <-  LSP-vue window/logMessage: {'type': 4, 'message': '[INFO ] Loaded bundled @prettier/plugin-pug.'}
:: <-  LSP-vue $/progress: {'value': {'kind': 'end'}, 'token': 'eeb89378-02e6-481e-8b6d-9e5197bf6e66'}
:: <<< LSP-vue 2: []
:: <<< LSP-vue 3: []
:: <<< LSP-vue 4: []
:: <-  LSP-vue textDocument/publishDiagnostics: {'diagnostics': [], 'uri': 'file:///Users/../edit.vue'}

Also, you should remove the config key from your custom settings. I'd recommend installing LSP-json so that you get diagnostics informing you about incorrect settings.

rchl commented 3 years ago

Actually I have "vetur.useWorkspaceDependencies": true, enabled. Without it I get messages like:

LSP-vue: [INFO ] Find node_modules paths in /Users/me/project - 530ms
LSP-vue: [INFO ] Loaded bundled typescript@4.2.3.
LSP-vue: [INFO ] Loaded bundled prettier.
LSP-vue: [INFO ] Loaded bundled @starptech/prettyhtml.
LSP-vue: [INFO ] Loaded bundled prettier-eslint.
LSP-vue: [INFO ] Loaded bundled prettier-tslint.
LSP-vue: [INFO ] Loaded bundled stylus-supremacy.
LSP-vue: [INFO ] Loaded bundled @prettier/plugin-pug.

So basically I think something goes a bit wrong when it detects project dependencies.

rchl commented 3 years ago

I'd recommend installing LSP-json so that you get diagnostics informing you about incorrect settings.

Well, I forgot to update the schema. Released new version now with the fix (372375a6e320037525e9d08a2084a88d48ca707e).

bjesus commented 3 years ago

Oh, my bad - I forgot I had to open the whole project so Vetur can read the settings. Doing this, removing config, and adding vetur.useWorkspaceDependencies": true - made it all work. Thank you very much! 🙏