Coder Social home page Coder Social logo

evil-smartparens's Introduction

Evil smartparens MELPA Build Status

Evil smartparens is a minor mode which makes evil play nice with smartparens.

Installation

I highly recommend installing evil-smartparens through elpa.

It's available on melpa:

M-x package-install evil-smartparens

Put this in your .emacs or init.el:

(add-hook 'smartparens-enabled-hook #'evil-smartparens-mode)

this will turn on evil-smartparens whenever smartparens is activated. This might not be what you want, as you're likely to get some surprises when working in buffers running say markdown-mode. If you just want to enable evil-smartparens in certain modes you can do something like this:

(add-hook 'clojure-mode-hook #'evil-smartparens-mode)

Note: If you wish to be protected from introducing unbalanced pairs by editing commands which delete regions, what you want is smartparens-strict-mode.

Features

The goal of evil smartparens is to do what you mean, instead of just erroring out when smartparens-strict-mode is active.

When only smartparens-mode is active, the only keys that are rebound are those imitating the functionality of sp-kill-sexp: Y, D and C.

In the examples below smartparens-strict-mode is active, | indicates the position of the cursor, and [ and ] delimit the visual selection:

Deleting text

The goal here is to just modify the region so it is safe. Most of the times this means shrinking the region.

dW

(|sp--get-pair-list-context)

And I hit dW I will see:

()

dd

(let| ((foo 1.01))
  (frobnicate foo))

And I hit dd then nothing will happen. But If I move down a line:

(let ((foo 1.01))
  (fr|obnicate foo))

And I hit dd then I will see:

(let ((foo 1.01))
  )

vd

(progn
[ (foo)
  (bar 'baz)
  (qux (quux (corge (grault "garply")))))]

Here I have used linewise selection and sloppily selected a bunch of unbalanced text. When I hit d I will see:

(progn
  )

This is so nice when you just want to get rid of something in a let binding.

D

D works like sp-kill-sexp with a universal prefix.

(let ((foo 1.01))
  (-> foo |(bar baz) qux (quux corge grault) garply))

and I hit D I will see:

(let ((foo 1.01))
  (-> foo |))
(foo "|bar baz"
     quux)

becomes:

(foo ""
     quux)
(|foo "bar baz"
     quux)

becomes

(
     quux)
|(foo ""
     quux)

Will kill everything.

c and y

c works just like d C just like D but also enters insert mode. y works just like d except it doesn't actually remove anything from the buffer.

Known limitations

Quite a bit of work is done to ensure region is OK. This means we can run into performance issues. The variable evil-smartparens-threshold controls how large region should be before we cop out. The most common cases should be quite fast (regions limited to the delimiters found in lisp-like languages), but the more exotic delimiters use a much slower code path. On slow computers it might make sense to decrease evil-smartparens-threshold. In any event, it prevents checking entire files when we're copying out from emacs.

Escape hatches

The function evil-sp-override, which by default is bound to o, in visual-state provides an escape hatch, out of evil-smartparens and back to evil, when it's called before another command.

I've also opted not to rebind r and R so these can also be used to get rid of stuff that would otherwise cause evil-smartparens to barf.

Is it any good?

Yes

demo.gif

The demo showcases c, with a sloppy unbalanced selection, D (in two contexts) and dd.

Contribute

Please send help! There is a suite of tests that I'd like you to add to whenever a bug is fixed or a new feature is added. If you don't do this I'm likely to break your code when I stumble around the codebase.

To fetch the test dependencies, install cask if you haven't already, then:

$ cd /path/to/evil-smartparens
$ cask

Run the tests with:

$ make test

License

Copyright (C) 2015 Lars Andersen

Author: Lars Andersen [email protected] Keywords: evil smartparens

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

evil-smartparens's People

Contributors

accidentalrebel avatar alexmurray avatar andyleejordan avatar ane avatar blak3mill3r avatar expez avatar grammati avatar jgkamat avatar purcell avatar robbyoconnor avatar syohex avatar tarsius 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

evil-smartparens's Issues

Emacs hangs completely when using D

I am editing fairly complex .cpp file,
when I use D (evil-sp-delete-line, which should delete until end of line (in a smart way))
emacs hangs and I have to kill it.
I am using 25.3.2 on Linux.
I happens quite consistently (few times per day),
but it hard to come up with minimal example.

Deleting in strings seems not to work well with smartparens

First off, thanks for this package! I've enjoyed it a lot.

I've noticed that I frequently end up with undeletable characters inside of strings -- for example, I can type this in emacs-lisp-mode:

")"

which Smartparens allows, but then evil-smartparens won't let me delete that closing square bracket because "it will leave the buffer unbalanced" (even though it won't). I took a quick look at the test suite and it appears that protecting against unbalanced parens inside string literals is intentional -- is that the case? If so, could that be made configurable so it could be turned off? I'd be happy to work on a pull request if so.

