Move Cursor to the Next/Previous Paragraph in Kate

It kind of irritates me that Kate doesn’t have a builtin functionality to move cursor to the next/previous paragraph. Fortunately, as with most KDE SC applications, Kate is extendable with custom scripts. So here’s my solution for the mentioned problem.

/* kate-script
 * author: Dzikri Aziz 
 * license: GPLv2
 * revision: 3
 * kate-version: 3.4
 * type: commands
 * functions: jumpUp, jumpDown
 *
 * Move cursor to next/previous paragraph
 */

function jumpDown() {
  return _jump();
}


function jumpUp() {
  return _jump( true );
}


function action( cmd ) {
  var a = new Object();
  if ( cmd == 'jumpUp' ) {
    a.text = i18n('Move cursor to previous paragraph');
    a.shortcut = 'Alt+Up';
    a.icon = "";
    a.category = "";
    a.interactive = false;
  }
  else if ( cmd == 'jumpDown' ) {
    a.text = i18n('Move cursor to next paragraph');
    a.shortcut = 'Alt+Down';
    a.icon = "";
    a.category = "";
    a.interactive = false;
  }

  return a;
}


function help( cmd ) {
  if (cmd == 'jumpUp') {
    return i18n('Move cursor to previous paragraph');
  }
  else if (cmd == 'jumpDown') {
    return i18n('Move cursor to next paragraph');
  }
}


function _jump( up ) {
  var init   = curPos = view.cursorPosition().line,
      lines  = document.lines(),
      target;

  if ( document.firstColumn(curPos) == -1 )
    curPos = document.prevNonEmptyLine(curPos);

  if ( up === true ) {
    target = 0;
    while ( curPos-- > 0 ) {
      if ( document.firstColumn(curPos) == -1 && document.nextNonEmptyLine(curPos) != init ) {
        target = document.nextNonEmptyLine(curPos);
        break;
      }
    }
  }

  else {
    lines--;
    target = lines;
    while ( curPos++ < lines ) {
      if ( document.firstColumn(curPos) == -1 && document.nextNonEmptyLine(curPos) != init ) {
        target = document.nextNonEmptyLine(curPos);
        break;
      }
    }
  }

  view.setCursorPosition(target, 0);
}

