46

GitHub - ethan-leba/tree-edit: 🌲 Structural editing in Emacs for any™ language...

 2 years ago
source link: https://github.com/ethan-leba/tree-edit
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
ethan-leba/tree-edit: 🌲 Structural editing in Emacs for any™ language!

warningTree-edit is very much a work-in-progress. Expect to run into bugs and breaking changes!

Every programming language has a formally defined structure, but most text editors are completely ignorant to it when editing code. As a result, editing can oftentimes devolve into a tedious exercise in character manipulation.

Tree-edit provides editing operations that map directly to the structure of the language, abstracting away the process of manually entering syntax. Leveraging the tree-sitter parser, tree-edit always has access to the precise state of the syntax tree – and directly wields the grammars of supported languages in order to power it’s editing capabilities.

Table of Contents

Getting started

Tree-edit is consists of two packages: tree-edit, a library for providing structural editing, and evil-tree-edit, a new evil tree state which exposes this functionality. The following sections of the README describe usage with evil-tree-edit.

After installation, add hooks for any language you’d like tree-edit to automatically enable in.

(add-hook 'java-mode-hook #'evil-tree-edit-mode)

It’s also recommended to use tree-edit with an autoformatter in it’s current state (see limitations).

(add-hook 'tree-edit-after-change-hook #'my-format-buffer-command)

Usage

The concept of the cursor, a position in the 2D plane of text, is replaced by the current node, which is a position in the syntax tree in tree-edit. All operations unless otherwise specified are performed on the current node. To help visualize the syntax tree, tree-edit provides M-x tree-edit-view-mode as seen in the demo GIF.

Tree-edit adopts a vim-style approach to editing, where certain operators also require a noun. In vim’s case, the nouns are text objects; In tree-edit’s case, the nouns are node types. For example, iv would insert a variable declaration. Due to the fact that most languages contain a large number of node types, and vary across languages, using which-key with tree-edit is highly recommended.

To activate tree-edit from normal state, press Q, and to return to normal state press ESC.

Navigation

The navigation primitives follow the tree structure of the language.

OperationKeybindDescriptionNextjMove cursor to the next sibling.PreviouskMove cursor to the previous sibling.InwardsfMove cursor to the first child.OutwardshMove cursor to the parent.Jump tosJump to a node of node-type for a node inside the current.Outwards SignificantAMove outwards until a significant node (e.g. function or class declaration) is hit.

Editing operations

The most important feature of tree-edit: editing the syntax tree. For any editing operation, the syntax will be added or deleted at will based on the needs of the operation. Any transformations will be rejected if a syntactically valid result cannot be generated.

OperationKeybindDescriptionRaiserReplace the current node’s parent with the current node.DeletedDelete the current node.ChangecDelete the current node and drop into insert state. Tree state will be re-entered on ESC.WrapwCreate a new node of node-type and insert the current one in it.ExchangeeExchange the current node with a new node of node-type.InsertiInsert a new node of node-type to the right of the current.AppendaInsert a new node of node-type to the left of the current.Insert ChildIInsert a new node of node-type as a child of the current. Useful for nodes with no named children, i.e. {}Slurp>Grow the current node to contain the nearest right-most element.Barf<Shrink the current node to place it’s left-most element into the parent node.CopyyCopy the text of the current node.

Pasting

Along with the standard node-types of the given language, tree-edit has a special node-type p that will attempt to parse the type of the most recently copied text. If a type can be identified and the operation is valid, the copied text will be used.

Supported languages

StatusLanguagehammerJava

Currently the list of supported languages is not very impressive, but in theory it should be as simple as adding a new grammar and language file for a given language. In practice I expect this to unearth some language-specific assumptions in the tree-edit code base!

Customization

Currently adding customization ontop of the preset language files requires a fair bit of boilerplate, but here’s some code to get started.

(with-eval-after-load 'tree-edit-java
  (with-mode-local java-mode
    (setq-mode-local
     java-mode

     tree-edit-syntax-snippets
     (append
      ;; Put your snippets here
      '((identifier . ("FOOBAR")))
      tree-edit-syntax-snippets)

     tree-edit-nodes
     (append
      ;; Put your nodes here
      '((:type if_statement
         :key "z"
         :name "if-else statement"
         :node-override '((if_statement . ("if" parenthesized_expression block "else" block)))))
      tree-edit-nodes)))

  (evil-tree-edit--set-state-bindings 'java-mode))

See tree-edit-java.el and the docstrings of the accompanying variables for more information.

Limitations

A non-comprehensive list of some of the larger limitations that tree-edit currently has:

Formattingtree-edit does not currently make any attempts to produce code in a well-formatted manner, and may change the formatting of adjacent nodes during editing operations. Impedance mismatchMost tree-sitter grammars were not designed with tree-edit’s usecase in mind, so some grammars may be structured inconveniently for tree-edit’s purposes. Tree-sitter-langsTree-edit currently depends on tree-sitter-langs to power the tree-sitter parsers, however tree-sitter-langs does not always have the most up-to-date grammars and is missing some languages. If this continues to be an issue a fork may be needed.

Contributing

Contributions are very much welcome! In particular, adding language files would be a great place to help. Otherwise, the issues are a good place to propose features or find ones to implement.

Tests can be run using ./run-tests.sh script.

Related projects

evil-textobj-tree-sitterEvil mode text objects using tree-sitter queries. lispyLisp structural editing package – big inspiration for tree-edit! smartparensMultilingual package with structural editing limited to matching delimiters.

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK