rnkn / fountain-mode

Emacs major mode for screenwriting in Fountain plain-text markup
https://fountain-mode.org
GNU General Public License v3.0
394 stars 15 forks source link

Moving elements with M-up/down #53

Closed tty-tourist closed 6 years ago

tty-tourist commented 8 years ago

It would be cool if M-up/down could be used for moving element at point in a way similar to how M-up/down work in org-mode.

In that way, M-up/down would fountain-outline-shift-up/fountain-outline-shift-down if scene heading is at point, and dialog elements (character+dialog line(s)) or action would be shifted up or down, if they are at point.

For example:

INT. HOUSE

MARY
Bye.

JANE
Well, see ya.

Mary opens the door.

If point is anywhere within:

MARY Bye.

Then M-down would do this:

INT. HOUSE

JANE
Well, see ya.

MARY
Bye.

Mary opens the door.

M-down again would to this:

INT. HOUSE

JANE
Well, see ya.

Mary opens the door.

MARY
Bye.

I've tried to make my own implementation of this but it's very poor because: 1.) it requires an external package (move-text) and 2.) it only moves individual lines, not character and dialog lines together.

It would be nice if elements could be moved as described above.

My own feeble attempt for reference:

(defun fountain-element-shift-up ()
  "Move fountain scene heading or line at point up."
  (interactive)
    (if (fountain-scene-heading-p)
        (fountain-outline-shift-up 1)
      (move-text-up 1)))

(defun fountain-element-shift-down ()
  "Move fountain scene heading or line at point down."
  (interactive)
    (if (fountain-scene-heading-p)
        (fountain-outline-shift-down 1)
      (move-text-down 1)))

(eval-after-load 'fountain-mode
    '(progn
       (define-key fountain-mode-map (kbd "M-<up>") 'fountain-element-shift-up)))

(eval-after-load 'fountain-mode
    '(progn
       (define-key fountain-mode-map (kbd "M-<down>") 'fountain-element-shift-down)))
rnkn commented 8 years ago

I've been wanting to implement this. It may be a little while before I get to it but it shouldn't be too difficult.

It will need a concept of a "block" in Fountain, which could be a paragraph of action or some dialogue containing the character name plus multiple lines of dialogue and parentheticals. This is already somewhere in the parsing code, I just need to find it and make it its own function.

I doubt I'll be able to reuse the outline code though for shifting blocks about. That's the non-trivial bit.

tty-tourist commented 8 years ago

Maybe a block could defined as any number of lines divided by on or more blank lines.

In all the cases I can't think of, that would constitute sensible blocks.

rnkn commented 8 years ago

When point is on a scene heading or section heading I think the block should refer to the scene or section, respectively. No?

This is how C-c C-^ and C-c C-v currently understand the script outline.

tty-tourist commented 8 years ago

Yes, I think that would make sense.

rnkn commented 8 years ago

What's your expectation for the following (point is [])...

INT. HOUSE

MARY
I guess, tomorrow
[](pause)
Yeah, tomorrow. Bye.

JANE
Well, see ya.

Mary opens the door.

Should this still move the whole dialogue block, or move just the parenthetical?

tty-tourist commented 8 years ago

I would expect the whole dialogue block to be moved with the following result:

INT. HOUSE

JANE
Well, see ya.

MARY
I guess, tomorrow
[](pause)
Yeah, tomorrow. Bye.

Mary opens the door.

The whole dialogue is moved and point is at the same place within the moved block.

If it were to move the parenthetical within the dialogue block, I think that would be more confusing than useful, at least for me.

tty-tourist commented 7 years ago

Glad to hear you're still working on this. I think the whole scene should shift if scene heading is at point.

Maybe the rule could be somthing like: Shift element at point within the order of elements on the same hierarchal level.

That way, in this example from earlier:

MARY
I guess, tomorrow
[](pause)
Yeah, tomorrow. Bye.

JANE
Well, see ya.

Mary opens the door.

Maybe the parenthetical should in fact be moved, and only the entire dialogue block if the header (eg. MARY) is at point.

Dialogue blocks and action blocks would need to be considered on the same level so that:

MARY
I guess, tomorrow
(pause)
Yeah, tomorrow. Bye.

[]JANE
Well, see ya.

Mary opens the door.

... would become:

MARY
I guess, tomorrow
(pause)
Yeah, tomorrow. Bye.

Mary opens the door.

[]JANE
Well, see ya.

Does that make sense to you?

rnkn commented 7 years ago

Sorry I only realised after I posted that I'd already asked the question about scene/section headings and you'd already answered, so I deleted the comment.

I agree that shifting entire scenes/sections is what's most useful and expected.

As for dialogue, I've implemented as "blocks" so a dialogue block contains the character, parentheticals and lines. I think this is probably what most people expect, and otherwise it would be not so different to just kill and yank line.

Any block can't be shifted above a preceding block if that block's end point exceeds its own, e.g. a scene's end point is the start of the next scene and so exceeds the end point of any dialogue within.

I'm in the midst of converting the entire parsing engine, so although this feature is rather trivial to implement, unfortunately it can't be released until that rewrite is done.

On the flip side, if all goes to plan, this rewrite will bring page locking to Fountain.

rnkn commented 6 years ago

Implemented in master branch.

rnkn commented 6 years ago

p.s. Sorry it took so long!