diff options
| author | Mitermayer Reis <mitermayer.reis@gmail.com> | 2023-10-10 12:02:33 +1100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-10-10 12:02:33 +1100 |
| commit | d10bdd15af8a61eff9d279bd2815b4192506d1c0 (patch) | |
| tree | 5cf0fd4ce325299bb3d989563ac862525e99b846 | |
| parent | 5e6cca21e12587c02e32a06bf423519eb1e9f1b2 (diff) | |
| parent | ba1d24036b35df89728344a46ed1f2006fbd1255 (diff) | |
| download | vim-prettier-d10bdd15af8a61eff9d279bd2815b4192506d1c0.tar.xz | |
Merge pull request #348 from victorspt/fix/consider_option_version
Fix/consider option version
| -rw-r--r-- | autoload/prettier/resolver/config.vim | 294 | ||||
| -rw-r--r-- | autoload/prettier/utils/buffer.vim | 14 | ||||
| -rw-r--r-- | autoload/prettier/utils/version.vim | 25 | ||||
| -rw-r--r-- | plugin/prettier.vim | 2 | ||||
| -rw-r--r-- | tests/vimscript/version.vim | 126 |
5 files changed, 411 insertions, 50 deletions
diff --git a/autoload/prettier/resolver/config.vim b/autoload/prettier/resolver/config.vim index 9a18444..7a9d813 100644 --- a/autoload/prettier/resolver/config.vim +++ b/autoload/prettier/resolver/config.vim @@ -3,55 +3,51 @@ function! prettier#resolver#config#resolve(config, hasSelection, start, end) abort " Allow params to be passed as json format " convert bellow usage of globals to a get function o the params defaulting to global - " TODO: Use a list, filter() and join() to get a nicer list of args. - let l:cmd = s:Flag_use_tabs(a:config) . ' ' . - \ s:Flag_tab_width(a:config) . ' ' . - \ s:Flag_print_width(a:config) . ' ' . - \ s:Flag_parser(a:config) . ' ' . - \ s:Flag_range_delimiter(a:config, a:hasSelection, a:start, a:end) . ' ' . - \ ' --semi=' . - \ get(a:config, 'semi', g:prettier#config#semi) . - \ ' --single-quote=' . - \ get(a:config, 'singleQuote', g:prettier#config#single_quote) . - \ ' --bracket-spacing=' . - \ get(a:config, 'bracketSpacing', g:prettier#config#bracket_spacing) . - \ ' --jsx-bracket-same-line=' . - \ get(a:config, 'jsxBracketSameLine', g:prettier#config#jsx_bracket_same_line) . - \ ' --arrow-parens=' . - \ get(a:config, 'arrowParens', g:prettier#config#arrow_parens) . - \ ' --trailing-comma=' . - \ get(a:config, 'trailingComma', g:prettier#config#trailing_comma) . - \ ' --config-precedence=' . - \ get(a:config, 'configPrecedence', g:prettier#config#config_precedence) . - \ ' --prose-wrap=' . - \ get(a:config, 'proseWrap', g:prettier#config#prose_wrap) . - \ ' --html-whitespace-sensitivity ' . - \ get(a:config, 'htmlWhitespaceSensitivity', g:prettier#config#html_whitespace_sensitivity) . - \ ' --stdin-filepath="'.simplify(expand('%:p')).'"' . - \ ' --require-pragma=' . - \ get(a:config, 'requirePragma', g:prettier#config#require_pragma) . - \ ' --end-of-line=' . - \ get(a:config, 'endOfLine', g:prettier#config#end_of_line) . - \ ' --loglevel error '. - \ ' --stdin ' + let l:config_and_sel = { + \ 'config': a:config, + \ 'hasSelection': a:hasSelection, + \ 'start': a:start, + \ 'end': a:end} + + let l:cmd = ' ' . s:Get_current_version_flags(s:FLAGS) + \ ->map(function('s:Map_flag_to_cmd_part', [l:config_and_sel])) + \ ->values() + \ ->join(' ') return l:cmd endfunction -" Returns either '--range-start X --range-end Y' or an empty string. -function! s:Flag_range_delimiter(config, partialFormatEnabled, start, end) abort - if (!a:partialFormatEnabled) +" Mapper functions: {{{ +" Returns either '--range-start X' or an empty string. +function! s:Flag_range_start(config_and_sel, ...) abort + if (!a:config_and_sel.hasSelection) + return '' + endif + + let l:rangeStart = + \ prettier#utils#buffer#getCharRangeStart(a:config_and_sel.start) + + return '--range-start=' . l:rangeStart +endfunction + +" Returns either '--range-end Y' or an empty string. +function! s:Flag_range_end(config_and_sel, ...) abort + if (!a:config_and_sel.hasSelection) return '' endif - let l:range = prettier#utils#buffer#getCharRange(a:start, a:end) + let l:rangeEnd = + \ prettier#utils#buffer#getCharRangeEnd(a:config_and_sel.end) - return '--range-start=' . l:range[0] . ' --range-end=' . l:range[1] + return '--range-end=' . l:rangeEnd endfunction " Returns '--tab-width=NN' -function! s:Flag_tab_width(config) abort - let l:value = get(a:config, 'tabWidth', g:prettier#config#tab_width) +function! s:Flag_tab_width(config_and_sel, ...) abort + let l:value = get( + \ a:config_and_sel.config, + \ 'tabWidth', + \ g:prettier#config#tab_width) if (l:value ==# 'auto') let l:value = prettier#utils#shim#shiftwidth() @@ -61,8 +57,12 @@ function! s:Flag_tab_width(config) abort endfunction " Returns either '--use-tabs' or an empty string. -function! s:Flag_use_tabs(config) abort - let l:value = get(a:config, 'useTabs', g:prettier#config#use_tabs) +function! s:Flag_use_tabs(config_and_sel, ...) abort + let l:value = get( + \ a:config_and_sel.config, + \ 'useTabs', + \ g:prettier#config#use_tabs) + if (l:value ==# 'auto') let l:value = &expandtab ? 'false' : 'true' endif @@ -75,8 +75,11 @@ function! s:Flag_use_tabs(config) abort endfunction " Returns '--print-width=NN' or '' -function! s:Flag_print_width(config) abort - let l:value = get(a:config, 'printWidth', g:prettier#config#print_width) +function! s:Flag_print_width(config_and_sel, ...) abort + let l:value = get( + \ a:config_and_sel.config, + \ 'printWidth', + \ g:prettier#config#print_width) if (l:value ==# 'auto') let l:value = &textwidth @@ -90,8 +93,11 @@ function! s:Flag_print_width(config) abort endfunction " Returns '--parser=PARSER' or '' -function! s:Flag_parser(config) abort - let l:value = get(a:config, 'parser', g:prettier#config#parser) +function! s:Flag_parser(config_and_sel, ...) abort + let l:value = get( + \ a:config_and_sel.config, + \ 'parser', + \ g:prettier#config#parser) if (l:value !=# '') return '--parser=' . l:value @@ -99,3 +105,203 @@ function! s:Flag_parser(config) abort return '' endif endfunction + +" Returns '--stdin-filepath=' concatenated with the full path of the opened +" file. +function! s:Flag_stdin_filepath(...) abort + let l:current_file = simplify(expand('%:p')) + return '--stdin-filepath="' . l:current_file . '"' +endfunction + +" Returns '--loglevel error' or '--log-level error'. +function! s:Flag_loglevel(config_and_sel, flag, props) abort + let l:level = 'error' + return a:flag . ' ' . l:level +endfunction + +" Returns '--stdin'. +function! s:Flag_stdin(...) abort + return '--stdin ' +endfunction + +" Returns a flag name concantenated with its value in the JSON config object or +" in the default global Prettier config. +function! s:Concat_value_to_flag(config_and_sel, flag, props) abort + let l:global_value = get(g:, 'prettier#config#' . a:props.global_name, "") + + let l:value = get(a:config_and_sel.config, a:props.json_name, l:global_value) + + return a:flag . '=' . l:value +endfunction + +" Maps a flag name to a part of a command. +function! s:Map_flag_to_cmd_part(config_and_sel, flag, props) abort + return a:props.mapper(a:config_and_sel, a:flag, a:props) +endfunction +" }}} + +" Constants: {{{ +let s:concat_value = function('s:Concat_value_to_flag') + +let s:FLAGS = { + \ '--use-tabs': { + \ 'json_name': 'useTabs', + \ 'global_name': 'use_tabs', + \ 'mapper': function('s:Flag_use_tabs')}, + \ '--tab-width': { + \ 'json_name': 'tabWidth', + \ 'global_name': 'tab_width', + \ 'mapper': function('s:Flag_tab_width')}, + \ '--print-width': { + \ 'json_name': 'printWidth', + \ 'global_name': 'print_width', + \ 'mapper': function('s:Flag_print_width')}, + \ '--parser': { + \ 'json_name': 'parser', + \ 'global_name': 'parser', + \ 'mapper': function('s:Flag_parser')}, + \ '--range-start': { + \ 'json_name': '', + \ 'global_name': '', + \ 'mapper': function('s:Flag_range_start')}, + \ '--range-end': { + \ 'json_name': '', + \ 'global_name': '', + \ 'mapper': function('s:Flag_range_end')}, + \ '--semi': { + \ 'json_name': 'semi', + \ 'global_name': 'semi', + \ 'mapper': s:concat_value}, + \ '--single-quote': { + \ 'json_name': 'singleQuote', + \ 'global_name': 'single_quote', + \ 'mapper': s:concat_value}, + \ '--bracket-spacing': { + \ 'json_name': 'bracketSpacing', + \ 'global_name': 'bracket_spacing', + \ 'mapper': s:concat_value}, + \ '--bracket-same-line': { + \ 'json_name': 'bracketSameLine', + \ 'global_name': 'bracket_same_line', + \ 'mapper': s:concat_value, + \ 'since': '2.4.0'}, + \ '--jsx-bracket-same-line': { + \ 'json_name': 'jsxBracketSameLine', + \ 'global_name': 'jsx_bracket_same_line', + \ 'mapper': s:concat_value, + \ 'deprecated': '2.4.0'}, + \ '--arrow-parens': { + \ 'json_name': 'arrowParens', + \ 'global_name': 'arrow_parens', + \ 'mapper': s:concat_value, + \ 'since': '1.9.0'}, + \ '--trailing-comma': { + \ 'json_name': 'trailingComma', + \ 'global_name': 'trailing_comma', + \ 'mapper': s:concat_value}, + \ '--config-precedence': { + \ 'json_name': 'configPrecedence', + \ 'global_name': 'config_precedence', + \ 'mapper': s:concat_value}, + \ '--prose-wrap': { + \ 'json_name': 'proseWrap', + \ 'global_name': 'prose_wrap', + \ 'mapper': s:concat_value, + \ 'since': '1.8.2'}, + \ '--html-whitespace-sensitivity': { + \ 'json_name': 'htmlWhitespaceSensitivity', + \ 'global_name': 'html_whitespace_sensitivity', + \ 'mapper': s:concat_value, + \ 'since': '1.15.0'}, + \ '--stdin-filepath': { + \ 'json_name': '', + \ 'global_name': '', + \ 'mapper': function('s:Flag_stdin_filepath')}, + \ '--require-pragma': { + \ 'json_name': 'requirePragma', + \ 'global_name': 'require_pragma', + \ 'mapper': s:concat_value, + \ 'since': '1.7.0'}, + \ '--end-of-line': { + \ 'json_name': 'endOfLine', + \ 'global_name': 'end_of_line', + \ 'mapper': s:concat_value, + \ 'since': '1.15.0'}, + \ '--loglevel': { + \ 'json_name': '', + \ 'global_name': '', + \ 'mapper': function('s:Flag_loglevel'), + \ 'deprecated': '3.0.0'}, + \ '--log-level': { + \ 'json_name': '', + \ 'global_name': '', + \ 'mapper': function('s:Flag_loglevel'), + \ 'since': '3.0.0'}, + \ '--stdin': { + \ 'json_name': '', + \ 'global_name': '', + \ 'mapper': function('s:Flag_stdin'), + \ 'deprecated': '2.0.0'}} +" }}} + +" Flags selector: {{{ +" Returns the argument string with unprintable characters represented in Vim +" internal format removed from both ends. +function! s:Trim_internal_unprintable(text) abort + let l:char_patt = '\%(\%(\^\m.\)\|\%(<\x\x>\)\)\{}' + let l:patt_at_ends = '^' . l:char_patt . '\|' . l:char_patt . '$' + let l:trimmed_text = a:text->substitute(l:patt_at_ends, '', 'g') + return l:trimmed_text +endfunction + +" Returns the version of the Prettier CLI as a string. +function! s:Get_prettier_cli_version() abort + let l:output = '' + redir => l:output + silent call prettier#PrettierCli('--version') + redir END + " The shell sends the string with whitespaces at both ends. + let l:prettier_cli_version = s:Trim_internal_unprintable(trim(l:output)) + return l:prettier_cli_version +endfunction + +" Returns 1 if the version of the flag argument is compatible with the +" version argument, otherwise returns 0. +function! s:Filter_uncompatible_flag(version, _, flag) abort + let l:is_deprecated = exists('a:flag.deprecated') + \ && prettier#utils#version#Is_greater_or_equal_version( + \ a:version, a:flag.deprecated) + if l:is_deprecated + return 0 + endif + + let l:is_added = !exists('a:flag.since') + \ || prettier#utils#version#Is_greater_or_equal_version( + \ a:version, a:flag.since) + if !l:is_added + return 0 + endif + return 1 +endfunction + +" Returns an object with the flags from the argument object that are compatible +" with the version of the Prettier CLI being used. +function! s:Get_current_version_flags(flags) abort + let l:prettier_version = s:Get_prettier_cli_version() + + let l:is_cached = exists('b:prettier_cached_flags') + \ && exists('b:prettier_last_used_cli_version') + \ && b:prettier_last_used_cli_version ==# l:prettier_version + if l:is_cached + return b:prettier_cached_flags->copy() + endif + + let l:compatible_flags = a:flags->copy()->filter( + \ function('s:Filter_uncompatible_flag', [l:prettier_version])) + let b:prettier_cached_flags = l:compatible_flags + let b:prettier_last_used_cli_version = l:prettier_version + return l:compatible_flags->copy() +endfunction +" }}} + +" vim:foldmethod=marker:foldmarker={{{,}}}: diff --git a/autoload/prettier/utils/buffer.vim b/autoload/prettier/utils/buffer.vim index 3125bcc..922a0db 100644 --- a/autoload/prettier/utils/buffer.vim +++ b/autoload/prettier/utils/buffer.vim @@ -61,10 +61,12 @@ function! s:getCharPosition(line, col) abort return line2byte(a:line) + (a:col - 2) endfun -" Returns [start, end] byte range when on visual mode -function! prettier#utils#buffer#getCharRange(startSelection, endSelection) abort - let l:range = [] - call add(l:range, s:getCharPosition(a:startSelection, col("'<"))) - call add(l:range, s:getCharPosition(a:endSelection, col("'>"))) - return l:range +" Return the start byte when on visual mode +function! prettier#utils#buffer#getCharRangeStart(startSelection) abort + return s:getCharPosition(a:startSelection, col("'<")) +endfunction + +" Return the end byte when on visual mode +function! prettier#utils#buffer#getCharRangeEnd(endSelection) abort + return s:getCharPosition(a:endSelection, col("'>")) endfunction diff --git a/autoload/prettier/utils/version.vim b/autoload/prettier/utils/version.vim new file mode 100644 index 0000000..3cbbb73 --- /dev/null +++ b/autoload/prettier/utils/version.vim @@ -0,0 +1,25 @@ +" Returns 1 if the first argument is the greater version, returns 0 if the +" arguments are the same version, or returns -1 if the first argument is the +" lesser version. +function! prettier#utils#version#Compare_versions(a, b) abort + let [l:a_major, l:a_minor, l:a_patch; l:rest] = a:a->split('\D') + \ ->map('str2nr(v:val)') + let [l:b_major, l:b_minor, l:b_patch; l:rest] = a:b->split('\D') + \ ->map('str2nr(v:val)') + let l:is_a_greater = + \ l:a_major > l:b_major + \ || (l:a_major == l:b_major && l:a_minor > l:b_minor) + \ || (l:a_major == l:b_major && l:a_minor == l:b_minor + \ && l:a_patch > l:b_patch) + let l:is_a_equal_b = + \ l:a_major == l:b_major + \ && l:a_minor == l:b_minor + \ && l:a_patch == l:b_patch + return l:is_a_greater ? 1 : (l:is_a_equal_b ? 0 : -1) +endfunction + +" Returns 1 if the first argument is greater than or equal to the second, +" otherwise returns 0. +function! prettier#utils#version#Is_greater_or_equal_version(a, b) abort + return prettier#utils#version#Compare_versions(a:a, a:b) != -1 +endfunction diff --git a/plugin/prettier.vim b/plugin/prettier.vim index b85195e..7ef774b 100644 --- a/plugin/prettier.vim +++ b/plugin/prettier.vim @@ -113,6 +113,8 @@ let g:prettier#config#bracket_spacing = get(g:,'prettier#config#bracket_spacing' " default: 'false' " See more: https://prettier.io/docs/en/options.html#jsx-brackets let g:prettier#config#jsx_bracket_same_line = get(g:,'prettier#config#jsx_bracket_same_line', 'false') +" This option has another name for Prettier versions 2.4.0 and higher: +let g:prettier#config#bracket_same_line = get(g:, 'prettier#config#bracket_same_line', 'false') " avoid wrapping a single arrow function param in parens " avoid|always diff --git a/tests/vimscript/version.vim b/tests/vimscript/version.vim new file mode 100644 index 0000000..9718011 --- /dev/null +++ b/tests/vimscript/version.vim @@ -0,0 +1,126 @@ +" To run the tests in this script, first add the vim-prettier plugin and let +" Vim load it, then uncomment the last line in this script, and source this +" file in Vim with the command +" ":source <file-path>" where <file-path> is the path to this file, e.g. +" ":source %". + +function! s:Test_version_comparison_greater_case() abort + echomsg 'Testing version comparison, greater case.' + + let l:ver_1 = '2.7.3' + let l:ver_2 = '0.9.8' + let l:value = prettier#utils#version#Compare_versions(l:ver_1, l:ver_2) + let l:expected = 1 + return assert_equal( + \ l:value, + \ l:expected, + \ 'Expected ' . l:expected . ' but received ' . l:value + \ . ' instead.') +endfunction + +function! s:Test_version_comparison_lesser_case() abort + echomsg 'Testing version comparison, lesser case.' + + let l:ver_1 = '3.9.5' + let l:ver_2 = '10.5.2' + let l:value = prettier#utils#version#Compare_versions(l:ver_1, l:ver_2) + let l:expected = -1 + return assert_equal( + \ l:value, + \ l:expected, + \ 'Expected ' . l:expected . ' but received ' . l:value + \ . ' instead.') +endfunction + +function! s:Test_version_comparison_equal_case() abort + echomsg 'Testing version comparison, equal case.' + + let l:ver_1 = '8.2.4' + let l:ver_2 = '8.2.4' + let l:value = prettier#utils#version#Compare_versions(l:ver_1, l:ver_2) + let l:expected = 0 + return assert_equal( + \ l:value, + \ l:expected, + \ 'Expected ' . l:expected . ' but received ' . l:value + \ . ' instead.') +endfunction + +function! s:Test_is_greater_or_equal_version_greater_case() abort + echomsg 'Testing function that checks if is lesser version, greater case.' + + let l:ver_1 = '3.8.1' + let l:ver_2 = '0.2.9' + let l:value = prettier#utils#version#Is_greater_or_equal_version( + \ l:ver_1, l:ver_2) + let l:expected = 1 + return assert_equal( + \ l:value, + \ l:expected, + \ 'Expected ' . l:expected . ' but received ' . l:value + \ . ' instead.') +endfunction + +function! s:Test_is_greater_or_equal_version_lesser_case() abort + echomsg 'Testing function that checks if is lesser version, lesser case.' + + let l:ver_1 = '7.2.8' + let l:ver_2 = '15.1.6' + let l:value = prettier#utils#version#Is_greater_or_equal_version( + \ l:ver_1, l:ver_2) + let l:expected = 0 + return assert_equal( + \ l:value, + \ l:expected, + \ 'Expected ' . l:expected . ' but received ' . l:value + \ . ' instead.') +endfunction + +function! s:Test_is_greater_or_equal_version_equal_case() abort + echomsg 'Testing function that checks if is lesser version, lesser case.' + + let l:ver_1 = '4.12.185' + let l:ver_2 = '4.12.185' + let l:value = prettier#utils#version#Is_greater_or_equal_version( + \ l:ver_1, l:ver_2) + let l:expected = 1 + return assert_equal( + \ l:value, + \ l:expected, + \ 'Expected ' . l:expected . ' but received ' . l:value + \ . ' instead.') +endfunction + +function! s:Run_tests() abort + let v:errors = [] + + let l:test_functions = [ + \ function('s:Test_version_comparison_greater_case'), + \ function('s:Test_version_comparison_lesser_case'), + \ function('s:Test_version_comparison_equal_case'), + \ function('s:Test_is_greater_or_equal_version_greater_case'), + \ function('s:Test_is_greater_or_equal_version_lesser_case'), + \ function('s:Test_is_greater_or_equal_version_equal_case')] + + let l:results_as_returned = l:test_functions->copy()->map('v:val()') + let l:results_as_text = l:results_as_returned + \ ->copy() + \ ->map('v:key + 1 .. '': '' .. (v:val ? "failed" : "passed")') + + let l:has_failed_test = v:errors->len() > 0 + \ || l:results_as_returned->index(1) >= 0 + if l:has_failed_test + echoerr 'The tests failed.' + echoerr 'Results:' + echoerr l:results_as_text->join('; ') + echoerr 'Errors:' + echoerr v:errors->join('; ') + else + echomsg 'The tests were completed successfully.' + echomsg 'Results:' + echomsg l:results_as_text->join('; ') + endif +endfunction + +" Uncomment the next line to run the tests. +" call s:Run_tests() |
