AndrewRadev / sideways.vim

A Vim plugin to move function arguments (and other delimited-by-something items) left and right.
http://www.vim.org/scripts/script.php?script_id=4171
MIT License
479 stars 9 forks source link

Support for [a; b] #32

Closed ghost closed 5 years ago

ghost commented 5 years ago

[a; b; c; d] syntax is generally used in OCaml (or only OCaml) and when I try to use it it does not work. Any solution?

AndrewRadev commented 5 years ago

I've added support for the syntax for ocaml filetypes. It's generally not difficult to implement it, although it's unfortunately not documented. Here's the commit, if you'd like to take a look: https://github.com/AndrewRadev/sideways.vim/commit/976cfaa7f27ca6add422611d810e1dd839b9fc78

That said, I don't write ocaml, so it's hard for me to tell if there's any edge cases I've missed. Try it out and let me know?

ghost commented 5 years ago

Okay

ghost commented 5 years ago

It does not work as I already updated. There is an edge case like this:

let my_list = [1, 2, 3; 4, 5, 6; 7, 8, 9]

This is equivalent to

my_list = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]

So it should think every ; as the end of a tuple.

NOTE: Every group (or tuple) should have equivalent size. For example

(* Invalid *)
let my_list = [1, 2, 3; 4, 5; 6];;
Error: This expression has type 'a * 'b
       but an expression was expected of type int * int * int

(* Valid *)
let my_list = [1, 2, 3; 4, 5, 6; 7, 8, 9];;
val my_list : (int * int * int) list = [(1, 2, 3); (4, 5, 6); (7, 8, 9)]
AndrewRadev commented 5 years ago

Hm, this is tricky. First off, in my experience, the list does work in terms of being delimited by ;:

let my_list = [1, 2, 3; 4, 5, 6; 7, 8, 9]
(* with cursor on 1, 2, 3, move right: *)
let my_list = [4, 5, 6; 1, 2, 3; 7, 8, 9]

The problem is, within the "1, 2, 3" and "4, 5, 6", and so on, blocks, the plugin doesn't move the individual tuple items around. Unfortunately, I can't imagine how to get that working without breaking the ;-moving. If the cursor is on "1", the plugin couldn't tell if you need to move it within the ,-list, or if you need to move "1, 2, 3" within the ;-list. This isn't a problem with [(1, 2, 3); ..., because you can put your cursor on the ( to move the tuple around the ;-list, or on 1 to move that number within the tuple.

Plus, on a purely technical level, the plugin looks for start and end delimiters to anchor itself, and there are no delimiters in this case. Even if I were to come up with some rule like "if the cursor is on ,, move the entire list", I have no tools to express this logic in the plugin's machinery.

Basically, this is one edge case I can't see a way to fix.

ghost commented 5 years ago

So, should we add moving the things selected visually? Like

[1, 2, 3]
|___|
Visual
:SidewaysRight<CR>

[3, 1, 2]
    |___|
   Visual

Isnt this will be kool :p

ghost commented 5 years ago

Also there is list and arrays in OCaml and both syntax is different. Thus, you should declare one like [| and one like [

AndrewRadev commented 5 years ago

So, should we add moving the things selected visually? Like

It's an interesting idea. Could be useful for some situations, in general. But I don't think it works around the problem -- even if I select "1, 2", this still doesn't indicate whether I want to slide those around the "1, 2, 3" tuple, or the entire tuple around the list/array. I could imagine some logic like "if the entire 1, 2, 3 is selected, then move that around", but I can't figure out how I'd implement it.

Also there is list and arrays in OCaml and both syntax is different. Thus, you should declare one like [| and one like [

Is there a difference in the delimiters? Or would it still be written like [|1; 2; 3]?

ghost commented 5 years ago

[|1, 2, 3|] for Arrays, [1, 2, 3] for lists.

AndrewRadev commented 5 years ago

Arrays should also be working now.

ghost commented 5 years ago

The support for arrays is bugged.

[|1,2, 3|]
(* to *)
[|a, c|, b]
AndrewRadev commented 5 years ago

Okay, I just realized the example you gave above uses commas, and I'm confused now. How do , and ; work in ocaml? I'm googling for syntax examples, but I can't see an explanation. Are all of these valid?

[|1; 2; 3|]
[1; 2; 3]
[|1, 2, 3|]
[1, 2, 3]

Could you maybe give me a link to some documentation that explains these in more detail?

ghost commented 5 years ago

All of these are valid.

https://v1.realworldocaml.org/v1/en/html/lists-and-patterns.html

If you want learn OCaml you should learn Real world OCaml

AndrewRadev commented 5 years ago

Okay, but all of these use ; as a separator. The comma is a tuple separator? So [|1, 2, 3|] is actually equivalent to [|(1, 2, 3)|]? Is that correct?

Regarding this example:

[|1,2, 3|]
(* to *)
[|a, c|, b]

I suppose you mean [|1, 2, 3|] -> [|1, 3|, 2]? But I don't get this result -- for commas, it simply doesn't do anything, because I've defined list/array separators as ;. Could you provide an example with more detail. Something like:

The way I've implemented it right now:

Do you get different results for any of these?

ghost commented 5 years ago

SEMICOLONS VERSUS COMMAS Unlike many other languages, OCaml uses semicolons to separate list elements in lists rather than commas. Commas, instead, are used for separating elements in a tuple. If you try to use commas in a list, you'll see that your code compiles but doesn't do quite what you might expect:

["OCaml", "Perl", "C"];;
- : (string * string * string) list = [("OCaml", "Perl", "C")]

In particular, rather than a list of three strings, what we have is a singleton list containing a three-tuple of strings.

This example uncovers the fact that commas create a tuple, even if there are no surrounding parens. So, we can write:

1,2,3;;
- : int * int * int = (1, 2, 3)

to allocate a tuple of integers. This is generally considered poor style and should be avoided. Same rules for Arrays ([|...|])

Tuples Just use commas :)

ghost commented 5 years ago

So you did say right.

AndrewRadev commented 5 years ago

Right, so, what I've currently done is, for this example:

[(1, 2); (3, 4)]

With the cursor on a (, the pairs of (1, 2) and (3, 4) get swapped. With the cursor on any of the numbers, the numbers in the tuple get swapped.

In this scenario:

[1, 2; 3, 4]

There's no way to move the elements of the internal tuple, because they're not delimited. It's a limitation of the plugin, but according to that documentation you pasted, it's considered "poor style" anyway, so I hope it's not a big practical problem.

All of this should currently work for [| |] arrays as well.

I think this is the best I can do in terms of ocaml support. Do you think we can close the issue for the moment?

ghost commented 5 years ago

Sure!