Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pipe table support implemented #266

Closed
saf-dmitry opened this issue Oct 2, 2017 · 7 comments
Closed

Pipe table support implemented #266

saf-dmitry opened this issue Oct 2, 2017 · 7 comments

Comments

@saf-dmitry
Copy link
Contributor

saf-dmitry commented Oct 2, 2017

Inspired by the excellent Org mode table editor, I've implemented pipe table support in Markdown mode.

markdown-mode-table.zip

A simple pipe table looks like this:

| Right | Left | Center | Default |
|------:|:-----|:------:|---------|
|    12 | 12   | 12     | 12      |
|   123 | 123  | 123    | 123     |
|     1 | 1    | 1      | 1       |

First line contains column headers. Second line contains a separator line between the headers and the content. Each following line is a row in the table. Columns are always separated by the pipe character. The colons indicate column alignment.

The code provides context-sensitive key bindings, basically the same as of the Org mode table editor. A table is re-aligned automatically each time you press <TAB> or <RET> inside the table. <TAB> also moves to the next field (<RET> to the next row) and creates new table rows at the end of the table or before horizontal separator lines. The indentation of the table is set by the first line. Column centering inside Emacs is not supported.

Beginning pipe characters are required for proper detection of table borders inside Emacs. Any line starting with |- or |: is considered as a horizontal separator line and will be expanded on the next re-align to span the whole table width. No padding is allowed between the beginning pipe character and header separator symbol. So, to create the above table, you would only type

|Right|Left|Center|Default|
|-

and then press <TAB> to align the table and start filling in cells.

Then you can jump with the <TAB> from one cell to the next or with S-<TAB> to the previous one. <RET> will jump to the to the next cell in the same column, and create a new row if there is no such cell or if the next row is beyond a separator line.

You can also convert selected region to a pipe table via C-c |. Basic editing capabilities comprise inserting, deleting, and moving of columns and rows, and table sorting and transposing:

  • M-<left/right>: Move the current column left/right.

  • M-S-<left>: Delete the current column.

  • M-S-<right>: Insert a new column to the left of the cursor position.

  • M-<up/down>: Move the current row up/down.

  • M-S-<up>: Delete the current row or horizontal separator line.

  • M-S-<down>: Insert a new row above the current row. With a prefix argument, the line is created below the current one.

  • C-c ^: Sort table lines alpabetically or numerically.

  • C-c |: Convert selected region to a pipe table.

  • C-c C-x C-t: Transpose the pipe table at point.

The code can be loaded and used in combination with the current stable version of Markdown mode, just by putting the file markdown-mode-table.el somewhere in the Emacs load path and adding to your .emacs file:

