nodes: 0, module; 1, function_definition; 2, function_name:sort_kate_imports; 3, parameters; 4, block; 5, default_parameter; 6, default_parameter; 7, expression_statement; 8, expression_statement; 9, expression_statement; 10, expression_statement; 11, expression_statement; 12, expression_statement; 13, expression_statement; 14, expression_statement; 15, if_statement; 16, expression_statement; 17, identifier:add_imports; 18, tuple; 19, identifier:remove_imports; 20, tuple; 21, comment:"""Sorts imports within Kate while maintaining cursor position and selection, even if length of file changes."""; 22, assignment; 23, assignment; 24, assignment; 25, assignment; 26, assignment; 27, call; 28, call; 29, identifier:selection; 30, block; 31, call; 32, identifier:document; 33, call; 34, identifier:view; 35, call; 36, identifier:position; 37, call; 38, identifier:selection; 39, call; 40, identifier:sorter; 41, call; 42, attribute; 43, argument_list; 44, attribute; 45, argument_list; 46, expression_statement; 47, expression_statement; 48, expression_statement; 49, expression_statement; 50, expression_statement; 51, expression_statement; 52, attribute; 53, argument_list; 54, attribute; 55, argument_list; 56, attribute; 57, argument_list; 58, attribute; 59, argument_list; 60, attribute; 61, argument_list; 62, identifier:SortImports; 63, argument_list; 64, identifier:document; 65, identifier:setText; 66, attribute; 67, identifier:position; 68, identifier:setLine; 69, binary_operator:position.line() + sorter.length_change; 70, assignment; 71, call; 72, assignment; 73, call; 74, call; 75, call; 76, identifier:view; 77, identifier:setCursorPosition; 78, identifier:position; 79, identifier:kate; 80, identifier:activeDocument; 81, identifier:document; 82, identifier:activeView; 83, identifier:view; 84, identifier:cursorPosition; 85, identifier:view; 86, identifier:selectionRange; 87, keyword_argument; 88, keyword_argument; 89, keyword_argument; 90, keyword_argument; 91, identifier:sorter; 92, identifier:output; 93, call; 94, attribute; 95, identifier:start; 96, call; 97, attribute; 98, argument_list; 99, identifier:end; 100, call; 101, attribute; 102, argument_list; 103, attribute; 104, argument_list; 105, attribute; 106, argument_list; 107, identifier:file_contents; 108, call; 109, identifier:add_imports; 110, identifier:add_imports; 111, identifier:remove_imports; 112, identifier:remove_imports; 113, identifier:settings_path; 114, call; 115, attribute; 116, argument_list; 117, identifier:sorter; 118, identifier:length_change; 119, attribute; 120, argument_list; 121, identifier:start; 122, identifier:setLine; 123, binary_operator:start.line() + sorter.length_change; 124, attribute; 125, argument_list; 126, identifier:end; 127, identifier:setLine; 128, binary_operator:end.line() + sorter.length_change; 129, identifier:selection; 130, identifier:setRange; 131, identifier:start; 132, identifier:end; 133, identifier:view; 134, identifier:setSelection; 135, identifier:selection; 136, attribute; 137, argument_list; 138, attribute; 139, argument_list; 140, identifier:position; 141, identifier:line; 142, identifier:selection; 143, identifier:start; 144, call; 145, attribute; 146, identifier:selection; 147, identifier:end; 148, call; 149, attribute; 150, identifier:document; 151, identifier:text; 152, attribute; 153, identifier:dirname; 154, call; 155, attribute; 156, argument_list; 157, identifier:sorter; 158, identifier:length_change; 159, attribute; 160, argument_list; 161, identifier:sorter; 162, identifier:length_change; 163, identifier:os; 164, identifier:path; 165, attribute; 166, argument_list; 167, identifier:start; 168, identifier:line; 169, identifier:end; 170, identifier:line; 171, attribute; 172, identifier:abspath; 173, call; 174, identifier:os; 175, identifier:path; 176, identifier:str; 177, argument_list; 178, call; 179, attribute; 180, argument_list; 181, call; 182, identifier:path; 183, attribute; 184, argument_list; 185, identifier:document; 186, identifier:url
code: def sort_kate_imports(add_imports=(), remove_imports=()):
      """Sorts imports within Kate while maintaining cursor position and selection, even if length of file changes."""
      document = kate.activeDocument()
      view = document.activeView()
      position = view.cursorPosition()
      selection = view.selectionRange()
      sorter = SortImports(file_contents=document.text(), add_imports=add_imports, remove_imports=remove_imports,
                           settings_path=os.path.dirname(os.path.abspath(str(document.url().path()))))
      document.setText(sorter.output)
      position.setLine(position.line() + sorter.length_change)
      if selection:
          start = selection.start()
          start.setLine(start.line() + sorter.length_change)
          end = selection.end()
          end.setLine(end.line() + sorter.length_change)
          selection.setRange(start, end)
          view.setSelection(selection)
      view.setCursorPosition(position)