(When evil and evil-smartparens are both disabled, Smartparens allows deletions of braces within strings, for what it's worth.)

x doesn't work like in evil

Having this on seems to break the xp operation, i.e. transposing two characters. It's like what I delete with x doesn't get copied, and so when I paste with p it keeps pasting the previous clipboard content.

"D" key example in README.md incorrect

I just recently installed this package. I was going through the examples when I noticed an incorrect result.

The readme says that this:

(let ((foo 1.01))
  (-> foo |(bar baz) qux (quux corge grault) garply))

will become this after hitting D:

(let ((foo 1.01))
  (-> foo |)

But the above is missing a closing parenthesis so it should be this:

(let ((foo 1.01))
  (-> foo |))

Sorry for the nitpick but it did threw me off guard when I was going through it.

I would like to ask permission if I can make a pull request with a fix to it. I have yet to do my very first pull request and I think this is a good and simple start.

Thanks!

not compatible with evil-surround

when enable evil-smartparens,
the function of evil-surround:
"Change surrounding

You can change a surrounding with cs."

not work properly.

For instance,
(te|st)

when cs({

it should be

{te|st}

but when evil-smartparens enabled, it became

{ (t }est)

evil-sp-delete-line behavior

Using spacemacs, with evil, smart-parens, smart-parens-strict, and evil-smartparens enabled in an emacs-lisp buffer

(defun test-sexp ()
   |(sexp-A
     (A-first-child))
    (sexp-B)
    (sexp-C
     (C-first-child)
     (C-second-child)))

My expectation is that "D" should delete sexp-A and it's child, but leave sexp-B and sexp-C, instead D results in:

(defun test-sexp ()
    |)

Is this intended? Others are noticing the same behavior, the discussion is located syl20bnr/spacemacs#2747

Spacemacs Emacs 29.2

Not sure if this is a Spacemacs, Emacs, or evil-smartparens.

Error loading autoloads: (file-missing Cannot open load file No such file or directory c:/Users/USERNAME/AppData/Roaming/.emacs.d/elpa/29.2/develop/evil-smartparens-20171210.1513/evil-smartparens-autoloads)

sp-region-ok gives nil on haskell pragmas

A haskell pragma looks like
{-# LANGUAGE ScopedTypeVariables #-}
and smartparens-haskell sets "{-#" "#-}" as a pair in haskell-mode.

But any evil-smartparens op on these gives "That would leave the buffer unbalanced", which seems to be because sp-region-ok (used by e.g. evil-sp--new-ending) gives nil on these haskell pragmas.

I see sp-region-ok is only used in one place by smartparens itself, and sp-kill-sexp in fact works fine here, while evil-sp-delete errors out here.

Cannot delete lines if quotes are in comments

If I have the following code (in a c file):

// |they're here.

and I run evil-sp-change-line

I would expect the comment to be deleted, but instead, I get the following message:

sp-get-string: End of buffer

I don't know if this is easy to fix (or possibly out of scope), because I don't know of a way of figuring out if we are in a comment block from the inside. For example:

| // they're here.

works fine...

Safe operators stop before unmatched apostrophe in elisp comments when using smartparens-config

With smartparens-strict-mode and (require 'smartparens-config), safe operators can behave incorrectly on unmatched apostrophes in emacs lisp comments. For example, dd (with point anywhere) on the following line:

;; doesn't that

leaves:

't that

Seems to be caused by the `' pair, here in smartparens-config:

(sp-with-modes (-difference sp-lisp-modes sp-clojure-modes)
  ;; also only use the pseudo-quote inside strings where it serve as
  ;; hyperlink.
  (sp-local-pair "`" "'"
                 :when '(sp-in-string-p
                         sp-in-comment-p)
                 :unless '(sp-lisp-invalid-hyperlink-p)
                 :skip-match (lambda (ms mb me)
                               (cond
                                ((equal ms "'")
                                 (or (sp-lisp-invalid-hyperlink-p "`" 'navigate '_)
                                     (not (sp-point-in-string-or-comment))))
                                (t (not (sp-point-in-string-or-comment)))))))

026d4a3 needs reworking

026d4a3 needs to be more carefully thought out - it only partially fixed the issue. More specifically, as soon as evil-smartparens is loaded at all (in any buffer), the DEL key is rebound for every buffer that has evil-smartparens-mode on (since the binding uses the global variable evil-smartparens-mode-map), regardless of whether smartparens-strict-mode is on in that buffer.

I've found a temporary work around thorugh (make-variable-buffer-local 'evil-smartparens-mode-map), but that's kind of hackish and doesn't feel like a final solution. One option could be to go the general-predicate-dispatch way and bind DEL to something like (macro-expansion of general-predicate-dispatch, could probably just use an if statement for our purposes):

(evil-define-key 'insert evil-smartparens-mode-map
  (kbd "DEL") '(menu-item "" nil :filter
                          (lambda
                            (&optional _)
                            (cond
                             (smartparens-strict-mode 'sp-backward-delete-char)
                             (t nil)))))

Which essentially actively checks if smartparens-strict-mode is enabled and does nothing if not.

evil-sp-delete-line not playing well with one-line comments

How to reproduce

  1. In any programming language mode make a pair of parenthesis with the body spanning multiple lines.
  2. Make a one-line comment inside of the body
  3. Place the cursor before the comment and press "D"
(|+ ;;This is a comment
  1
  1)

Expected result

The region from the point to the end of the line is deleted

(|
  1
  1)

Actual result

The region from the point to the end of the s-expression is deleted.

(|)

Further thoughts

The results seem to be consistent across programming languages (I have tried Scheme, Emacs-Lisp, Python and Java). Multiline-comments like /* */ are handled just fine, even if they only span one line.

evil-sp-delete-line deleting closing parenthesis

How to reproduce

Create a pair of parenthesis and place the point such that it is on the same line with nothing but whitespace in between it and the closing parenthis. Then press D.

( Test |   ) Test

Expected Result

The region from the point up to the closing parenthesis is deleted:

( Test |) Test

Actual Result

The region from the point up to and including the closing parenthesis is deleted:

( Test | Test

Slurpage and Barfage

Are slurpage and barfage not implemented? There is no mention of it in README.md and I am unable to figure out how to do it with evil-smartparens.

Slurpage and barfage would be very nice to have.

Thanks!

Problem with evil-sp-change indent-according-to-mode

Bug

I have a strange (new-ish) issue. When using an operator such as ce in certain modes (so far, markdown-mode and ledger-mode), upon entering insert state, two unexpected things happen: a) the line indents up completely unindented, and b), the cursor is left at the beginning of the line.

Trace

When I remove the call to indent-according-to-mode at the end of evil-sp-change, the issue no longer reproduces (of course, this isn't a solution).

Examples

In ledger-mode, where <P> is the location of the point (the point being on the next letter):

2016/02/13 * Whole Foods                                                        
     Expenses:<P>Food:Groceries                   $49.93                            
     Liabilities:Credit:Citi 

When I ce at any point in that snippet (for example, on the F of Food), here's what happens:

2016/02/13 * Whole Foods                                                        
Expenses:<P>:Groceries                   $49.93                                    
     Liabilities:Credit:Andy:Citi

In markdown-mode:

## Net <P>profit                                                                   

Again, ce:

<P>## Net                                                                          

Versions

  • GNU Emacs 24.5.1 (x86_64-apple-darwin15.2.0) of 2015-12-19 on elcapitanvm.local, installed via Homebrew
  • OS X El Capitan 10.11.3 (15D21)
  • evil 20160312.1042
  • evil-smartparens 20151126.124
  • smartparens 20160225.705
  • ledger-mode 20160228.1734
  • markdown-mode 20160312.2335

Minor modes

I have a lot of minor modes:

Enabled minor modes: Async-Bytecomp-Package Auto-Compile-On-Load                 
Auto-Compile-On-Save Auto-Composition Auto-Compression Auto-Encryption           
Company Company-Flx Dtrt-Indent Electric-Indent Evil Evil-Commentary             
Evil-Escape Evil-Local Evil-Matchit Evil-Smartparens Evil-Surround               
File-Name-Shadow Flx-Ido Flycheck Font-Lock Fortune-Cookie Git-Gutter            
Global-Auto-Revert Global-Company Global-Evil-Matchit                            
Global-Evil-Surround Global-Flycheck Global-Font-Lock                            
Global-Git-Commit Global-Git-Gutter Global-Undo-Tree                             
Global-Whitespace-Cleanup Ido-Grid Ido-Ubiquitous Line-Number Menu-Bar           
Override-Global Popwin Recentf Shell-Dirtrack Show-Smartparens                   
Show-Smartparens-Global Smartparens Smartparens-Global                           
Smartparens-Global-Strict Smartparens-Strict Tooltip Transient-Mark              
Undo-Tree Which-Key Whitespace-Cleanup Winner

But I've tested with and without smartparens-strict-mode, smartparens-mode, electric-indent-mode, dtrt-indent-mode, etc. It's evil-smartparens, but I bet it's interacting with something else odd (as there haven't been any changes to this package recently).

evil-smartparens not playing nice with linewise operations

I'm trying to use the vim linewise delete operations (cc and dd) and evil-smartparens isn't acting the way I would expect. Your example for dd says that

(let | ((foo 1.01))
  (frobnicate foo))

using dd on this code with the cursor at the | should leave us with

(
  (frobnicate foo))

but instead I'm left with

  (frobnicate foo))