(require 'markdown-mode-table)

but I would love to see it implemented in the Markdown mode itself. Basically one just needs to copy the content of the file and adapt some functions for the context-sensitive key bindings.

@vyp
Copy link

vyp commented Oct 2, 2017

Submit a pull request?

@jrblevin
Copy link
Owner

jrblevin commented Oct 2, 2017

This is fantastic. Thank you!

I have only had time to try it out for a few minutes so far, but everything has worked great so far. I will read it more carefully soon.

For now, I just have one question: why do so many functions have autoload tokens? Presumably we won't need these when this is included (and I suppose it should simply be required from markdown-mode.el)?

Also, I will cross-reference #171 here, since this addresses that issue.

@saf-dmitry
Copy link
Contributor Author

saf-dmitry commented Oct 3, 2017

Yes, you are right, the autoload tokens will be not required, when the code is included.

jrblevin pushed a commit that referenced this issue Oct 21, 2017
This commit adds support for pipe tables of the following form:

| Right | Left | Center | Default |
|------:|:-----|:------:|---------|
|    12 | 12   | 12     | 12      |
|   123 | 123  | 123    | 123     |
|     1 | 1    | 1      | 1       |

Several functions related to such tables are included:

- Pipe table recognition, insertion, and editing functions.
- Functions for navigating within table cells.
- Functions for moving, killing, and inserting rows and columns.
- Functions for re-aligning, sorting, and transposing tables.

The above features are the work by Dmitry Safronov, who adapted the
table editing functions from org-mode to work with Markdown pipe
tables in GH-266.  This code was modified for inclusion in
markdown-mode and committed by Jason Blevins with the following
changes:

- Incorporate the documentation from comments into the main
  markdown-mode documentation and README.md.
- Use markdown-table prefix for all table editing functions.
- Mark some helper functions as internal.
- Remove autoload tokens and don't require cl-lib.
- Incorporate keybindings into markdown-mode keymaps.
- Note that table functions are based on org-table.el
- Fix some checkdoc warnings (unused variables, docstrings, etc.).
- Add a condition to markdown-do for table re-alignment with C-c C-d.

Closes GH-171 and GH-266.
@jrblevin
Copy link
Owner

I have now incorporated the table code into markdown-mode; see commit 5729dc5. I hope you don't mind, but since you contributed the code I committed it with you as the author to give credit where it is due.

I did make some small modifications, mostly to keybindings, and I also changed some function names, docstrings, and added the documentation to the README.md file. We should also add tests at some point.

I had to change some keybindings to prevent using top-level keys to follow the Emacs major-mode conventions:

The key sequences bound in a major mode keymap should usually start with C-c, followed by a control character, a digit, or {, }, <, >, : or ;. The other punctuation characters are reserved for minor modes, and ordinary letters are reserved for users.

I know that org-mode doesn't adhere to these guidelines, but over-riding some top-level keys in the past caused conflicts for markdown-mode users, so I avoid doing that now. Perhaps one day an option can be added to markdown-mode to enable top-level org-mode-like keybindings for those that prefer them. Here is a summary of the new bindings (which you can also now see in the README.md file):

  • C-c UP, C-c DOWN, C-c LEFT, C-c RIGHT - move rows and columns.
  • C-c S-UP, C-c S-DOWN, C-c S-LEFT, C-c S-RIGHT - insert and delete rows and columns.
  • I moved the other table functions under C-c C-c: C-c C-c ^ for sorting, C-c C-c | for table creation, and C-c C-c t for transposition.
  • Finally, I also added a context-specific case to C-c C-d (markdown-do) for table re-alignment, like C-c C-c in org-mode.

Many thanks again for adapting the table editing code for markdown-mode. This is a really great addition that I and many users have wanted for a long time (e.g., #171). Let me know if you see any problems or have thoughts on how to better incorporate this.

@saf-dmitry
Copy link
Contributor Author

saf-dmitry commented Oct 22, 2017

Thank you for quick incorporation of the code. I did not try it yet, just took a quick look into the commit. Some comments/thoughts:

  1. In the definition of markdown-table-goto-dline function (line 9190) could you please change the uppercase N (function argument) to the lowercase n(my fault).

  2. I see your point in adhering to the Emacs major-mode conventions for keybindings.

  3. I think we should add some more explanation to the functions for table sorting (markdown-table-sort-lines) and creation (markdown-table-convert-region) in the README.md or refer the user to see the corresponding docstrings for details.

  4. My idea to use pipe-table prefix in function names was to prevent possible name collisions if support for other table syntaxes (like e.g., Pandoc simple tables) will be implemented in the future.

  5. As I wrote in comments to the original code, columns containig hidden markup may not always be properly aligned. This is because Emacs' format function cannot properly handle invisible characters in strings. Please let me know, if you experienced this issue in your environment. A proper solution would be to "manually" calculate additional whitespace padding for all cells. This way we could handle column centering inside Emacs as well.

@jrblevin
Copy link
Owner

In the definition of markdown-table-goto-dline function (line 9190) could you please change the uppercase N (function argument) to the lowercase n (my fault).

Done, thanks. See b718630.

I think we should add some more explanation to the functions for table sorting (markdown-table-sort-lines) and creation (markdown-table-convert-region) in the README.md or refer the user to see the corresponding docstrings for details.

Also done, see c25f394. Feel free to submit a PR if you think it needs even more detail.

My idea to use pipe-table prefix in function names was to prevent possible name collisions if support for other table syntaxes (like e.g., Pandoc simple tables) will be implemented in the future.

I assumed that was the idea, but "pipe tables" are really the common denominator among Markdown implementations and if we were going to support one table syntax, that was the right one. I'm not very keen on including more than one, so I thought it was good enough to simply call them "tables" at this point.

As I wrote in comments to the original code, columns containig hidden markup may not always be properly aligned. This is because Emacs' format function cannot properly handle invisible characters in strings. Please let me know, if you experienced this issue in your environment. A proper solution would be to "manually" calculate additional whitespace padding for all cells. This way we could handle column centering inside Emacs as well.

I haven't tested this because I use different fonts for code and regular text, and an unfortunate consequence is that tables containing code are never aligned on screen anyway. Aside from my issue, when using the same font things could feasibly be lined up with padding as you suggested. That seems like a good opportunity for a future enhancement pull request for anyone so inclined.

@hmelman
Copy link
Contributor

hmelman commented Nov 2, 2017

I think the table commands should be listed in the Markdown menu the same as header and list commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants