Git Product home page Git Product logo

Comments (8)

AndrewRadev avatar AndrewRadev commented on August 27, 2024

Multibyte characters are tricky :). I should remember to test my plugins with them more often.

I've pushed some commits that should fix this, could you check it out and confirm that it works now?

from switch.vim.

zhaocai avatar zhaocai commented on August 27, 2024

The update works OK now.

one more thing I notice is case matching. True is switched to false

from switch.vim.

AndrewRadev avatar AndrewRadev commented on August 27, 2024

There's really no way to somehow automatically detect capitalization. The plugin attemts to do a substitution, and that respects your ignorecase option. But even if you have ignorecase on, Vim has no way of matching the T in true to F in false automatically. I could write the built-in pattern so that it handles that, but that would probably make it too complicated, especially if I try to respect all patterns like that.

Still, the True and False case is probably important for Python at least. I added a built-in for ['True', 'False'], so this particular example should work capitalize correctly now.

from switch.vim.

zhaocai avatar zhaocai commented on August 27, 2024

There's really no way to somehow automatically detect capitalization.

I disagree on this one.

I have some sample code from vim-cycle:

function! s:imitate_case(text, reference) "{{{
  if a:reference =~# '^\u*$'
    return toupper(a:text)
  elseif a:reference =~# '^\U*$'
    return tolower(a:text)
  else
    let uppers = substitute(a:reference, '\U', '0', 'g')
    let new_text = tolower(a:text)
    while uppers !~ '^0\+$'
      let index = match(uppers, '[^0]')
      if len(new_text) < index
        break
      endif
      let new_text = substitute(new_text, '\%' . (index + 1) . 'c[a-z]', toupper(new_text[index]), '')
      let uppers = substitute(uppers, '\%' . (index + 1) . 'c.', '0', '')
    endwhile
    return new_text
  endif
endfunction "}}}

from neocomplcache

  " Convert words.
  if neocomplcache#is_text_mode() "{{{
    let convert_candidates = filter(copy(complete_words),
          \ "get(v:val, 'neocomplcache__convertable', 1)")

    if a:cur_keyword_str =~ '^\l\+$'
      for keyword in convert_candidates
        let keyword.word = tolower(keyword.word)
        let keyword.abbr = tolower(keyword.abbr)
      endfor
    elseif a:cur_keyword_str =~ '^\u\+$'
      for keyword in convert_candidates
        let keyword.word = toupper(keyword.word)
        let keyword.abbr = toupper(keyword.abbr)
      endfor
    elseif a:cur_keyword_str =~ '^\u\l\+$'
      for keyword in convert_candidates
        let keyword.word = toupper(keyword.word[0]).
              \ tolower(keyword.word[1:])
        let keyword.abbr = toupper(keyword.abbr[0]).
              \ tolower(keyword.abbr[1:])
      endfor
    endif
  endif"}}}

from switch.vim.

AndrewRadev avatar AndrewRadev commented on August 27, 2024

Imagine I have the following definition:

let g:switch_definitions =
      \ [
      \   {
      \     '\<\(\k\+\)\>': '@_\1',
      \     '@_\(\k\+\)\>': '\1',
      \   }
      \ ]

This changes between fooBarBaz and @_fooBarBaz. This could be useful in coffeescript if you want to switch between local functions and class-level "private" functions (starting with an underscore). It's a bit of a weird example, I suppose, but I think it's fairly realistic. If I use the s:imitateCase function to normalize the case of the result based on the original, then from fooBarBaz, I'd get @_fOobArbaz. Which is really quite wrong.

This is what I meant when I said that it's impossible to detect capitalization -- it's impossible to correctly detect capitalization, since in many cases, capitalization holds meaning.

For an example closer to what vim-cycle would do, consider ['nextAll', 'siblings']. Both of these words are jquery methods that have a similar functionality, so I think it's fairly realistic that you'd want to switch between them. Normalizing with s:imitateCase leads to nextAll being transformed into subsTitute.

It may be possible to normalize case on a pattern-by-pattern basis, but I'd have to change the API and somehow put in a flag, and I don't think that this is a case that would be worth the complexity.

Incidentally, I didn't actually see this function in the vim-cycle source code. Is it from an older version? There's a TODO item in the README that says "Operate on non-lowercase text and retain case", so I assume the author doesn't really have something working quite yet.

As for neocomplcache, I haven't really experimented with the code, but it seems like it's simply attempting to match two strings together, by trying out foo, FOO, and Foo, which is a much simpler case by far. I may be wrong, though, in which case -- could you explain it in more detail?

A thread on reddit that discusses this can be found here. The general thoughts there are that you can define the very patterns to hold the information. They get a bit complicated, but that's a lot better than any automatic transformation that I can think of on the plugin side. There's also a keepcase plugin mentioned, but I'd rather not attempt any weird heuristics to get this working.

from switch.vim.

zhaocai avatar zhaocai commented on August 27, 2024

The answer depends on the grand goal of this plugin.

For this particular case, I am thinking of context (filetype, syntax, etc. ) to trigger the switch.

  • text context: syntax [Comment, String, ...], filetype [text, markdown, rst, tex, ...]
  • code context: filetype[ruby, python, ...]

Capitalization match is triggered only for text context. and I am not talking about weird heuristics to imitate case; check capitalization for the first letter usually is good enough.

from switch.vim.

AndrewRadev avatar AndrewRadev commented on August 27, 2024

I am not talking about weird heuristics to imitate case; check capitalization for the first letter usually is good enough.

You should have mentioned that earlier :). Both examples you gave seem to do more than just that, so I assumed you wanted a more complete solution.

In any case, this still can't be done for all patterns. The solution you propose -- to separate "text" and "code" doesn't look viable to me at all. There are a lot of file formats out there, many of which are not built into Vim. It's completely impossible for me to separate them, especially "comment" and "text" areas in code. Spellchecking is a good example of something that works exactly that way, but that's encoded in the syntax files, each of which is maintained by a different person. It's not feasible for me to attempt to do something like this in the plugin. I could make the separation a job for the user -- make them set variables with filetypes they use as "text" and as "code", but that goes in the realm of yak shaving, I think -- you need to set a list of filetypes in order for the plugin to figure out if it's code or text in order to take care of capitalization... And even so, there's no guarantee that you wouldn't want a particular pattern to behave differently. Making the transformation automatic for one or the other case means taking the freedom of the user to choose one or the other.

As for the user's choice in this matter, it's possible to simply duplicate the patterns:

let g:switch_definitions =
      \ [
      \   { '\Ctrue': 'false', '\Cfalse': 'true' },
      \   { '\CTrue': 'False', '\CFalse': 'True' },
      \ ]

Admittedly, this makes them more complicated and makes it impossible to use the shorthand form of the plugin. A compromise I propose is something like this:

let g:switch_definitions =
      \ [
      \   ['normalize_case', ['true', 'false']]
      \ ]

And this pattern would capitalize the first letter if it has to. I can probably implement it easily by simply duplicating the patterns -- getting the form I described above.

Considering I'm probably going to make more complicated ways to define patterns anyway, this seems like a reasonable start. I could add additional transformation flags (that I may think of in the future) in the list, having the last item be the actual switch definition. That way, the shorthand version remains the same, but if you want some additional tweaks to the pattern, you can do that as well in this new form. What do you think?

from switch.vim.

bootleq avatar bootleq commented on August 27, 2024

Hi, just for information:
vim-cycle with s:imitate_case was from another plugin with the same name https://github.com/bootleq/vim-cycle

I've asked @mjbrownie and @zef for borrowing the name, and we felt okay at that time.

from switch.vim.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.