I'm on emacs 24.5 from homebrew

How about move out from multiple-nested parens with different types?

Sorry for my poor english, I suppose this should work on this situation.

(hello {:foo "foo"|:bar "bar"})   ;; | = cursor

After I press ) it should become:

(hello {:foo "foo" :bar "bar"})|

instead of

(hello {:foo "foo") :bar "bar"}) 

I think this is useful in strict-mode, because once i typed mistake ) it's very inconvenient delete the unmatched ).

Evil-smartparens overrides "o" in visual state

I don't know about you, but I consider this to be a bit of an issue, I use the default meaning of "o" fairly frequently. Please consider using another key for this.

Moreover, the binding is added in evil-sp--add-bindings, a function that whenever the mode is enabled (in every buffer). That shouldn't be necessary, the bindings should only have to be made once. The upshot of this is that I can't simply unbind the key once, either, I need to use a hook or an advise to do it, which is a little awkward. If you don't want to move the binding I'd appreciate if it was a little easier to change it.

Fix the tests on travis

The code is fine, but the tests are failing. It looks like evil-smartparens-mode isn't being activated properly in the tests.

these lines aren't doing what they should ๐Ÿ‘Ž

Could not get it to work at all

I followed the README, installed the MELPA package w/ Cask, enabled evil-smartparens-mode for emacs-lisp and clojure, and made absolutely sure I had removed all traces of paredit, evil-paredit, and clj-refactor which appears to depend on paredit in some way.

