Code Monkey home page Code Monkey logo

vim-sexp's Introduction

             o8o
             '"'
 oooo    ooooooo ooo. .oo.  .oo.        .oooo.o  .ooooo. oooo    ooooo.ooooo.
  `88.  .8' `888 `888P"Y88bP"Y88b      d88(  "8 d88' `88b `88b..8P'  888' `88b
   `88..8'   888  888   888   888 8888 `"Y88b.  888ooo888   Y888'    888   888
    `888'    888  888   888   888      o.  )88b 888    .o .o8"'88b   888   888
     `8'    o888oo888o o888o o888o     8""888P' `Y8bod8P'o88'   888o 888bod8P'
                                                                     888
                                                                    o888o

Introduction

Vim-sexp brings the Vim philosophy of precision editing to S-expressions.

Requirements

  • Vim 7.3+

  • vim-repeat (optional)

    Enables use of the . command for repeating change operations in vim-sexp, as well as repeating builtin operations with vim-sexp's text objects.

Definitions

A COMPOUND FORM is a region of text delimited by a pair of ( and ), [ and ], or { and }.

A STRING is a contiguous region of text whose syntax name matches the Vim pattern \vstring|regex|pattern.

A COMMENT is a region of text whose syntax name matches the Vim pattern comment. Line comments that are indented but on successive lines are considered to be a single comment.

MACRO CHARACTERS are the special set of leading characters expanded by a Lisp reader at read-time. These differ by language, and default to Scheme's macro character set in an unknown FileType.

An ELEMENT is the

  • current STRING if the cursor is in a STRING
  • current COMMENT if the cursor is in a COMMENT
  • current COMPOUND FORM if the cursor is on a paired structural bracket
  • current sequence of MACRO CHARACTERS and the following ELEMENT if the cursor is on a MACRO CHARACTER
  • current contiguous sequence of non-whitespace, non-bracket characters otherwise

An ELEMENT always includes any leading MACRO CHARACTERS.

Mappings

All default mappings can be changed via the g:sexp_mappings variable. Every mapping is available as a <Plug> mapping, which may be used for any purpose.

Users who desire more explicit, opt-in configuration should refer to :help sexp-explicit-mappings.

Comprehensive documentation is available at :help vim-sexp. The following is a brief summary.

Text Object Selections (visual, operator-pending)

Text object selections refer to text around the cursor.

  • The af and if objects select COMPOUND FORMS.
  • The aF and iF objects select top-level COMPOUND FORMS.
  • The as and is objects select STRINGS.
  • The ae and ie objects select ELEMENTS.

Text Object Motions (normal, visual, operator-pending)

Text object motions move the cursor in normal mode, extend selections in visual mode, and refer to text defined by the movement of the cursor in operator-pending mode.

  • The ( and ) motions move the cursor to the nearest paired structural bracket.
  • The <M-b> and <M-w> motions move the cursor ELEMENT-wise, ending on an element head. Analogous to builtin b and w motions.
  • The g<M-e> and <M-e> motions move the cursor ELEMENT-wise, ending on an element tail. Analogous to builtin ge and e motions.
  • The [[ and ]] motions move the cursor to an adjacent top-level ELEMENT.
  • The [e and ]e mappings select an adjacent ELEMENT.

Indent Commands (normal)

  • == indents the current COMPOUND FORM without moving the cursor
  • =- indents the current top-level COMPOUND FORM without moving the cursor

Wrap Commands (normal, visual)

Wrap commands wrap the current COMPOUND FORM, ELEMENT, or visual selection and place the cursor at the head or tail of the newly created COMPOUND FORM.

If g:sexp_insert_after_wrap is set (true by default), insert mode is entered after wrapping.

  • <LocalLeader>i and <LocalLeader>I wrap the current COMPOUND FORM with ( and ).
  • <LocalLeader>[ and <LocalLeader>] wrap the current COMPOUND FORM with [ and ].
  • <LocalLeader>{ and <LocalLeader>} wrap the current COMPOUND FORM with { and }.
  • <LocalLeader>W and <LocalLeader>w wrap the current ELEMENT with ( and ).
  • <LocalLeader>e[ and <LocalLeader>e] wrap the current ELEMENT with [ and ].
  • <LocalLeader>e{ and <LocalLeader>e} wrap the current ELEMENT with { and }.

List Manipulation (normal, visual)

List manipulation commands change the structure of COMPOUND FORMS. If these commands are called from visual mode, the selection is used in place of the current COMPOUND FORM or ELEMENT.

  • <LocalLeader>@ splices the current COMPOUND FORM into its parent.
  • <LocalLeader>o raises the current COMPOUND FORM to replace the enclosing COMPOUND FORM.
  • <LocalLeader>O raises the current ELEMENT to replace the enclosing COMPOUND FORM.
  • <M-k> and <M-j> swap the position of the current COMPOUND FORM with a sibling ELEMENT.
  • <M-h> and <M-l> swap the position of the current ELEMENT with a sibling ELEMENT.
  • <M-S-j> and <M-S-k> emit the terminal ELEMENTS of the current COMPOUND FORM.
  • <M-S-h> and <M-S-l> capture adjacent ELEMENTS into the current COMPOUND FORM.

The last two commands are also known as barfage and slurpage in paredit.el.

Cursor Insertion (normal)

  • <LocalLeader>h inserts the cursor at the head of the current COMPOUND FORM
  • <LocalLeader>l inserts the cursor at the tail of the current COMPOUND FORM

If inserting at the head, a space is conditionally appended after the opening bracket so that any typed characters will be separated from the next element.

Insert Mode Mappings (insert)

Vim-sexp does intelligent bracket and double quote insertion like paredit.el. Unlike ParEdit, deletion of brackets that would cause an imbalance is not prevented, except in the limited case of <BS> below.

  • (, [, and { produce a closing bracket and also insert spaces as necessary to separate the new COMPOUND FORM from adjacent non-compound ELEMENTS.
  • ), ], and } insert closing brackets when the corresponding opening bracket is unpaired. If the opening bracket is paired, jump to the next paired instance of the closing bracket.
  • " inserts a pair of double quotes, unless the cursor is currently in a STRING.
  • <BS> deletes an adjacent pair of (), [], {}, and "" when deleting the opening bracket or quote. Normal backspace otherwise.

These insert mode mappings can be disabled with:

let g:sexp_enable_insert_mode_mappings = 0

vim-sexp's People

Contributors

bpstahlman avatar frangio avatar guns avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vim-sexp's Issues

maintaining balance of parenthesis

Are there any plans of implementing the feature? Or is it left out on purpose? The lack of it is keeps me from switching from vim-paredit.

Missing several very useful paredit commands

I love vim-sexp, and am very excited about the possibility of using vim-sexp instead of paredit; having used it for several weeks, however, there are several useful paredit commands I really miss: e.g.,
paredit-forward-down
paredit-forward-up
paredit-backward-down
paredit-backward-up
paredit-split-sexp
paredit-join-sexps
paredit-splice-sexp-killing-backward
paredit-splice-sexp-killing-forward

If vim-sexp had these commands, I think it would be "no contest" between it and vim paredit (and possibly even emacs paredit)...

vim repeat sets could include insert-mode text

e.g.

<localleader>wdefn should be the repeat#set text instead of <localleaderw alone. This makes it easier to repeat that kind of change, and would align the behavior with a and i for example.

Element motion problems (does not work with selection=exclusive in gvim)

Maybe these things are just happening for me, because of some other plugin or settings, but...

In the following, |x| represents the cursor position, and <x> represents a visual selection.

Starting with (+ 10|0|0) and doing vae results in (+< 100>0).
Starting with (+ sym|b|ol) and doing vae results in (+< symbo>l).
Starting with something "a str|i|ng" and doing vae results in something< "a string>".

There are similar problems with ie motions. In summary, the element motion does not quite work for the last element in a list, or if the element is a string.

Please add count to ae and ie

The ae and ie object selectors would be more useful if you could prepend a count. BTW, I'm really liking vim-sexp.

Incompatibility with tree-sitter

Hey there! Love the plugin, it makes working in Clojure a breeze.

I've run into a small problem where if I use nvim-treesitter and leave additional_vim_regex_highlighting = false (meaning all syntax highlighting is provided by TS), then the " insert maps don't work correctly anymore, as s:syntax_match can't find any highlighting under the cursor.

Would it be feasible to add some awareness of TS and use that when appropriate?

I know than a solution is to set additional_vim_regex_highlighting = true, but it's not ideal because the two highlights clash and don't look great together.

paste?

I just want to make sure I am getting the most out of this very useful plugin. My question is, if I want to move an element from one form to another it seems like I am left to deal with whitespace manually, eg:

(a form [with an ele|ment])
(target form)
;; daf
(a form)
(target form|)
;; p
(a form)
(another form[an element])

meaning I have to add the space between "form" and "[an element]".

And also, if I had put the cursor on the bracket and used dae, the paste would work as expected, i.e. (another form [an element])

License situation is problematic

The plugin claims to be under the "MIT" license: https://github.com/guns/vim-sexp/blob/master/plugin/sexp.vim#L12

However it's impossible for anyone looking to build upon (pieces of) your work to comply with this license. Assuming you meant this license:

Copyright (c) <year> <copyright holders>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Note that it says "The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software."
This plugin itself violates this requirement, and
it's impossible to copy this license to derivative works because the notice wasn't in the original to
begin with.

Cannot insert unbalanced paren

The insert mode mappings by default don't allow me to match unbalanced parentheses (| denotes the cursor).
What I have: ([(|])
What I want: ([()|])
What I get: ([(]|)

Rather than recognizing that the internal paren is unmatched, and therefore allowing me to insert, it moves my cursor to the closing ). This comment in the source explains that it's a tradeoff made for performance reasons. Is there any way to get the desired functionality without taking the performance hit? I'm happy to do the work if you have a solution in mind.

Respect "local-additions" convention in magic first line of vim-sexp.txt

@guns, when I consult the table of contents at :h local-additions vim-sexp isn't there. This is because vim-sexp does not respect the convention documented at :h write-local-help: The first line of a plugin doc is magic, and the proper format is

*myplugin.txt*<Tab>This is the tagline for my plugin

In practice, hardly anybody uses <Tab>. (I do: to make sure "the entries line up nicely".)

I have a creeping feeling that I'm turning into the GitHub resident respect-local-additions-magic-first-line-of-doc.txt zealot, but hey, we do what we do best, don't we? Feel free to disregard this end of the year (at least on my end) trifle.

Looking forward to using vim-sexp in the new year, nice work!

Do the <M-S-hjkl> mappings work natively on Mac?

Thanks for the great plugin.

I'm trying hard to get it to work on a mac in iterm2 with vim version 7.4.488.
My .vimrc is pretty big so I'm eliminating any possible conflicts by using a plain vanila .vimrc
with nothing in it but your plugin.
None of the <M mappings work for me.

Am I missing some obvious thing specific to Mac. Anybody else has/had this issue?

I saw that there is a possibility to set your own mappings using the 'sexp-explicit-mappings' directive.
But I like the default mappings so want to stick to those..

Thanks

Capture and emit should not treat comments as elements

When capturing tail on a top level form, capture will place the bracket at the end of subsequent comments. Similar behavior can be seen with emit-tail. This seems surprising to me as it unbalances forms. Capture and emit should probably ignore comments altogether and act on the next real element.

Given the following with the cursor on foo.

(foo) ;comment-a
bar
;; comment-b
zap

Capture tail twice should produce

(foo ;comment-a
bar
;; comment-b
zap)

Slurping and barfing changes cursor position

For example:

(f1 (f2 fC3 f4))

cursor position marked by C. After barfing once to the left, the cursor moves to the left paren:

(f1 f2 (Cf3 f4))

This is quite annoying compared to paredit in emacs. Is there an option to make the cursor stay where it was?

Thanks!

Easier navigation of subforms

I hope I'm not missing something obvious but navigating into (and out of) subforms seems to be more difficult than one would hope it would be in a Lisp. For example imagine the following Clojure code:

(defn some-function
  "Some
   docstring."
  [x]
  (if (= x 42)
    "That's the answer!"
    (str x " is not the answer")))

If the cursor is at |(defn (perhaps by way of using [[ or ]] to navigate) and one wanted to navigate into the function to add a parameter, for example but imagine introducing another let assignment, adjusting a condition, etc., how would one achieve this? Currently I believe you have to move the cursor into the form you wish to subnavigate and use the sibling motion keys but then of course this navigates elements and not forms.

Text Objects Don't Work

The plugin is loading, but then the text objects don't seem to work. If I understand correctly, I should be able to put my cursor inside of

(an sexp)

and type

daf

and it will delete it? Other bindings don't seem to really work either. Matched parentheses are inserted though during insert mode.

Broken parenthesis closing

I have a very annoying problem with the closing parenthesis magic from vim-sexp. I have the following .clj file:

(defn foo []
  (println "Hello"))

I do the following after opening the file:

  • Hit o to insert a line before the println
  • type (bla
  • Hit ESC to exit edit mode
  • Do lx to delete the closing brace
  • a to enter append mode

No matter what I do, i can't seem to close the opening brace anymore, it always jumps to the last line.

I use MacVim 7.4, no other plugins installed (except pathogen).

Include macro characters in COMPOUND FORM

Clojure uses reader macros like @ and # before forms. I think it makes sense to include macro characters as a part of the COMPOUND FORM to make it more consistent with ELEMENT behavior
In the current implementation ( | denotes cursor, <> denotes vim command):

@(re-|frame/subscribe [::the-sub])
<daf>
|@
;; but
(@a|bc de fg)
<dae>
(|de fg)

After my suggestion:

@(re-|frame/subscribe [::the-sub])
<daf>
|
;; but
(@a|bc de fg)
<dae>
(|de fg)

visual mode mappings are created indiscriminately

Many of the default g:sexp_mappings do not make sense in visual mode (correct me if I'm wrong). To avoid visual-mode mappings, extra configuration steps are needed.

If I configure sexp mappings like this:

let g:sexp_mappings = { 'sexp_insert_at_list_head': '<I' }

vim-sexp creates nmap and xmap mappings, but sexp_insert_at_list_head is not really useful in visual-mode.

In order to avoid this, I must do this:

nmap <I     <Plug>(sexp_insert_at_list_head)
let g:sexp_mappings = { 'sexp_insert_at_list_head': '' }

Perhaps the plugin could be more discriminating about which maps it creates in visual-mode.

Capturing elements like emacs slurp

Hi, great plugin!

There are two features of slurping in emacs paredit mode that I really miss in vim-sexp. The cheat sheet here shows how it behaves and below is why it feels more natural for me to use than the vim equivalents.
http://emacswiki.org/emacs/PareditCheatsheet (See Barfage & Slurpage)

Take the example of introducing a let for the map result, after typing (something xs)

(let [xs])
(map to-x ys)
(something xs)

The first thing I miss, is that slurping an element does not move the cursor (or if at the end of a line it moves to the prev char). It makes it far easier to quickly drop out of insert, put forms in the right place and then back to insert without losing focus of where you were working. In the example, I can finish the vector and easily slurp in the map I was working on with ...[xs])<ESC><slurp><slurp>. With vim-sexp captures, it's painful to do this as I need to navigate to the previous form after each slurp.

The second thing is that slurping will recursively slurp up the tree if there's nothing to slurp in the current form. In the example, my cursor can be on the s (the last non-closing char I need to type) and I can just slurp three times to get the map into the binding and the final form into the body.

Would it be possible to change capture to behave in this way or introduce slurp and barf calls with this behavior?

I would have loved to do a PR but I've never written a vim plugin and I felt like I was way over my head when I dove into this.

Interference when inserting parenthesis in Julia code

I'm writing Julia using the Julia-vim plugin. When I also have Vim-Sexp loaded, any parenthesis or bracket (([{) inserted in a Julia (*.jl) file is autoindented by one space - a space is inserted before the parenthesis right after it's typed. Commenting Vim-Sexp out makes the issue go away.

I understand the description is light on details and the problem might as well be in the Julia-Vim plugin rather than Vim-Sexp. However, I think this issue might be helpful to anyone who runs into the same problem. Maybe someone will actually be able to figure it out!

Please make a video...

This plugin looks cool but I am having difficulty figuring out how to use it. I see that a video is on your todo list. Any chance of getting that done?

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.