Menu

#294 XML: Wrap selection in a tag

open
XML (7)
5
2017-11-07
2012-04-27
Tai
No

Hi there,

I primarily work with HTML and XML. I find jEdit to be an amazing tool, in particular how sidekick parses and displays the markup language.

One feature that I would dearly like, is a way for me to:

i) Wrap selected lines with tags
ii) Wrap a selection with tag

1) Wrap selection with an arbitrary tag

Often time, I'm required to take multiple lines and wrap them with an arbitrary tag. Right now, I make use of beanshell macros to do this, but they are hardcoded to specific tags (like <li> or <p>). I would like to do this without having to type into a dialog box.

See image 01_jetbrains_IDEA_wrap_in_tag.png

2)

Discussion

  • Tai

    Tai - 2012-04-27

    Image of Jetbrains IDEA wrapping a selection with an arbitrary tag

     
  • Tai

    Tai - 2012-04-27

    Oops...

    2) I would like to have the option to do this across multiple lines. This is great for making individual paragraphs or list elements. I have macros that do it, but some editors on OS X (like Textmate, espresso) do this out of the box.

    See image 02_Wrap_selected_lines_in_tag.png

    Thanks,

    Tai

     
  • Tai

    Tai - 2012-04-27

    Image of Espresso with Wrap selected lines in tag.

     
  • Dale Anson

    Dale Anson - 2012-04-27
    • labels: 871558 -->
     
  • Dale Anson

    Dale Anson - 2012-04-27

    Looks like a nice feature for the XML plugin.

     
  • Jarek Czekalski

    Jarek Czekalski - 2012-04-27
    • labels: --> XML
    • summary: Wrap selection in a tag --> XML: Wrap selection in a tag
     
  • Jarek Czekalski

    Jarek Czekalski - 2012-04-27
    • assigned_to: nobody --> kerik-sf
     
  • Tai

    Tai - 2012-04-27

    Thanks Dale,

    I'd love to see it implemented.

    -T

     
  • Alan Ezust

    Alan Ezust - 2013-07-31
    • priority: 5 --> 7
     
  • Alan Ezust

    Alan Ezust - 2013-07-31

    +1 to that!!

     
  • Steve Jakob

    Steve Jakob - 2013-07-31

    Have you tried the XInsert plugin? Not sure about arbitrary tags, but it looks like it might not be too difficult to create your own custom tag libraries.

     
  • Alan Ezust

    Alan Ezust - 2013-08-01

    Actually, now that you mention it, this might be a templates or supertemplates or xinsert feature rather than something that needs to be added to XML plugin, but Ia m not familiar enough with those other plugins to say for sure.

    In my earlier comment, when I said +1 to that, I thought this request was for reformatting words (as in word wrap) for the contents between a tag (instead of using the traditional paragraph separation criteria that jedit's built in reformat paragraph uses) but after looking at the images you attached, I realize your request is not about word wrap, but "tag wrapping".

     
  • Alan Ezust

    Alan Ezust - 2013-08-01
    • priority: 7 --> 5
     
  • Skeeve

    Skeeve - 2017-10-31

    Does this Macro help? (Small bug fixed 2017-11-02)

    os=textArea.getSelection();
    om=textArea.isMultipleSelectionEnabled();
    if (! om) {
        textArea.toggleMultipleSelectionEnabled();
    }
    
    int[] sl= new int[os.length];
    int[] el= new int[os.length];
    String[] in= new String[os.length];
    boolean appendLine= false;
    for (i=os.length; i-->0; ) {
        sl[i]= os[i].getStartLine();
        el[i]= os[i].getEndLine();
        if ( textArea.getLineStartOffset(el[i]) == os[i].getEnd() ) {
                --el[i];
        }
        appendLine= el[i]+1 == textArea.getLineCount();
        in[i]= textArea.getLineText(sl[i]).replaceFirst("\\S.*$","");
    }
    
    textArea.shiftIndentRight();
    textArea.selectNone();
    
    if ( appendLine ) {
        textArea.setCaretPosition(textArea.getBufferLength());
        textArea.setSelectedText("\n");
    }
    
    la= 0;
    for (i=0; i<os.length; ++i) {
        textArea.setCaretPosition(textArea.getLineStartOffset(sl[i]+la));
        sl[i]=  textArea.getCaretPosition()+in[i].length()+1;
        textArea.setSelectedText(in[i]+"<tag>\n");
        ++la;
        textArea.setCaretPosition(textArea.getLineStartOffset(el[i]+1+la));
        el[i]=  textArea.getCaretPosition()+in[i].length()+2;
        textArea.setSelectedText(in[i]+"</tag>\n");
        ++la;
    }
    
    for (i=os.length; i-->0;) {
        textArea.addToSelection(new Selection.Range( sl[i], sl[i]+3 ));
        textArea.addToSelection(new Selection.Range( el[i], el[i]+3 ));
    }
    

    Just select whatever block(s) you want to surround with a tag, call the Macro and start typing the tag.

    Example: https://youtu.be/H5FluV_J11o

    Example with the bugfix: https://youtu.be/WflpyHzeYvo

     

    Last edit: Skeeve 2017-11-02
  • Skeeve

    Skeeve - 2017-11-02

    One more iteration without a video this time.

    This version will put the tags on the same line the text is in, if the selection is just a single line.

    os=textArea.getSelection();
    om=textArea.isMultipleSelectionEnabled();
    if (! om) {
        textArea.toggleMultipleSelectionEnabled();
    }
    
    int[] sl= new int[os.length];
    int[] el= new int[os.length];
    boolean[] ol= new boolean[os.length];
    String[] in= new String[os.length];
    boolean appendLine= false;
    boolean oneLine= false;
    for (i=os.length; i-->0; ) {
        sl[i]= os[i].getStartLine();
        el[i]= os[i].getEndLine();
        ol[i]= oneLine= sl[i] == el[i];
        if ( ! oneLine && textArea.getLineStartOffset(el[i]) == os[i].getEnd() ) {
                --el[i];
        }
        appendLine= !oneLine && el[i]+1 == textArea.getLineCount();
        in[i]= textArea.getLineText(sl[i]).replaceFirst("\\S.*$","");
        if (oneLine) {
            textArea.removeFromSelection( os[i] );
        }
    }
    
    textArea.shiftIndentRight();
    textArea.selectNone();
    
    if ( appendLine ) {
        textArea.setCaretPosition(textArea.getBufferLength());
        textArea.setSelectedText("\n");
    }
    
    la= 0;
    for (i=0; i<os.length; ++i) {
        textArea.setCaretPosition(textArea.getLineStartOffset(sl[i]+la));
        if (ol[i]) {
            textArea.goToStartOfWhiteSpace(false);
            sl[i]=  textArea.getCaretPosition()+1;
            textArea.setSelectedText("<tag>");
            textArea.goToEndOfWhiteSpace(false);
            el[i]=  textArea.getCaretPosition()+2;
            textArea.setSelectedText("</tag>");
        }
        else {
            sl[i]=  textArea.getCaretPosition()+in[i].length()+1;
            textArea.setSelectedText(in[i]+"<tag>\n");
            ++la;
            textArea.setCaretPosition(textArea.getLineStartOffset(el[i]+1+la));
            el[i]=  textArea.getCaretPosition()+in[i].length()+2;
            textArea.setSelectedText(in[i]+"</tag>\n");
            ++la;
        }
    }
    
    for (i=os.length; i-->0;) {
        textArea.addToSelection(new Selection.Range( sl[i], sl[i]+3 ));
        textArea.addToSelection(new Selection.Range( el[i], el[i]+3 ));
    }
    
    if (! om) {
        textArea.toggleMultipleSelectionEnabled();
    }
    
     

    Last edit: Skeeve 2017-11-02
  • Roman Tsourick

    Roman Tsourick - 2017-11-02

    This would be a super cool feature!

    Unfortunately the latter macro has some issues:
    - adds unecessary tab before selection
    - does not turn off multiple selection after
    - seems like there is no way to just enclose single word on a line, encloses the whole text
    - has no way to "finish" the process

     

    Last edit: Roman Tsourick 2017-11-02
    • Skeeve

      Skeeve - 2017-11-02
      • adds unecessary tab before selection

      I do not think the tab is unneccessary. The content should be indented a level more than the tag - but this is my personal preference. Remove the shiftIndentRight().

      • does not turn off multiple selection after

      I fixed the multiple selection "issue". If it was off before it will be off after the macro call. See the last 3 lines of the macro [ if ( ! om ) … ]

      • seems like there is no way to just enclose single word on a line, encloses the whole text

      It is. If you have multiple selections on and do not select a block but single lines (even a character per line is sufficient, then just those lines will be surrounded by tags. But yes - not single word. Always the whole line at least.

      • has no way to "finish" the process

      Press Esc when done.

       

      Last edit: Skeeve 2017-11-02
      • Roman Tsourick

        Roman Tsourick - 2017-11-04

        Now I understand your use case.
        You must be selecting a block of text, multiline, and I agree, it is good to indent the inner content.
        While I was telling about a single line, which should not be indented, because it is already indented 99% of the time. May be you could improve it even further, checking if the text selected is on the single line or not and apply indentation accrodingly.

        Ok.

        Would be nice to have this too.

        Works. Would be great to finish on Enter also if possible.

        Thank you!

         
  • Skeeve

    Skeeve - 2017-11-06

    I already checkeked whether the selection is on just one line.

    But there was a bug in the macro indenting the current line when all selections were just one-liners.

    Fixed now with nbelow code:

    os=textArea.getSelection();
    om=textArea.isMultipleSelectionEnabled();
    if (! om) {
        textArea.toggleMultipleSelectionEnabled();
    }
    
    int[] sl= new int[os.length];
    int[] el= new int[os.length];
    boolean[] ol= new boolean[os.length];
    String[] in= new String[os.length];
    boolean appendLine= false;
    boolean oneLine= false;
    int remainingSelections= os.length;
    for (i=os.length; i-->0; ) {
        sl[i]= os[i].getStartLine();
        el[i]= os[i].getEndLine();
        ol[i]= oneLine= sl[i] == el[i];
        if ( ! oneLine && textArea.getLineStartOffset(el[i]) == os[i].getEnd() ) {
                --el[i];
        }
        appendLine= !oneLine && el[i]+1 == textArea.getLineCount();
        in[i]= textArea.getLineText(sl[i]).replaceFirst("\\S.*$","");
        if (oneLine) {
            textArea.removeFromSelection( os[i] );
            --remainingSelections;
        }
    }
    
    if (remainingSelections > 0) {
        textArea.shiftIndentRight();
    }
    textArea.selectNone();
    
    if ( appendLine ) {
        textArea.setCaretPosition(textArea.getBufferLength());
        textArea.setSelectedText("\n");
    }
    
    la= 0;
    for (i=0; i<os.length; ++i) {
        textArea.setCaretPosition(textArea.getLineStartOffset(sl[i]+la));
        if (ol[i]) {
            textArea.goToStartOfWhiteSpace(false);
            sl[i]=  textArea.getCaretPosition()+1;
            textArea.setSelectedText("<tag>");
            textArea.goToEndOfWhiteSpace(false);
            el[i]=  textArea.getCaretPosition()+2;
            textArea.setSelectedText("</tag>");
        }
        else {
            sl[i]=  textArea.getCaretPosition()+in[i].length()+1;
            textArea.setSelectedText(in[i]+"<tag>\n");
            ++la;
            textArea.setCaretPosition(textArea.getLineStartOffset(el[i]+1+la));
            el[i]=  textArea.getCaretPosition()+in[i].length()+2;
            textArea.setSelectedText(in[i]+"</tag>\n");
            ++la;
        }
    }
    
    for (i=os.length; i-->0;) {
        textArea.addToSelection(new Selection.Range( sl[i], sl[i]+3 ));
        textArea.addToSelection(new Selection.Range( el[i], el[i]+3 ));
    }
    
    if (! om) {
        textArea.toggleMultipleSelectionEnabled();
    }
    
     
  • Roman Tsourick

    Roman Tsourick - 2017-11-07

    Yes, now it respects nubmer of lines.

    I've noticed another issue, the backspace does not work at all while typing the tag name.

    Probably it goes beyond the macro. Even this really helps I believe.

     

Log in to post a comment.