Save this script as jump.js inside katepart directory in your KDE user directory, eg: $KDEHOME/share/apps/katepart/script (just create the sub-directories if they don't exist yet) and relaunch Kate. Now you can move the cursor to the next paragraph by pressing Alt+Up or the previous one by pressing Alt+Down. You can freely customize the shortcut from Settings » Configure Shortcuts.

Any improvements are welcome!

As a bonus, here's the scripting guide I printed from Google cache.

5 thoughts on “Move Cursor to the Next/Previous Paragraph in Kate”

  1. Hi,

    thanks for sharing this script. There is one little problem, though: it does not jump to the previous paragraph if it starts on line 1. Is there any way to fix this?

    Greetings!

    1. Hi Chris,
      I fixed the script. Now it should always take you to the first/last line if there are no paragraphs left.

  2. Here is the code for paragraph selection:

    /* kate-script
     * author: Dzikri Aziz 
     * license: GPLv2
     * revision: 3
     * kate-version: 3.4
     * type: commands
     * functions: jumpUpp, jumpDownp
     *
     * Selects to next/previous paragraph
     */
    
    require("cursor.js");
    require("range.js");
    
    function jumpDownp() {
      return _jumpp();
    }
    
    
    function jumpUpp() {
      return _jumpp( true );
    }
    
    
    function action( cmd ) {
      var a = new Object();
      if ( cmd == 'jumpUpp' ) {
        a.text = i18n('Select cursor to previous paragraph');
        a.shortcut = 'Ctrl+Shift+Up';
        a.icon = "";
        a.category = "";
        a.interactive = false;
      }
      else if ( cmd == 'jumpDownp' ) {
        a.text = i18n('Select cursor to next paragraph');
        a.shortcut = 'Ctrl+Shift+Down';
        a.icon = "";
        a.category = "";
        a.interactive = false;
      }
    
      return a;
    }
    
    
    function help( cmd ) {
      if (cmd == 'jumpUpp') {
        return i18n('Select cursor to previous paragraph');
      }
      else if (cmd == 'jumpDownp') {
        return i18n('Select cursor to next paragraph');
      }
    }
    
    
    function _jumpp( up ) {
      var init   = curPos = view.cursorPosition().line,
          lines  = document.lines(),
          target;
    
      if ( document.firstColumn(curPos) == -1 )
        curPos = document.prevNonEmptyLine(curPos);
    
      if ( up === true ) {
         
        target = 0;
        while ( curPos-- > 0 ) {
          if ( document.firstColumn(curPos) == -1 && document.nextNonEmptyLine(curPos) != init ) {
            target = document.nextNonEmptyLine(curPos);
            break;
          }
        }
        
        var cc = view.cursorPosition();
        var p = new Cursor(target, 0);
        var beg;
        var end;
        
        if (view.hasSelection()) {
           selbeg = view.selection().start;
           selend = view.selection().end;
           if (p.compareTo(selbeg) == -1) {
              if (selbeg.compareTo(cc) == -1) {
                 beg = p;
                 end = selbeg;
              } else {
                 beg = p;
                 end = selend;             
              }
           } else if (selend.compareTo(p) == 0) {
              beg = p;
              end = p;
           } else {
              beg = selbeg;
              end = p;
           }
        } else {
           beg = p;
           end = view.cursorPosition();
        }
        
        view.setSelection(new Range(beg, end));
        view.setCursorPosition(target, 0);
        
        
      } else {
        
        while ( curPos++ < lines ) {
          if ( document.firstColumn(curPos) == -1 && document.nextNonEmptyLine(curPos) != init ) {
            target = document.nextNonEmptyLine(curPos);
            break;
          }
        }
        
        var cc = view.cursorPosition();
        
        if (target == -1) {
           target = lines - 1;       
           if (cc.compareTo(new Cursor(target, 0)) == 0)
              return;
        }
        
        var p = new Cursor(target, 0);
        var beg;
        var end;
        
        if (view.hasSelection()) {
           selbeg = view.selection().start;
           selend = view.selection().end;
           if (selend.compareTo(p) == -1) {
              if (cc.compareTo(selend) == -1) {
                 beg = selend;
                 end = p;
              } else {
                 beg = selbeg;
                 end = p;             
              }
           } else if (selend.compareTo(p) == 0) {
              beg = p;
              end = p;
           } else {
              beg = p;
              end = selend;
           }
        } else {
           beg = view.cursorPosition();
           end = p;
        }
        
        view.setSelection(new Range(beg, end));
        view.setCursorPosition(target, 0);
      }
      
    }
    
    1. Thanks Mohsen! I’ve yet to test it, but I think you should submit this to the maintainers so other people can use it too!

  3. Here is code for
    paragraph next and previous
    select paragraph next and previous
    count word
    select word

    /* kate-script
    * author: Dzikri Aziz
    * license: GPLv2
    * revision: 3
    * kate-version: 3.4
    * type: commands
    * functions: jumpUp, jumpDown
    *
    * Move cursor to next/previous paragraph
    */

    require(“cursor.js”);
    require(“range.js”);

    function jumpDown() {
    return _jump();
    }

    function jumpUp() {
    return _jump( true );
    }

    function action( cmd ) {
    var a = new Object();
    if ( cmd == ‘jumpUp’ ) {
    a.text = i18n(‘Move cursor to previous paragraph’);
    a.shortcut = ‘Ctrl+Up';
    a.icon = “”;
    a.category = “MScripts”;
    a.interactive = false;
    }
    else if ( cmd == ‘jumpDown’ ) {
    a.text = i18n(‘Move cursor to next paragraph’);
    a.shortcut = ‘Ctrl+Down';
    a.icon = “”;
    a.category = “MScripts”;
    a.interactive = false;
    }

    return a;
    }

    function help( cmd ) {
    if (cmd == ‘jumpUp’) {
    return i18n(‘Move cursor to previous paragraph’);
    }
    else if (cmd == ‘jumpDown’) {
    return i18n(‘Move cursor to next paragraph’);
    }
    }

    function _jump(up) {
    var init = view.cursorPosition().line;
    var curPos = view.cursorPosition().line;
    var lines = document.lines();

    if ( up === true ) {

    while ((curPos > 0) && (document.firstColumn(curPos) == -1))
    curPos–;

    while (curPos > 0) {
    if (document.firstColumn(curPos) == -1 && document.nextNonEmptyLine(curPos) != init) {
    curPos = document.nextNonEmptyLine(curPos);
    break;
    }
    curPos–;
    }

    } else {

    while ((curPos < lines – 1) && (document.firstColumn(curPos) == -1))
    curPos++;

    while (curPos 0) && (document.firstColumn(curPos) == -1))
    curPos–;

    while (curPos > 0) {
    if (document.firstColumn(curPos) == -1 && document.nextNonEmptyLine(curPos) != init) {
    curPos = document.nextNonEmptyLine(curPos);
    break;
    }
    curPos–;
    }

    var cc = view.cursorPosition();
    var p = new Cursor(curPos, 0);
    // For the first line
    if (cc.compareTo(p) == 0)
    return;
    var beg;
    var end;

    if (view.hasSelection()) {
    selbeg = view.selection().start;
    selend = view.selection().end;
    if (p.compareTo(selbeg) == -1) {
    if (selbeg.compareTo(cc) == -1) {
    beg = p;
    end = selbeg;
    } else {
    beg = p;
    end = selend;
    }
    } else if (selend.compareTo(p) == 0) {
    beg = p;
    end = p;
    } else {
    beg = selbeg;
    end = p;
    }
    } else {
    beg = p;
    end = view.cursorPosition();
    }

    view.setSelection(new Range(beg, end));
    view.setCursorPosition(curPos, 0);

    } else {

    while ((curPos < lines – 1) && (document.firstColumn(curPos) == -1))
    curPos++;

    while (curPos < lines – 1) {
    if (document.firstColumn(curPos) == -1) {
    /* target = document.prevNonEmptyLine(curPos); */
    break;
    }
    curPos++;
    }

    var cc = view.cursorPosition();
    var p = new Cursor(curPos, 0);
    // For the last line
    if (cc.compareTo(p) == 0)
    return;
    var beg;
    var end;

    if (view.hasSelection()) {
    selbeg = view.selection().start;
    selend = view.selection().end;
    if (selend.compareTo(p) == -1) {
    if (cc.compareTo(selend) == -1) {
    beg = selend;
    end = p;
    } else {
    beg = selbeg;
    end = p;
    }
    } else if (selend.compareTo(p) == 0) {
    beg = p;
    end = p;
    } else {
    beg = p;
    end = selend;
    }
    } else {
    beg = view.cursorPosition();
    end = p;
    }

    view.setSelection(new Range(beg, end));
    view.setCursorPosition(curPos, 0);
    }

    }

    /* kate-script
    * author: Mohsen
    * license: GPLv2
    * revision: 3
    * kate-version: 3.4
    * type: commands
    * functions: count_words
    *
    * Count the words of the selected text
    */

    require("cursor.js");
    require("range.js");

    function count_horse(s) {
    s = s.replace(/(^\s*)|(\s*$)/gi,""); //exclude start and end white-space
    s = s.replace(/[ ]{2,}/gi," ");//2 or more space to 1
    s = s.replace(/\n /,'\n'); // exclude newline with a start spacing
    s = s.replace(/\n/g,' '); // exclude newline with a start spacing

    return s.split(' ').length;
    }

    function count_words() {
    if (view.selection().start.compareTo(view.selection().end))
    return 1;
    var s = count_horse(
    document.text(
    view.selection().start,
    view.selection().end
    )
    );
    document.insertText(view.selection().end, "\nCount = " + s + "\n");
    return 1;
    }

    function action( cmd ) {
    var a = new Object();
    a.text = i18n('Count words');
    a.shortcut = 'Ctrl+E';
    a.icon = "";
    a.category = "MScripts";
    a.interactive = false;
    return a;
    }

    function help( cmd ) {
    return i18n('Count words');
    }

    /* kate-script
    * author: Mohsen Lesani
    * license: GPLv2
    * revision: 3
    * kate-version: 3.4
    * type: commands
    * functions: selectWord
    *
    * Select current word
    */

    /*
    * Note:
    * To reload, switch to the command line (F7) and invoke the command reload-scripts.
    */

    require("cursor.js");
    require("range.js");

    function selectWord() {
    view.setSelection(document.wordRangeAt(view.cursorPosition()));
    }

    function action( cmd ) {
    var a = new Object();
    a.text = i18n('Select current word');
    a.shortcut = 'Ctrl+w';
    a.icon = "";
    a.category = "MScripts";
    a.interactive = false;
    return a;
    }

    function help( cmd ) {
    return i18n('Select current word');
    }

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>