I get nothing, although I've confirmed that the evil-smartparens-mode is active, none of the examples work (they just blow away parens, e.g. dW inside a function call blows away the closing paren)

Any ideas? Or should I just start disabling bits of my config, or start from scratch... ugh

evil-sp-change behaves differently than sp-change outside its use case

To reproduce the issue start emacs -q, load and activate evil-mode, smartparens-strict-mode and evil-smartparens mode.

When sp-evil-change word or cw is called on text "|foo bar" what remains is "bar".

Without evil-smartparens-mode cw leaves " bar", meaning it does not delete the space after "foo".

So sp-evil-change is changing evil's behaviour in a case where it shouldn't. At least I don't see a reason for the difference.

I'm running emacs version 25.0.50.1 and the newest verions of evil, smartparens and evil-smartparens that el-get will give me.

Emacs hangs on haskell-mode when evil-smartparens is enabled

Hello, first let me thank you for this package, I've been using it for years without any issue at all, but now I'm experiencing an Emacs freeze and the only clue I have led me here. Let me explain:

When I'm in haskell-mode and want to yank to the end of line with Y emacs freezes, pressing C-g unfreezes it, it happens the same when using D or C. At first I didn't know what was the cause but I create this issue here because when I disable evil-smartparens-mode the problem goes away.

I've used toggle-debug-on-quit and this is what happens when emacs freezes:

Debugger entered--Lisp error: (quit)
  syntax-ppss(5925)
  sp--syntax-ppss(5925)
  sp-point-in-comment()
  sp-get-comment-bounds()
  sp-get-enclosing-sexp(1)
  sp-up-sexp(-1 nil)
  sp-backward-up-sexp()
  evil-sp--depth-at(3964)
  evil-sp--get-endpoint-for-killing()
  evil-sp-yank-line(3953 4014 line)
  funcall-interactively(evil-sp-yank-line 3953 4014 line)
  call-interactively(evil-sp-yank-line nil nil)
  command-execute(evil-sp-yank-line)

