PageRenderTime 55ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/part/vimode/katevinormalmode.cpp

https://bitbucket.org/totte/kate
C++ | 3313 lines | 2459 code | 646 blank | 208 comment | 539 complexity | 7e727612fd6052ec7d0afb2f067f6b31 MD5 | raw file
Possible License(s): LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /* This file is part of the KDE libraries and the Kate part.
  2. *
  3. * Copyright (C) 2008-2009 Erlend Hamberg <ehamberg@gmail.com>
  4. * Copyright (C) 2008 Evgeniy Ivanov <powerfox@kde.ru>
  5. * Copyright (C) 2009 Paul Gideon Dann <pdgiddie@gmail.com>
  6. * Copyright (C) 2011 Svyatoslav Kuzmich <svatoslav1@gmail.com>
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Library General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Library General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Library General Public License
  19. * along with this library; see the file COPYING.LIB. If not, write to
  20. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  21. * Boston, MA 02110-1301, USA.
  22. */
  23. #include "katevinormalmode.h"
  24. #include "katevivisualmode.h"
  25. #include "kateviinsertmode.h"
  26. #include "kateviinputmodemanager.h"
  27. #include "kateviglobal.h"
  28. #include "kateglobal.h"
  29. #include "katebuffer.h"
  30. #include "kateviewhelpers.h"
  31. #include <QApplication>
  32. #include <QList>
  33. using KTextEditor::Cursor;
  34. using KTextEditor::Range;
  35. #define ADDCMD(STR, FUNC, FLGS) m_commands.push_back( \
  36. new KateViCommand( this, STR, &KateViNormalMode::FUNC, FLGS ) );
  37. #define ADDMOTION(STR, FUNC, FLGS) m_motions.push_back( \
  38. new KateViMotion( this, STR, &KateViNormalMode::FUNC, FLGS ) );
  39. KateViNormalMode::KateViNormalMode( KateViInputModeManager *viInputModeManager, KateView * view,
  40. KateViewInternal * viewInternal ) : KateViModeBase()
  41. {
  42. m_view = view;
  43. m_viewInternal = viewInternal;
  44. m_viInputModeManager = viInputModeManager;
  45. m_stickyColumn = -1;
  46. // FIXME: make configurable
  47. m_extraWordCharacters = "";
  48. m_matchingItems["/*"] = "*/";
  49. m_matchingItems["*/"] = "-/*";
  50. m_matchItemRegex = generateMatchingItemRegex();
  51. m_defaultRegister = '"';
  52. m_scroll_count_limit = 1000; // Limit of count for scroll commands.
  53. m_timeoutlen = 1000; // FIXME: make configurable
  54. m_mappingKeyPress = false; // temporarily set to true when an aborted mapping sends key presses
  55. m_mappingTimer = new QTimer( this );
  56. connect(m_mappingTimer, SIGNAL(timeout()), this, SLOT(mappingTimerTimeOut()));
  57. initializeCommands();
  58. m_ignoreMapping = false;
  59. m_pendingResetIsDueToExit = false;
  60. m_isRepeatedTFcommand = false;
  61. resetParser(); // initialise with start configuration
  62. }
  63. KateViNormalMode::~KateViNormalMode()
  64. {
  65. qDeleteAll( m_commands );
  66. qDeleteAll( m_motions) ;
  67. }
  68. void KateViNormalMode::mappingTimerTimeOut()
  69. {
  70. kDebug( 13070 ) << "timeout! key presses: " << m_mappingKeys;
  71. m_mappingKeyPress = true;
  72. if (!m_fullMappingMatch.isNull())
  73. {
  74. executeMapping();
  75. }
  76. else
  77. {
  78. m_viInputModeManager->feedKeyPresses( m_mappingKeys );
  79. }
  80. m_mappingKeyPress = false;
  81. m_mappingKeys.clear();
  82. }
  83. /**
  84. * parses a key stroke to check if it's a valid (part of) a command
  85. * @return true if a command was completed and executed, false otherwise
  86. */
  87. bool KateViNormalMode::handleKeypress( const QKeyEvent *e )
  88. {
  89. int keyCode = e->key();
  90. QString text = e->text();
  91. // ignore modifier keys alone
  92. if ( keyCode == Qt::Key_Shift || keyCode == Qt::Key_Control
  93. || keyCode == Qt::Key_Alt || keyCode == Qt::Key_Meta ) {
  94. return false;
  95. }
  96. if ( keyCode == Qt::Key_AltGr ) {
  97. KateViKeyParser::self()->setAltGrStatus( true );
  98. return true;
  99. }
  100. if ( keyCode == Qt::Key_Escape ) {
  101. m_view->setCaretStyle( KateRenderer::Block, true );
  102. m_pendingResetIsDueToExit = true;
  103. reset();
  104. return true;
  105. }
  106. QChar key = KateViKeyParser::self()->KeyEventToQChar( keyCode, text, e->modifiers(), e->nativeScanCode() );
  107. // check for matching mappings
  108. if ( !m_mappingKeyPress && !m_ignoreMapping) {
  109. m_mappingKeys.append( key );
  110. bool isPartialMapping = false;
  111. bool isFullMapping = false;
  112. m_fullMappingMatch.clear();
  113. foreach ( const QString &mapping, getMappings() ) {
  114. if ( mapping.startsWith( m_mappingKeys ) ) {
  115. if ( mapping == m_mappingKeys ) {
  116. isFullMapping = true;
  117. m_fullMappingMatch = mapping;
  118. } else {
  119. isPartialMapping = true;
  120. }
  121. }
  122. }
  123. if (isFullMapping && !isPartialMapping)
  124. {
  125. // Great - m_mappingKeys is a mapping, and one that can't be extended to
  126. // a longer one - execute it immediately.
  127. executeMapping();
  128. return true;
  129. }
  130. if (isPartialMapping)
  131. {
  132. // Need to wait for more characters (or a timeout) before we decide what to
  133. // do with this.
  134. m_mappingTimer->start( m_timeoutlen );
  135. m_mappingTimer->setSingleShot( true );
  136. return true;
  137. }
  138. // We've been swallowing all the keypresses meant for m_keys for our mapping keys; now that we know
  139. // this cannot be a mapping, restore them. The current key will be appended further down.
  140. Q_ASSERT(!isPartialMapping && !isFullMapping);
  141. if (m_keys.isEmpty())
  142. m_keys = m_mappingKeys.mid(0, m_mappingKeys.length() - 1);
  143. m_mappingKeys.clear();
  144. } else {
  145. // FIXME:
  146. //m_mappingKeyPress = false; // key press ignored wrt mappings, re-set m_mappingKeyPress
  147. }
  148. if ( m_ignoreMapping ) m_ignoreMapping = false;
  149. if ( key == 'f' || key == 'F' || key == 't' || key == 'T' || key == 'r' ) {
  150. // don't translate next character, we need the actual character so that
  151. // 'ab' is translated to 'fb' if the mapping 'a' -> 'f' exists
  152. m_ignoreMapping = true;
  153. }
  154. // Use replace caret when reading a character for "r"
  155. if ( key == 'r' ) {
  156. m_view->setCaretStyle( KateRenderer::Underline, true );
  157. }
  158. m_keysVerbatim.append( KateViKeyParser::self()->decodeKeySequence( key ) );
  159. QChar c = QChar::Null;
  160. if ( m_keys.size() > 0 ) {
  161. c = m_keys.at( m_keys.size()-1 ); // last char
  162. }
  163. if ( ( keyCode >= Qt::Key_0 && keyCode <= Qt::Key_9 && c != '"' ) // key 0-9
  164. && ( m_countTemp != 0 || keyCode != Qt::Key_0 ) // first digit can't be 0
  165. && ( c != 'f' && c != 't' && c != 'F' && c != 'T' && c != 'r' ) ) { // "find char" motions
  166. m_countTemp *= 10;
  167. m_countTemp += keyCode-Qt::Key_0;
  168. return true;
  169. } else if ( m_countTemp != 0 ) {
  170. m_count = getCount() * m_countTemp;
  171. m_countTemp = 0;
  172. m_iscounted = true;
  173. kDebug( 13070 ) << "count = " << getCount();
  174. }
  175. m_keys.append( key );
  176. // Special case: "cw" and "cW" work the same as "ce" and "cE" if the cursor is
  177. // on a non-blank. This is because Vim interprets "cw" as change-word, and a
  178. // word does not include the following white space. (:help cw in vim)
  179. if ( ( m_keys == "cw" || m_keys == "cW" ) && !getCharUnderCursor().isSpace() ) {
  180. // Special case of the special case: :-)
  181. // If the cursor is at the end of the current word rewrite to "cl"
  182. Cursor c1( m_view->cursorPosition() ); // current position
  183. Cursor c2 = findWordEnd(c1.line(), c1.column()-1, true); // word end
  184. if ( c1 == c2 ) { // the cursor is at the end of a word
  185. m_keys = "cl";
  186. } else {
  187. if ( m_keys.at(1) == 'w' ) {
  188. m_keys = "ce";
  189. } else {
  190. m_keys = "cE";
  191. }
  192. }
  193. }
  194. if ( m_keys[ 0 ] == Qt::Key_QuoteDbl ) {
  195. if ( m_keys.size() < 2 ) {
  196. return true; // waiting for a register
  197. }
  198. else {
  199. QChar r = m_keys[ 1 ].toLower();
  200. if ( ( r >= '0' && r <= '9' ) || ( r >= 'a' && r <= 'z' ) ||
  201. r == '_' || r == '+' || r == '*' || r == '#' || r == '^' ) {
  202. m_register = r;
  203. kDebug( 13070 ) << "Register set to " << r;
  204. m_keys.clear();
  205. return true;
  206. }
  207. else {
  208. resetParser();
  209. return true;
  210. }
  211. }
  212. }
  213. // if we have any matching commands so far, check which ones still match
  214. if ( m_matchingCommands.size() > 0 ) {
  215. int n = m_matchingCommands.size()-1;
  216. // remove commands not matching anymore
  217. for ( int i = n; i >= 0; i-- ) {
  218. if ( !m_commands.at( m_matchingCommands.at( i ) )->matches( m_keys ) ) {
  219. //kDebug( 13070 ) << "removing " << m_commands.at( m_matchingCommands.at( i ) )->pattern() << ", size before remove is " << m_matchingCommands.size();
  220. if ( m_commands.at( m_matchingCommands.at( i ) )->needsMotion() ) {
  221. // "cache" command needing a motion for later
  222. //kDebug( 13070 ) << "m_motionOperatorIndex set to " << m_motionOperatorIndex;
  223. m_motionOperatorIndex = m_matchingCommands.at( i );
  224. }
  225. m_matchingCommands.remove( i );
  226. }
  227. }
  228. // check if any of the matching commands need a motion/text object, if so
  229. // push the current command length to m_awaitingMotionOrTextObject so one
  230. // knows where to split the command between the operator and the motion
  231. for ( int i = 0; i < m_matchingCommands.size(); i++ ) {
  232. if ( m_commands.at( m_matchingCommands.at( i ) )->needsMotion() ) {
  233. m_awaitingMotionOrTextObject.push( m_keys.size() );
  234. break;
  235. }
  236. }
  237. } else {
  238. // go through all registered commands and put possible matches in m_matchingCommands
  239. for ( int i = 0; i < m_commands.size(); i++ ) {
  240. if ( m_commands.at( i )->matches( m_keys ) ) {
  241. m_matchingCommands.push_back( i );
  242. if ( m_commands.at( i )->needsMotion() && m_commands.at( i )->pattern().length() == m_keys.size() ) {
  243. m_awaitingMotionOrTextObject.push( m_keys.size() );
  244. }
  245. }
  246. }
  247. }
  248. // this indicates where in the command string one should start looking for a motion command
  249. int checkFrom = ( m_awaitingMotionOrTextObject.isEmpty() ? 0 : m_awaitingMotionOrTextObject.top() );
  250. // Use operator-pending caret when reading a motion for an operator
  251. // in normal mode. We need to check that we are indeed in normal mode
  252. // since visual mode inherits from it.
  253. if( m_viInputModeManager->getCurrentViMode() == NormalMode &&
  254. !m_awaitingMotionOrTextObject.isEmpty() ) {
  255. m_view->setCaretStyle( KateRenderer::Half, true );
  256. }
  257. //kDebug( 13070 ) << "checkFrom: " << checkFrom;
  258. // look for matching motion commands from position 'checkFrom'
  259. // FIXME: if checkFrom hasn't changed, only motions whose index is in
  260. // m_matchingMotions should be checked
  261. if ( checkFrom < m_keys.size() ) {
  262. for ( int i = 0; i < m_motions.size(); i++ ) {
  263. //kDebug( 13070 ) << "\tchecking " << m_keys.mid( checkFrom ) << " against " << m_motions.at( i )->pattern();
  264. if ( m_motions.at( i )->matches( m_keys.mid( checkFrom ) ) ) {
  265. //kDebug( 13070 ) << m_keys.mid( checkFrom ) << " matches!";
  266. m_matchingMotions.push_back( i );
  267. // if it matches exact, we have found the motion command to execute
  268. if ( m_motions.at( i )->matchesExact( m_keys.mid( checkFrom ) ) ) {
  269. if ( checkFrom == 0 ) {
  270. // no command given before motion, just move the cursor to wherever
  271. // the motion says it should go to
  272. KateViRange r = m_motions.at( i )->execute();
  273. // jump over folding regions since we are just moving the cursor
  274. int currLine = m_view->cursorPosition().line();
  275. int delta = r.endLine - currLine;
  276. int vline = doc()->foldingTree()->getVirtualLine( currLine );
  277. r.endLine = doc()->foldingTree()->getRealLine( vline+delta );
  278. if ( r.endLine >= doc()->lines() ) r.endLine = doc()->lines()-1;
  279. // make sure the position is valid before moving the cursor there
  280. // TODO: can this be simplified? :/
  281. if ( r.valid
  282. && r.endLine >= 0
  283. && ( r.endLine == 0 || r.endLine <= doc()->lines()-1 )
  284. && r.endColumn >= 0 ) {
  285. if ( r.endColumn >= doc()->lineLength( r.endLine )
  286. && doc()->lineLength( r.endLine ) > 0 ) {
  287. r.endColumn = doc()->lineLength( r.endLine ) - 1;
  288. }
  289. kDebug( 13070 ) << "No command given, going to position ("
  290. << r.endLine << "," << r.endColumn << ")";
  291. goToPos( r );
  292. m_viInputModeManager->clearLog();
  293. } else {
  294. kDebug( 13070 ) << "Invalid position: (" << r.endLine << "," << r.endColumn << ")";
  295. }
  296. resetParser();
  297. // if normal mode was started by using Ctrl-O in insert mode,
  298. // it's time to go back to insert mode.
  299. if (m_viInputModeManager->getTemporaryNormalMode()) {
  300. startInsertMode();
  301. m_viewInternal->repaint();
  302. }
  303. return true;
  304. } else {
  305. // execute the specified command and supply the position returned from
  306. // the motion
  307. m_commandRange = m_motions.at( i )->execute();
  308. m_linewiseCommand = m_motions.at( i )->isLineWise();
  309. // if we didn't get an explicit start position, use the current cursor position
  310. if ( m_commandRange.startLine == -1 ) {
  311. Cursor c( m_view->cursorPosition() );
  312. m_commandRange.startLine = c.line();
  313. m_commandRange.startColumn = c.column();
  314. }
  315. // special case: When using the "w" motion in combination with an operator and
  316. // the last word moved over is at the end of a line, the end of that word
  317. // becomes the end of the operated text, not the first word in the next line.
  318. if ( m_keys.right(1) == "w" || m_keys.right(1) == "W" ) {
  319. if(m_commandRange.endLine != m_commandRange.startLine &&
  320. m_commandRange.endColumn == getLine(m_commandRange.endLine).indexOf( QRegExp("\\S") )){
  321. m_commandRange.endLine--;
  322. m_commandRange.endColumn = doc()->lineLength(m_commandRange.endLine );
  323. }
  324. }
  325. m_commandWithMotion = true;
  326. if ( m_commandRange.valid ) {
  327. kDebug( 13070 ) << "Run command" << m_commands.at( m_motionOperatorIndex )->pattern()
  328. << "from (" << m_commandRange.startLine << "," << m_commandRange.endLine << ")"
  329. << "to (" << m_commandRange.endLine << "," << m_commandRange.endColumn << ")";
  330. executeCommand( m_commands.at( m_motionOperatorIndex ) );
  331. } else {
  332. kDebug( 13070 ) << "Invalid range: "
  333. << "from (" << m_commandRange.startLine << "," << m_commandRange.endLine << ")"
  334. << "to (" << m_commandRange.endLine << "," << m_commandRange.endColumn << ")";
  335. }
  336. if( m_viInputModeManager->getCurrentViMode() == NormalMode ) {
  337. m_view->setCaretStyle( KateRenderer::Block, true );
  338. }
  339. m_commandWithMotion = false;
  340. reset();
  341. return true;
  342. }
  343. }
  344. }
  345. }
  346. }
  347. //kDebug( 13070 ) << "'" << m_keys << "' MATCHING COMMANDS: " << m_matchingCommands.size();
  348. //kDebug( 13070 ) << "'" << m_keys << "' MATCHING MOTIONS: " << m_matchingMotions.size();
  349. //kDebug( 13070 ) << "'" << m_keys << "' AWAITING MOTION OR TO (INDEX): " << ( m_awaitingMotionOrTextObject.isEmpty() ? 0 : m_awaitingMotionOrTextObject.top() );
  350. // if we have only one match, check if it is a perfect match and if so, execute it
  351. // if it's not waiting for a motion or a text object
  352. if ( m_matchingCommands.size() == 1 ) {
  353. if ( m_commands.at( m_matchingCommands.at( 0 ) )->matchesExact( m_keys )
  354. && !m_commands.at( m_matchingCommands.at( 0 ) )->needsMotion() ) {
  355. //kDebug( 13070 ) << "Running command at index " << m_matchingCommands.at( 0 );
  356. if( m_viInputModeManager->getCurrentViMode() == NormalMode ) {
  357. m_view->setCaretStyle( KateRenderer::Block, true );
  358. }
  359. KateViCommand *cmd = m_commands.at( m_matchingCommands.at( 0 ) );
  360. executeCommand( cmd );
  361. // check if reset() should be called. some commands in visual mode should not end visual mode
  362. if ( cmd->shouldReset() ) {
  363. reset();
  364. m_view->setBlockSelectionMode(false);
  365. }
  366. resetParser();
  367. return true;
  368. }
  369. } else if ( m_matchingCommands.size() == 0 && m_matchingMotions.size() == 0 ) {
  370. resetParser();
  371. return false;
  372. }
  373. m_matchingMotions.clear();
  374. return false;
  375. }
  376. /**
  377. * (re)set to start configuration. This is done when a command is completed
  378. * executed or when a command is aborted
  379. */
  380. void KateViNormalMode::resetParser()
  381. {
  382. // kDebug( 13070 ) << "***RESET***";
  383. m_keys.clear();
  384. m_keysVerbatim.clear();
  385. m_count = 0;
  386. m_iscounted = false;
  387. m_countTemp = 0;
  388. m_register = QChar::Null;
  389. m_findWaitingForChar = false;
  390. m_matchingCommands.clear();
  391. m_matchingMotions.clear();
  392. m_awaitingMotionOrTextObject.clear();
  393. m_motionOperatorIndex = 0;
  394. m_commandWithMotion = false;
  395. m_linewiseCommand = true;
  396. m_deleteCommand = false;
  397. m_commandShouldKeepSelection = false;
  398. }
  399. // reset the command parser
  400. void KateViNormalMode::reset()
  401. {
  402. resetParser();
  403. m_commandRange.startLine = -1;
  404. m_commandRange.startColumn = -1;
  405. }
  406. void KateViNormalMode::setMappingTimeout(int timeoutMS)
  407. {
  408. m_timeoutlen = timeoutMS;
  409. }
  410. void KateViNormalMode::goToPos( const KateViRange &r )
  411. {
  412. Cursor c;
  413. c.setLine( r.endLine );
  414. c.setColumn( r.endColumn );
  415. if ( r.jump ) {
  416. addCurrentPositionToJumpList();
  417. }
  418. if ( c.line() >= doc()->lines() ) {
  419. c.setLine( doc()->lines()-1 );
  420. }
  421. updateCursor( c );
  422. }
  423. void KateViNormalMode::executeCommand( const KateViCommand* cmd )
  424. {
  425. cmd->execute();
  426. // if normal mode was started by using Ctrl-O in insert mode,
  427. // it's time to go back to insert mode.
  428. if (m_viInputModeManager->getTemporaryNormalMode()) {
  429. startInsertMode();
  430. m_viewInternal->repaint();
  431. }
  432. // if the command was a change, and it didn't enter insert mode, store the key presses so that
  433. // they can be repeated with '.'
  434. if ( m_viInputModeManager->getCurrentViMode() != InsertMode ) {
  435. if ( cmd->isChange() && !m_viInputModeManager->isReplayingLastChange() ) {
  436. m_viInputModeManager->storeChangeCommand();
  437. }
  438. m_viInputModeManager->clearLog();
  439. }
  440. // make sure the cursor does not end up after the end of the line
  441. Cursor c( m_view->cursorPosition() );
  442. if ( m_viInputModeManager->getCurrentViMode() == NormalMode ) {
  443. int lineLength = doc()->lineLength( c.line() );
  444. if ( c.column() >= lineLength ) {
  445. if ( lineLength == 0 ) {
  446. c.setColumn( 0 );
  447. } else {
  448. c.setColumn( lineLength-1 );
  449. }
  450. }
  451. updateCursor( c );
  452. }
  453. }
  454. void KateViNormalMode::addCurrentPositionToJumpList() {
  455. m_viInputModeManager->addJump(m_view->cursorPosition());
  456. }
  457. ////////////////////////////////////////////////////////////////////////////////
  458. // COMMANDS AND OPERATORS
  459. ////////////////////////////////////////////////////////////////////////////////
  460. /**
  461. * enter insert mode at the cursor position
  462. */
  463. bool KateViNormalMode::commandEnterInsertMode()
  464. {
  465. m_stickyColumn = -1;
  466. return startInsertMode();
  467. }
  468. /**
  469. * enter insert mode after the current character
  470. */
  471. bool KateViNormalMode::commandEnterInsertModeAppend()
  472. {
  473. Cursor c( m_view->cursorPosition() );
  474. c.setColumn( c.column()+1 );
  475. // if empty line, the cursor should start at column 0
  476. if ( doc()->lineLength( c.line() ) == 0 ) {
  477. c.setColumn( 0 );
  478. }
  479. // cursor should never be in a column > number of columns
  480. if ( c.column() > doc()->lineLength( c.line() ) ) {
  481. c.setColumn( doc()->lineLength( c.line() ) );
  482. }
  483. updateCursor( c );
  484. m_stickyColumn = -1;
  485. return startInsertMode();
  486. }
  487. /**
  488. * start insert mode after the last character of the line
  489. */
  490. bool KateViNormalMode::commandEnterInsertModeAppendEOL()
  491. {
  492. Cursor c( m_view->cursorPosition() );
  493. c.setColumn( doc()->lineLength( c.line() ) );
  494. updateCursor( c );
  495. m_stickyColumn = -1;
  496. return startInsertMode();
  497. }
  498. bool KateViNormalMode::commandEnterInsertModeBeforeFirstNonBlankInLine()
  499. {
  500. Cursor cursor( m_view->cursorPosition() );
  501. QRegExp nonSpace( "\\S" );
  502. int c = getLine().indexOf( nonSpace );
  503. if ( c == -1 ) {
  504. c = 0;
  505. }
  506. cursor.setColumn( c );
  507. updateCursor( cursor );
  508. m_stickyColumn = -1;
  509. return startInsertMode();
  510. }
  511. /**
  512. * enter insert mode at the last insert position
  513. */
  514. bool KateViNormalMode::commandEnterInsertModeLast()
  515. {
  516. Cursor c = m_view->getViInputModeManager()->getMarkPosition( '^' );
  517. if ( c.isValid() ) {
  518. updateCursor( c );
  519. }
  520. m_stickyColumn = -1;
  521. return startInsertMode();
  522. }
  523. bool KateViNormalMode::commandEnterVisualLineMode()
  524. {
  525. if ( m_viInputModeManager->getCurrentViMode() == VisualLineMode ) {
  526. reset();
  527. return true;
  528. }
  529. return startVisualLineMode();
  530. }
  531. bool KateViNormalMode::commandEnterVisualBlockMode()
  532. {
  533. if ( m_viInputModeManager->getCurrentViMode() == VisualBlockMode ) {
  534. reset();
  535. return true;
  536. }
  537. return startVisualBlockMode();
  538. }
  539. bool KateViNormalMode::commandReselectVisual()
  540. {
  541. // start last visual mode and set start = `< and cursor = `>
  542. Cursor c1 = m_view->getViInputModeManager()->getMarkPosition( '<' );
  543. Cursor c2 = m_view->getViInputModeManager()->getMarkPosition( '>' );
  544. // we should either get two valid cursors or two invalid cursors
  545. Q_ASSERT( c1.isValid() == c2.isValid() );
  546. if ( c1.isValid() && c2.isValid() ) {
  547. m_viInputModeManager->getViVisualMode()->setStart( c1 );
  548. updateCursor( c2 );
  549. switch ( m_viInputModeManager->getViVisualMode()->getLastVisualMode() ) {
  550. case VisualMode:
  551. return commandEnterVisualMode();
  552. break;
  553. case VisualLineMode:
  554. return commandEnterVisualLineMode();
  555. break;
  556. case VisualBlockMode:
  557. return commandEnterVisualBlockMode();
  558. break;
  559. default:
  560. Q_ASSERT( "invalid visual mode" );
  561. }
  562. } else {
  563. error("No previous visual selection");
  564. }
  565. return false;
  566. }
  567. bool KateViNormalMode::commandEnterVisualMode()
  568. {
  569. if ( m_viInputModeManager->getCurrentViMode() == VisualMode ) {
  570. reset();
  571. return true;
  572. }
  573. return startVisualMode();
  574. }
  575. bool KateViNormalMode::commandToOtherEnd()
  576. {
  577. if ( m_viInputModeManager->getCurrentViMode() == VisualMode
  578. || m_viInputModeManager->getCurrentViMode() == VisualLineMode
  579. || m_viInputModeManager->getCurrentViMode() == VisualBlockMode ) {
  580. m_viInputModeManager->getViVisualMode()->switchStartEnd();
  581. return true;
  582. }
  583. return false;
  584. }
  585. bool KateViNormalMode::commandEnterReplaceMode()
  586. {
  587. return startReplaceMode();
  588. }
  589. bool KateViNormalMode::commandDeleteLine()
  590. {
  591. Cursor c( m_view->cursorPosition() );
  592. KateViRange r;
  593. r.startLine = c.line();
  594. r.endLine = c.line()+getCount()-1;
  595. int column = c.column();
  596. bool ret = deleteRange( r, LineWise );
  597. c = m_view->cursorPosition();
  598. if ( column > doc()->lineLength( c.line() )-1 ) {
  599. column = doc()->lineLength( c.line() )-1;
  600. }
  601. if ( column < 0 ) {
  602. column = 0;
  603. }
  604. if ( c.line() > doc()->lines()-1 ) {
  605. c.setLine( doc()->lines()-1 );
  606. }
  607. c.setColumn( column );
  608. m_stickyColumn = -1;
  609. updateCursor( c );
  610. m_deleteCommand = true;
  611. return ret;
  612. }
  613. bool KateViNormalMode::commandDelete()
  614. {
  615. m_deleteCommand = true;
  616. return deleteRange( m_commandRange, getOperationMode() );
  617. }
  618. bool KateViNormalMode::commandDeleteToEOL()
  619. {
  620. Cursor c( m_view->cursorPosition() );
  621. OperationMode m = CharWise;
  622. if ( m_viInputModeManager->getCurrentViMode() == NormalMode ) {
  623. m_commandRange.startLine = c.line();
  624. m_commandRange.startColumn = c.column();
  625. m_commandRange.endLine = c.line()+getCount()-1;
  626. m_commandRange.endColumn = doc()->lineLength( m_commandRange.endLine )-1;
  627. }
  628. if ( m_viInputModeManager->getCurrentViMode() == VisualMode
  629. || m_viInputModeManager->getCurrentViMode() == VisualLineMode ) {
  630. m = LineWise;
  631. } else if ( m_viInputModeManager->getCurrentViMode() == VisualBlockMode ) {
  632. m_commandRange.normalize();
  633. m_commandRange.endColumn = KateVi::EOL;
  634. m = Block;
  635. }
  636. bool r = deleteRange( m_commandRange, m );
  637. switch (m) {
  638. case CharWise:
  639. c.setColumn( doc()->lineLength( c.line() )-1 );
  640. break;
  641. case LineWise:
  642. c.setLine( m_commandRange.startLine );
  643. c.setColumn( 0 ); // FIXME: should be first non-blank
  644. break;
  645. case Block:
  646. c.setLine( m_commandRange.startLine );
  647. c.setColumn( m_commandRange.startColumn-1 );
  648. break;
  649. }
  650. // make sure cursor position is valid after deletion
  651. if ( c.line() < 0 ) {
  652. c.setLine( 0 );
  653. }
  654. if ( c.line() > doc()->lastLine() ) {
  655. c.setLine( doc()->lastLine() );
  656. }
  657. if ( c.column() > doc()->lineLength( c.line() )-1 ) {
  658. c.setColumn( doc()->lineLength( c.line() )-1 );
  659. }
  660. if ( c.column() < 0 ) {
  661. c.setColumn( 0 );
  662. }
  663. updateCursor( c );
  664. m_deleteCommand = true;
  665. return r;
  666. }
  667. bool KateViNormalMode::commandMakeLowercase()
  668. {
  669. Cursor c = m_view->cursorPosition();
  670. OperationMode m = getOperationMode();
  671. QString text = getRange( m_commandRange, m );
  672. if (m == LineWise)
  673. text = text.left(text.size() - 1); // don't need '\n' at the end;
  674. QString lowerCase = text.toLower();
  675. m_commandRange.normalize();
  676. Cursor start( m_commandRange.startLine, m_commandRange.startColumn );
  677. Cursor end( m_commandRange.endLine, m_commandRange.endColumn );
  678. Range range( start, end );
  679. doc()->replaceText( range, lowerCase, m == Block );
  680. if (m_viInputModeManager->getCurrentViMode() == NormalMode)
  681. updateCursor( start );
  682. else
  683. updateCursor(c);
  684. return true;
  685. }
  686. bool KateViNormalMode::commandMakeLowercaseLine()
  687. {
  688. Cursor c( m_view->cursorPosition() );
  689. m_commandRange.startLine = c.line();
  690. m_commandRange.endLine = c.line() + getCount() - 1;
  691. m_commandRange.startColumn = 0;
  692. m_commandRange.endColumn = doc()->lineLength( c.line() )-1;
  693. return commandMakeLowercase();
  694. }
  695. bool KateViNormalMode::commandMakeUppercase()
  696. {
  697. Cursor c = m_view->cursorPosition();
  698. OperationMode m = getOperationMode();
  699. QString text = getRange( m_commandRange, m );
  700. if (m == LineWise)
  701. text = text.left(text.size() - 1); // don't need '\n' at the end;
  702. QString upperCase = text.toUpper();
  703. m_commandRange.normalize();
  704. Cursor start( m_commandRange.startLine, m_commandRange.startColumn );
  705. Cursor end( m_commandRange.endLine, m_commandRange.endColumn );
  706. Range range( start, end );
  707. doc()->replaceText( range, upperCase, m == Block );
  708. if (m_viInputModeManager->getCurrentViMode() == NormalMode)
  709. updateCursor( start );
  710. else
  711. updateCursor(c);
  712. return true;
  713. }
  714. bool KateViNormalMode::commandMakeUppercaseLine()
  715. {
  716. Cursor c( m_view->cursorPosition() );
  717. m_commandRange.startLine = c.line();
  718. m_commandRange.endLine = c.line() + getCount() - 1;
  719. m_commandRange.startColumn = 0;
  720. m_commandRange.endColumn = doc()->lineLength( c.line() )-1;
  721. return commandMakeUppercase();
  722. }
  723. bool KateViNormalMode::commandChangeCase()
  724. {
  725. switchView();
  726. QString text;
  727. Range range;
  728. Cursor c( m_view->cursorPosition() );
  729. // in visual mode, the range is from start position to end position...
  730. if ( m_viInputModeManager->getCurrentViMode() == VisualMode
  731. || m_viInputModeManager->getCurrentViMode() == VisualBlockMode ) {
  732. Cursor c2 = m_viInputModeManager->getViVisualMode()->getStart();
  733. if ( c2 > c ) {
  734. c2.setColumn( c2.column()+1 );
  735. } else {
  736. c.setColumn( c.column()+1 );
  737. }
  738. range.setRange( c, c2 );
  739. // ... in visual line mode, the range is from column 0 on the first line to
  740. // the line length of the last line...
  741. } else if ( m_viInputModeManager->getCurrentViMode() == VisualLineMode ) {
  742. Cursor c2 = m_viInputModeManager->getViVisualMode()->getStart();
  743. if ( c2 > c ) {
  744. c2.setColumn( doc()->lineLength( c2.line() ) );
  745. c.setColumn( 0 );
  746. } else {
  747. c.setColumn( doc()->lineLength( c.line() ) );
  748. c2.setColumn( 0 );
  749. }
  750. range.setRange( c, c2 );
  751. // ... and in normal mode the range is from the current position to the
  752. // current position + count
  753. } else {
  754. Cursor c2 = c;
  755. c2.setColumn( c.column()+getCount() );
  756. if ( c2.column() > doc()->lineLength( c.line() ) ) {
  757. c2.setColumn( doc()->lineLength( c.line() ) );
  758. }
  759. range.setRange( c, c2 );
  760. }
  761. bool block = m_viInputModeManager->getCurrentViMode() == VisualBlockMode;
  762. // get the text the command should operate on
  763. text = doc()->text ( range, block );
  764. // for every character, switch its case
  765. for ( int i = 0; i < text.length(); i++ ) {
  766. if ( text.at(i).isUpper() ) {
  767. text[i] = text.at(i).toLower();
  768. } else if ( text.at(i).isLower() ) {
  769. text[i] = text.at(i).toUpper();
  770. }
  771. }
  772. // replace the old text with the modified text
  773. doc()->replaceText( range, text, block );
  774. // in normal mode, move the cursor to the right, in visual mode move the
  775. // cursor to the start of the selection
  776. if ( m_viInputModeManager->getCurrentViMode() == NormalMode ) {
  777. updateCursor( range.end() );
  778. } else {
  779. updateCursor( range.start() );
  780. }
  781. return true;
  782. }
  783. bool KateViNormalMode::commandOpenNewLineUnder()
  784. {
  785. Cursor c( m_view->cursorPosition() );
  786. c.setColumn( doc()->lineLength( c.line() ) );
  787. updateCursor( c );
  788. for ( unsigned int i = 0; i < getCount(); i++ ) {
  789. doc()->newLine( m_view );
  790. }
  791. m_stickyColumn = -1;
  792. startInsertMode();
  793. m_viewInternal->repaint ();
  794. return true;
  795. }
  796. bool KateViNormalMode::commandOpenNewLineOver()
  797. {
  798. Cursor c( m_view->cursorPosition() );
  799. if ( c.line() == 0 ) {
  800. for (unsigned int i = 0; i < getCount(); i++ ) {
  801. doc()->insertLine( 0, QString() );
  802. }
  803. c.setColumn( 0 );
  804. c.setLine( 0 );
  805. updateCursor( c );
  806. } else {
  807. c.setLine( c.line()-1 );
  808. c.setColumn( getLine( c.line() ).length() );
  809. updateCursor( c );
  810. for ( unsigned int i = 0; i < getCount(); i++ ) {
  811. doc()->newLine( m_view );
  812. }
  813. if ( getCount() > 1 ) {
  814. c = m_view->cursorPosition();
  815. c.setLine( c.line()-(getCount()-1 ) );
  816. updateCursor( c );
  817. }
  818. //c.setLine( c.line()-getCount() );
  819. }
  820. m_stickyColumn = -1;
  821. startInsertMode();
  822. m_viewInternal->repaint ();
  823. return true;
  824. }
  825. bool KateViNormalMode::commandJoinLines()
  826. {
  827. Cursor c( m_view->cursorPosition() );
  828. // remember line length so the cursor can be put between the joined lines
  829. int l = doc()->lineLength( c.line() );
  830. unsigned int from = c.line();
  831. unsigned int to = c.line()+getCount();
  832. // if we were given a range of lines, this information overrides the previous
  833. if ( m_commandRange.startLine != -1 && m_commandRange.endLine != -1 ) {
  834. m_commandRange.normalize();
  835. c.setLine ( m_commandRange.startLine );
  836. to = m_commandRange.endLine;
  837. }
  838. joinLines( from, to );
  839. // position cursor between the joined lines
  840. c.setColumn( l );
  841. updateCursor( c );
  842. m_deleteCommand = true;
  843. return true;
  844. }
  845. bool KateViNormalMode::commandChange()
  846. {
  847. Cursor c( m_view->cursorPosition() );
  848. OperationMode m = getOperationMode();
  849. doc()->editStart();
  850. commandDelete();
  851. // if we deleted several lines, insert an empty line and put the cursor there
  852. if ( m == LineWise ) {
  853. doc()->insertLine( m_commandRange.startLine, QString() );
  854. c.setLine( m_commandRange.startLine );
  855. c.setColumn(0);
  856. }
  857. doc()->editEnd();
  858. if ( m == LineWise ) {
  859. updateCursor( c );
  860. }
  861. // block substitute can be simulated by first deleting the text (done above) and then starting
  862. // block prepend
  863. if ( m == Block ) {
  864. return commandPrependToBlock();
  865. }
  866. commandEnterInsertMode();
  867. // correct indentation level
  868. if ( m == LineWise ) {
  869. m_view->align();
  870. }
  871. m_deleteCommand = true;
  872. return true;
  873. }
  874. bool KateViNormalMode::commandChangeToEOL()
  875. {
  876. commandDeleteToEOL();
  877. if ( getOperationMode() == Block ) {
  878. return commandPrependToBlock();
  879. }
  880. m_deleteCommand = true;
  881. return commandEnterInsertModeAppend();
  882. }
  883. bool KateViNormalMode::commandChangeLine()
  884. {
  885. m_deleteCommand = true;
  886. Cursor c( m_view->cursorPosition() );
  887. c.setColumn( 0 );
  888. updateCursor( c );
  889. doc()->editStart();
  890. // if count >= 2 start by deleting the whole lines
  891. if ( getCount() >= 2 ) {
  892. KateViRange r( c.line(), 0, c.line()+getCount()-2, 0, ViMotion::InclusiveMotion );
  893. deleteRange( r );
  894. }
  895. // ... then delete the _contents_ of the last line, but keep the line
  896. KateViRange r( c.line(), c.column(), c.line(), doc()->lineLength( c.line() )-1,
  897. ViMotion::InclusiveMotion );
  898. deleteRange( r, CharWise, true );
  899. doc()->editEnd();
  900. // ... then enter insert mode
  901. if ( getOperationMode() == Block ) {
  902. return commandPrependToBlock();
  903. }
  904. commandEnterInsertModeAppend();
  905. // correct indentation level
  906. m_view->align();
  907. return true;
  908. }
  909. bool KateViNormalMode::commandSubstituteChar()
  910. {
  911. if ( commandDeleteChar() ) {
  912. return commandEnterInsertMode();
  913. }
  914. m_deleteCommand = true;
  915. return false;
  916. }
  917. bool KateViNormalMode::commandSubstituteLine()
  918. {
  919. m_deleteCommand = true;
  920. return commandChangeLine();
  921. }
  922. bool KateViNormalMode::commandYank()
  923. {
  924. Cursor c( m_view->cursorPosition() );
  925. bool r = false;
  926. QString yankedText;
  927. OperationMode m = getOperationMode();
  928. yankedText = getRange( m_commandRange, m );
  929. fillRegister( getChosenRegister( '0' ), yankedText, m );
  930. return r;
  931. }
  932. bool KateViNormalMode::commandYankLine()
  933. {
  934. Cursor c( m_view->cursorPosition() );
  935. QString lines;
  936. int linenum = c.line();
  937. for ( unsigned int i = 0; i < getCount(); i++ ) {
  938. lines.append( getLine( linenum + i ) + '\n' );
  939. }
  940. fillRegister( getChosenRegister( '0' ), lines, LineWise );
  941. return true;
  942. }
  943. bool KateViNormalMode::commandYankToEOL()
  944. {
  945. Cursor c( m_view->cursorPosition() );
  946. bool r = false;
  947. QString yankedText;
  948. m_commandRange.endLine = c.line()+getCount()-1;
  949. m_commandRange.endColumn = doc()->lineLength( m_commandRange.endLine )-1;
  950. OperationMode m = CharWise;
  951. if ( m_viInputModeManager->getCurrentViMode() == VisualMode
  952. || m_viInputModeManager->getCurrentViMode() == VisualLineMode ) {
  953. m = LineWise;
  954. KateViVisualMode* visualmode = static_cast<KateViVisualMode*>(this);
  955. visualmode->setStart( Cursor(visualmode->getStart().line(),0) );
  956. } else if (m_viInputModeManager->getCurrentViMode() == VisualBlockMode ) {
  957. m = Block;;
  958. }
  959. if ( m_viInputModeManager->getCurrentViMode() == NormalMode ) {
  960. m_commandRange.startLine = c.line();
  961. m_commandRange.startColumn = c.column();
  962. }
  963. yankedText = getRange( m_commandRange, m );
  964. fillRegister( getChosenRegister( '0' ), yankedText, m );
  965. return r;
  966. }
  967. // insert the text in the given register at the cursor position
  968. // the cursor should end up at the beginning of what was pasted
  969. bool KateViNormalMode::commandPasteLeaveCursorAtStart()
  970. {
  971. return paste(true);
  972. }
  973. // insert the text in the given register before the cursor position
  974. // the cursor should end up at the beginning of what was pasted
  975. bool KateViNormalMode::commandPasteBeforeLeaveCursorAtStart()
  976. {
  977. return pasteBefore(true);
  978. }
  979. // as with commandPasteLeaveCursorAtStart, but leaves the cursor at the end
  980. // of what was pasted
  981. bool KateViNormalMode::commandPasteLeaveCursorAtEnd()
  982. {
  983. return paste(false);
  984. }
  985. // as with commandPasteBeforeLeaveCursorAtStart, but leaves the cursor at the end
  986. // of what was pasted
  987. bool KateViNormalMode::commandPasteBeforeLeaveCursorAtEnd()
  988. {
  989. return pasteBefore(false);
  990. }
  991. bool KateViNormalMode::commandDeleteChar()
  992. {
  993. Cursor c( m_view->cursorPosition() );
  994. KateViRange r( c.line(), c.column(), c.line(), c.column()+getCount(), ViMotion::ExclusiveMotion );
  995. if ( m_commandRange.startLine != -1 && m_commandRange.startColumn != -1 ) {
  996. r = m_commandRange;
  997. } else {
  998. if ( r.endColumn > doc()->lineLength( r.startLine ) ) {
  999. r.endColumn = doc()->lineLength( r.startLine );
  1000. }
  1001. }
  1002. // should delete entire lines if in visual line mode and selection in visual block mode
  1003. OperationMode m = CharWise;
  1004. if ( m_viInputModeManager->getCurrentViMode() == VisualLineMode ) {
  1005. m = LineWise;
  1006. } else if ( m_viInputModeManager->getCurrentViMode() == VisualBlockMode ) {
  1007. m = Block;
  1008. }
  1009. m_deleteCommand = true;
  1010. return deleteRange( r, m );
  1011. }
  1012. bool KateViNormalMode::commandDeleteCharBackward()
  1013. {
  1014. Cursor c( m_view->cursorPosition() );
  1015. KateViRange r( c.line(), c.column()-getCount(), c.line(), c.column(), ViMotion::ExclusiveMotion );
  1016. if ( m_commandRange.startLine != -1 && m_commandRange.startColumn != -1 ) {
  1017. r = m_commandRange;
  1018. } else {
  1019. if ( r.startColumn < 0 ) {
  1020. r.startColumn = 0;
  1021. }
  1022. }
  1023. // should delete entire lines if in visual line mode and selection in visual block mode
  1024. OperationMode m = CharWise;
  1025. if ( m_viInputModeManager->getCurrentViMode() == VisualLineMode ) {
  1026. m = LineWise;
  1027. } else if ( m_viInputModeManager->getCurrentViMode() == VisualBlockMode ) {
  1028. m = Block;
  1029. }
  1030. m_deleteCommand = true;
  1031. return deleteRange( r, m );
  1032. }
  1033. bool KateViNormalMode::commandReplaceCharacter()
  1034. {
  1035. bool r;
  1036. if ( m_viInputModeManager->getCurrentViMode() == VisualMode
  1037. || m_viInputModeManager->getCurrentViMode() == VisualLineMode
  1038. || m_viInputModeManager->getCurrentViMode() == VisualBlockMode ) {
  1039. OperationMode m = getOperationMode();
  1040. QString text = getRange( m_commandRange, m );
  1041. if (m == LineWise)
  1042. text = text.left(text.size() - 1); // don't need '\n' at the end;
  1043. text.replace( QRegExp( "[^\n]" ), m_keys.right( 1 ) );
  1044. m_commandRange.normalize();
  1045. Cursor start( m_commandRange.startLine, m_commandRange.startColumn );
  1046. Cursor end( m_commandRange.endLine, m_commandRange.endColumn );
  1047. Range range( start, end );
  1048. r = doc()->replaceText( range, text, m == Block );
  1049. } else {
  1050. Cursor c1( m_view->cursorPosition() );
  1051. Cursor c2( m_view->cursorPosition() );
  1052. c2.setColumn( c2.column()+1 );
  1053. r = doc()->replaceText( Range( c1, c2 ), m_keys.right( 1 ) );
  1054. updateCursor( c1 );
  1055. }
  1056. m_ignoreMapping = false;
  1057. return r;
  1058. }
  1059. bool KateViNormalMode::commandSwitchToCmdLine()
  1060. {
  1061. Cursor c( m_view->cursorPosition() );
  1062. m_view->switchToCmdLine();
  1063. if ( m_viInputModeManager->getCurrentViMode() == VisualMode
  1064. || m_viInputModeManager->getCurrentViMode() == VisualLineMode
  1065. || m_viInputModeManager->getCurrentViMode() == VisualBlockMode ) {
  1066. // if in visual mode, make command range == visual selection
  1067. m_viInputModeManager->getViVisualMode()->saveRangeMarks();
  1068. m_view->cmdLineBar()->setText( "'<,'>", false );
  1069. }
  1070. else if ( getCount() != 1 ) {
  1071. // if a count is given, the range [current line] to [current line] +
  1072. // count should be prepended to the command line
  1073. m_view->cmdLineBar()->setText( ".,.+" +QString::number( getCount()-1 ), false);
  1074. }
  1075. m_commandShouldKeepSelection = true;
  1076. return true;
  1077. }
  1078. bool KateViNormalMode::commandSearchBackward()
  1079. {
  1080. m_view->find();
  1081. m_viInputModeManager->setLastSearchBackwards( true );
  1082. return true;
  1083. }
  1084. bool KateViNormalMode::commandSearchForward()
  1085. {
  1086. m_view->find();
  1087. m_viInputModeManager->setLastSearchBackwards( false );
  1088. return true;
  1089. }
  1090. bool KateViNormalMode::commandUndo()
  1091. {
  1092. doc()->undo();
  1093. return true;
  1094. }
  1095. bool KateViNormalMode::commandRedo()
  1096. {
  1097. doc()->redo();
  1098. return true;
  1099. }
  1100. bool KateViNormalMode::commandSetMark()
  1101. {
  1102. Cursor c( m_view->cursorPosition() );
  1103. m_view->getViInputModeManager()->addMark( doc(), m_keys.at( m_keys.size()-1 ), c );
  1104. kDebug( 13070 ) << "set mark at (" << c.line() << "," << c.column() << ")";
  1105. return true;
  1106. }
  1107. bool KateViNormalMode::commandIndentLine()
  1108. {
  1109. Cursor c( m_view->cursorPosition() );
  1110. for ( unsigned int i = 0; i < getCount(); i++ ) {
  1111. doc()->indent( KTextEditor::Range( c.line()+i, 0, c.line()+i, 0), 1 );
  1112. }
  1113. return true;
  1114. }
  1115. bool KateViNormalMode::commandUnindentLine()
  1116. {
  1117. Cursor c( m_view->cursorPosition() );
  1118. for ( unsigned int i = 0; i < getCount(); i++ ) {
  1119. doc()->indent( KTextEditor::Range( c.line()+i, 0, c.line()+i, 0), -1 );
  1120. }
  1121. return true;
  1122. }
  1123. bool KateViNormalMode::commandIndentLines()
  1124. {
  1125. Cursor c( m_view->cursorPosition() );
  1126. m_commandRange.normalize();
  1127. int line1 = m_commandRange.startLine;
  1128. int line2 = m_commandRange.endLine;
  1129. int col = getLine( line2 ).length();
  1130. doc()->indent( KTextEditor::Range( line1, 0, line2, col ), getCount() );
  1131. return true;
  1132. }
  1133. bool KateViNormalMode::commandUnindentLines()
  1134. {
  1135. Cursor c( m_view->cursorPosition() );
  1136. m_commandRange.normalize();
  1137. int line1 = m_commandRange.startLine;
  1138. int line2 = m_commandRange.endLine;
  1139. doc()->indent( KTextEditor::Range( line1, 0, line2, doc()->lineLength( line2 ) ), -getCount() );
  1140. return true;
  1141. }
  1142. bool KateViNormalMode::commandScrollPageDown()
  1143. {
  1144. if ( getCount() < m_scroll_count_limit ) {
  1145. for(uint i = 0; i < getCount(); i++)
  1146. m_view->pageDown();
  1147. }
  1148. return true;
  1149. }
  1150. bool KateViNormalMode::commandScrollPageUp()
  1151. {
  1152. if ( getCount() < m_scroll_count_limit ) {
  1153. for(uint i=0; i < getCount(); i++)
  1154. m_view->pageUp();
  1155. }
  1156. return true;
  1157. }
  1158. bool KateViNormalMode::commandScrollHalfPageUp()
  1159. {
  1160. if ( getCount() < m_scroll_count_limit ) {
  1161. for(uint i=0; i < getCount(); i++)
  1162. m_viewInternal->pageUp(false, true);
  1163. }
  1164. return true;
  1165. }
  1166. bool KateViNormalMode::commandScrollHalfPageDown()
  1167. {
  1168. if ( getCount() < m_scroll_count_limit ) {
  1169. for(uint i=0; i < getCount(); i++)
  1170. m_viewInternal->pageDown(false, true);
  1171. }
  1172. return true;
  1173. }
  1174. bool KateViNormalMode::commandCentreViewOnCursor()
  1175. {
  1176. Cursor c( m_view->cursorPosition() );
  1177. int linesToScroll = (m_viewInternal->endLine()-linesDisplayed()/2)-c.line();
  1178. scrollViewLines( -linesToScroll );
  1179. return true;
  1180. }
  1181. bool KateViNormalMode::commandAbort()
  1182. {
  1183. m_pendingResetIsDueToExit = true;
  1184. reset();
  1185. return true;
  1186. }
  1187. bool KateViNormalMode::commandPrintCharacterCode()
  1188. {
  1189. QChar ch = getCharUnderCursor();
  1190. if ( ch == QChar::Null ) {
  1191. message( QString( "NUL" ) );
  1192. } else {
  1193. int code = ch.unicode();
  1194. QString dec = QString::number( code );
  1195. QString hex = QString::number( code, 16 );
  1196. QString oct = QString::number( code, 8 );
  1197. if ( oct.length() < 3 ) { oct.prepend( '0' ); }
  1198. if ( code > 0x80 && code < 0x1000 ) { hex.prepend( ( code < 0x100 ? "00" : "0" ) ); }
  1199. message( i18n("'%1' %2, Hex %3, Octal %4", ch, dec, hex, oct ) );
  1200. }
  1201. return true;
  1202. }
  1203. bool KateViNormalMode::commandRepeatLastChange()
  1204. {
  1205. resetParser();
  1206. doc()->editStart();
  1207. m_viInputModeManager->repeatLastChange();
  1208. doc()->editEnd();
  1209. return true;
  1210. }
  1211. bool KateViNormalMode::commandAlignLine()
  1212. {
  1213. const int line = m_view->cursorPosition().line();
  1214. Range alignRange( Cursor(line, 0), Cursor(line, 0) );
  1215. doc()->align( m_view, alignRange );
  1216. return true;
  1217. }
  1218. bool KateViNormalMode::commandAlignLines()
  1219. {
  1220. Cursor c( m_view->cursorPosition() );
  1221. m_commandRange.normalize();
  1222. Cursor start(m_commandRange.startLine, 0);
  1223. Cursor end(m_commandRange.endLine, 0);
  1224. doc()->align( m_view, Range( start, end ) );
  1225. return true;
  1226. }
  1227. bool KateViNormalMode::commandAddToNumber()
  1228. {
  1229. addToNumberUnderCursor( getCount() );
  1230. return true;
  1231. }
  1232. bool KateViNormalMode::commandSubtractFromNumber()
  1233. {
  1234. addToNumberUnderCursor( -getCount() );
  1235. return true;
  1236. }
  1237. bool KateViNormalMode::commandPrependToBlock()
  1238. {
  1239. Cursor c( m_view->cursorPosition() );
  1240. // move cursor to top left corner of selection
  1241. m_commandRange.normalize();
  1242. c.setColumn( m_commandRange.startColumn );
  1243. c.setLine( m_commandRange.startLine );
  1244. updateCursor( c );
  1245. m_stickyColumn = -1;
  1246. m_viInputModeManager->getViInsertMode()->setBlockPrependMode( m_commandRange );
  1247. return startInsertMode();
  1248. }
  1249. bool KateViNormalMode::commandAppendToBlock()
  1250. {
  1251. Cursor c( m_view->cursorPosition() );
  1252. m_commandRange.normalize();
  1253. if ( m_stickyColumn == (unsigned int)KateVi::EOL ) { // append to EOL
  1254. // move cursor to end of first line
  1255. c.setLine( m_commandRange.startLine );
  1256. c.setColumn( doc()->lineLength( c.line() ) );
  1257. updateCursor( c );
  1258. m_viInputModeManager->getViInsertMode()->setBlockAppendMode( m_commandRange, AppendEOL );
  1259. } else {
  1260. m_viInputModeManager->getViInsertMode()->setBlockAppendMode( m_commandRange, Append );
  1261. // move cursor to top right corner of selection
  1262. c.setColumn( m_commandRange.endColumn+1 );
  1263. c.setLine( m_commandRange.startLine );
  1264. updateCursor( c );
  1265. }
  1266. m_stickyColumn = -1;
  1267. return startInsertMode();
  1268. }
  1269. bool KateViNormalMode::commandGoToNextJump() {
  1270. Cursor c = getNextJump(m_view->cursorPosition());
  1271. updateCursor(c);
  1272. return true;
  1273. }
  1274. bool KateViNormalMode::commandGoToPrevJump() {
  1275. Cursor c = getPrevJump(m_view->cursorPosition());
  1276. updateCursor(c);
  1277. return true;
  1278. }
  1279. bool KateViNormalMode::commandSwitchToLeftView() {
  1280. switchView(Left);
  1281. return true;
  1282. }
  1283. bool KateViNormalMode::commandSwitchToDownView() {
  1284. switchView(Down);
  1285. return true;
  1286. }
  1287. bool KateViNormalMode::commandSwitchToUpView() {
  1288. switchView(Up);
  1289. return true;
  1290. }
  1291. bool KateViNormalMode::commandSwitchToRightView() {
  1292. switchView(Right);
  1293. return true;
  1294. }
  1295. bool KateViNormalMode::commandSwitchToNextView() {
  1296. switchView(Next);
  1297. return true;
  1298. }
  1299. bool KateViNormalMode::commandSplitHoriz() {
  1300. m_view->cmdLineBar()->execute("split");
  1301. return true;
  1302. }
  1303. bool KateViNormalMode::commandSplitVert() {
  1304. m_view->cmdLineBar()->execute("vsplit");
  1305. return true;
  1306. }
  1307. bool KateViNormalMode::commandSwitchToNextTab() {
  1308. QString command = "bn";
  1309. if ( m_iscounted )
  1310. command = command + " " + QString::number(getCount());
  1311. m_view->cmdLineBar()->execute(command);
  1312. return true;
  1313. }
  1314. bool KateViNormalMode::commandSwitchToPrevTab() {
  1315. QString command = "bp";
  1316. if ( m_iscounted )
  1317. command = command + " " + QString::number(getCount());
  1318. m_view->cmdLineBar()->execute(command);
  1319. return true;
  1320. }
  1321. bool KateViNormalMode::commandFormatLine()
  1322. {
  1323. Cursor c( m_view->cursorPosition() );
  1324. reformatLines( c.line(), c.line()+getCount()-1 );
  1325. return true;
  1326. }
  1327. bool KateViNormalMode::commandFormatLines()
  1328. {
  1329. reformatLines( m_commandRange.startLine, m_commandRange.endLine );
  1330. return true;
  1331. }
  1332. bool KateViNormalMode::commandCollapseToplevelNodes()
  1333. {
  1334. doc()->foldingTree()->collapseToplevelNodes();
  1335. return true;
  1336. }
  1337. bool KateViNormalMode::commandCollapseLocal()
  1338. {
  1339. Cursor c( m_view->cursorPosition() );
  1340. doc()->foldingTree()->collapseOne( c.line(), c.column() );
  1341. return true;
  1342. }
  1343. bool KateViNormalMode::commandExpandAll() {
  1344. doc()->foldingTree()->expandAll();
  1345. return true;
  1346. }
  1347. bool KateViNormalMode::commandExpandLocal()
  1348. {
  1349. Cursor c( m_view->cursorPosition() );
  1350. doc()->foldingTree()->expandOne( c.line() + 1, c.column() );
  1351. return true;
  1352. }
  1353. bool KateViNormalMode::commandToggleRegionVisibility()
  1354. {
  1355. Cursor c( m_view->cursorPosition() );
  1356. doc()->foldingTree()->toggleRegionVisibility( c.line() );
  1357. return true;
  1358. }
  1359. ////////////////////////////////////////////////////////////////////////////////
  1360. // MOTIONS
  1361. ////////////////////////////////////////////////////////////////////////////////
  1362. KateViRange KateViNormalMode::motionDown()
  1363. {
  1364. return goLineDown();
  1365. }
  1366. KateViRange KateViNormalMode::motionUp()
  1367. {
  1368. return goLineUp();
  1369. }
  1370. KateViRange KateViNormalMode::motionLeft()
  1371. {
  1372. Cursor cursor ( m_view->cursorPosition() );
  1373. m_stickyColumn = -1;
  1374. KateViRange r( cursor.line(), cursor.column(), ViMotion::ExclusiveMotion );
  1375. r.endColumn -= getCount();
  1376. if ( r.endColumn < 0 ) {
  1377. r.endColumn = 0;
  1378. }
  1379. return r;
  1380. }
  1381. KateViRange KateViNormalMode::motionRight()
  1382. {
  1383. Cursor cursor ( m_view->cursorPosition() );
  1384. m_stickyColumn = -1;
  1385. KateViRange r( cursor.line(), cursor.column(), ViMotion::ExclusiveMotion );
  1386. r.endColumn += getCount();
  1387. // make sure end position isn't > line length
  1388. if ( r.endColumn > doc()->lineLength( r.endLine ) ) {
  1389. r.endColumn = doc()->lineLength( r.endLine );
  1390. }
  1391. return r;
  1392. }
  1393. KateViRange KateViNormalMode::motionPageDown()
  1394. {
  1395. Cursor c( m_view->cursorPosition() );
  1396. int linesToScroll = linesDisplayed();
  1397. KateViRange r( c.line()+linesToScroll, c.column(), ViMotion::InclusiveMotion );
  1398. if ( r.endLine >= doc()->lines() ) {
  1399. r.endLine = doc()->lines()-1;
  1400. }
  1401. return r;
  1402. }
  1403. KateViRange KateViNormalMode::motionPageUp()
  1404. {
  1405. Cursor c( m_view->cursorPosition() );
  1406. int linesToScroll = linesDisplayed();
  1407. KateViRange r( c.line()-linesToScroll, c.column(), ViMotion::InclusiveMotion );
  1408. if ( r.endLine < 0 ) {
  1409. r.endLine = 0;
  1410. }
  1411. return r;
  1412. }
  1413. KateViRange KateViNormalMode::motionDownToFirstNonBlank()
  1414. {
  1415. Cursor c( m_view->cursorPosition() );
  1416. KateViRange r = goLineDown();
  1417. r.endColumn = getLine( r.endLine ).indexOf( QRegExp( "\\S" ) );
  1418. if ( r.endColumn < 0 ) {
  1419. r.endColumn = 0;
  1420. }
  1421. return r;
  1422. }
  1423. KateViRange KateViNormalMode::motionUpToFirstNonBlank()
  1424. {
  1425. Cursor c( m_view->cursorPosition() );
  1426. KateViRange r = goLineUp();
  1427. r.endColumn = getLine( r.endLine ).indexOf( QRegExp( "\\S" ) );
  1428. if ( r.endColumn < 0 ) {
  1429. r.endColumn = 0;
  1430. }
  1431. return r;
  1432. }
  1433. KateViRange KateViNormalMode::motionWordForward()
  1434. {
  1435. Cursor c( m_view->cursorPosition() );
  1436. KateViRange r( c.line(), c.column(), ViMotion::ExclusiveMotion );
  1437. m_stickyColumn = -1;
  1438. // Special case: If we're already on the very last character in the document, the motion should be
  1439. // inclusive so the last character gets included
  1440. if ( c.line() == doc()->lines()-1 && c.column() == doc()->lineLength( c.line() )-1 ) {
  1441. r.motionType = ViMotion::InclusiveMotion;
  1442. } else {
  1443. for ( unsigned int i = 0; i < getCount(); i++ ) {
  1444. c = findNextWordStart( c.line(), c.column() );
  1445. // stop when at the last char in the document
  1446. if ( c.line() == doc()->lines()-1 && c.column() == doc()->lineLength( c.line() )-1 ) {
  1447. // if we still haven't "used up the count", make the motion inclusive, so that the last char
  1448. // is included
  1449. if ( i < getCount() ) {
  1450. r.motionType = ViMotion::InclusiveMotion;
  1451. }

Large files files are truncated, but you can click here to view the full file