Why does this happen? I appreciate any help, Thanks!

That would leave the buffer unbalanced

Unable to delete a single parentheses when it it not balanced

For instance, I want to turn:

(setq a t)
(setq b t)

into

(setq a t
      b t)

This is not possible since when I backspace or C-d in emacs state or x in evil normal state, or mark the extra text to delete, it will fail and display

That would leave the buffer unbalanced

Or sometime this kind of unbalanced code would exist after I copy/paste:

(
 (
 ))  <-- a
)  <-- b

I need to delete the unbalanced parentheses, a or b, but deleting any of them would not be possible since it would fail and display

That would leave the buffer unbalanced

Currently I use M-x delete-char to manually delete it.

So how can I delete the single unbalanced parentheses using normal key like x or C-d or backspace?

backspace key just deletes a single character when I mark a string using Ctrl-space in insert state

I don't know this is the problem of spacemacs or evil-smartparens, I'll post this issue first.

When I'm in insert state in spacemacs, and use Ctrl-space to mark a string like vanilla emacs, and I'd like to delete this marked string, usually I just hit backspace, but backspace just delete a single character in spacemacs, and it's bound to sp-backward-delete-char.

So, how can I delete the string marked with Ctrl-space when I'm in insert state? (Please don't say that I SHOULD mark string in normal state.)

Unexpected register behavior with full line commands (dd cc yy)

When performing full line commands like dd, cc, and yy, the value that is placed into the register is inconsistent depending on whether there was 'extra' data on the line.

(+
  |(+ 1 2)
  (+ 3 4))

In this situation dd will place (+ 1 2)^J in the register so it will be pasted on a newline when hitting p.

(+
  (+ 1 2)
  |(+ 3 4))

In this situation dd will not add the ^J in the register leading to unexpected results when hitting p afterwards.

evil-smartparens can't handle multi-character ruby pairs like "def" "end".

When I try to delete code like

def echo(value)
  puts value
end

with 3dd, only the first two characters of def are deleted, instead of the whole three lines. If I use 3dd again, I'm still left with the final d of end. The behaviour is the same when yanking code.

I don't really care about smartparens handling these sorts of pairs, so I tried just disabling them with eval-after-load statements like

(eval-after-load 'smartparens-ruby (lambda () (sp-local-pair 'ruby-mode "def" nil :actions :rem)))

This disables auto-insertion of the pairs, but I still get the same problem when trying to delete and yank code.

I'd be grateful for a solution that either fixes evil-smartparens's handling of these pairs, or just allows me to fully disable them.

Is there any way to change the default S binding?

I am an amateur at elisp and with what I know, I could not change the S binding (bound to evil-sp-change-whole-line function. I use S for other purposes and wanted to know if there is a way to change this binding.

I use a use-package definition for evil-smartparens and its bind is not evil friendly, so I use general.el for consistent bindings. After that didn't work, I tried to just use the normal evil-define-key bindings. Those didn't work either. I tried to set the default binding to nil and set these bindings again inside (with-eval-after-load 'evil-smartparens) block but that didn't make any difference either. Finally, I created a function with just binding definitions and created a hook based on (add-hook 'evil-smartparens-mode-hook #'my-function) but that also didn't work.

I just want to know if I'm doing something wrong. If so, it would be very helpful if you can correct it. Thanks!

whitespace after daf and dab

Hi, This is a minor annoyance for me, but maybe there's something you can do about it. Here's an example, where I'm using . to represent spaces

;;.A.sentence.in.a.comment
(progn.(a).(sequence).(of).(commands))

If I daw on "sentence", I get

;;.A.in.a.comment
(progn.(a).(sequence).(of).(commands))

but daf on sequence then gives

;;.A.in.a.comment
(progn.(a)..(of).(commands))

Notice when I delete "sentence" it also deletes one space, but I'm left with two spaces between (a) and (of), which I typically then have to fix right away.

Maybe this is too complicated to fix, but if it's not, I'd appreciate it if the behavior with regards to whitespace leftover was consistent.

By the way I've been using this package for a while now, and it really makes editing lisp much more pleasant, so thank you.

Backspace in Normal Mode

evil-smartparens rebinds backspace in normal mode to #'sp-backward-delete-char, which means it actually deletes characters instead of just moving.

Err... This seems to be intentional, but it's not documented and really odd behavior -- it changes the function of the key rather than just preventing it from unbalancing parens... Which it couldn't do anyway.

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.