Kate
katevivisualmode.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries and the Kate part. 00002 * 00003 * Copyright (C) 2008 Erlend Hamberg <ehamberg@gmail.com> 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Library General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Library General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Library General Public License 00016 * along with this library; see the file COPYING.LIB. If not, write to 00017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 * Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "katevivisualmode.h" 00022 #include "katevirange.h" 00023 00024 using KTextEditor::Cursor; 00025 using KTextEditor::Range; 00026 00027 #define ADDCMD(STR,FUNC, FLGS) m_commands.push_back( \ 00028 new KateViCommand( this, STR, &KateViNormalMode::FUNC, FLGS ) ); 00029 00030 #define ADDMOTION(STR, FUNC, FLGS) m_motions.push_back( new \ 00031 KateViMotion( this, STR, &KateViNormalMode::FUNC, FLGS ) ); 00032 00033 KateViVisualMode::KateViVisualMode( KateViInputModeManager* viInputModeManager, KateView *view, KateViewInternal *viewInternal ) 00034 : KateViNormalMode( viInputModeManager, view, viewInternal ) 00035 { 00036 m_start.setPosition( -1, -1 ); 00037 m_previous.setPosition( -1, -1 ); 00038 00039 m_mode = VisualMode; 00040 00041 initializeCommands(); 00042 } 00043 00044 KateViVisualMode::~KateViVisualMode() 00045 { 00046 } 00047 00048 void KateViVisualMode::updateDirty( bool entireView ) const 00049 { 00050 Cursor c = m_view->cursorPosition(); 00051 00052 if ( entireView ) { 00053 m_view->tagLines(0, m_view->doc()->lastLine() ); 00054 } else { 00055 // tag lines that might have changed their highlighting as dirty 00056 if ( c.line() >= m_start.line() ) { // selection in the "normal" direction 00057 if ( c.line() > m_previous.line() ) { 00058 m_view->tagLines(m_start.line(), c.line()); 00059 } else { 00060 m_view->tagLines(m_start.line(), m_previous.line()); 00061 } 00062 } else { // selection in the "opposite" direction, i.e., upward or to the left 00063 if ( c.line() < m_previous.line() ) { 00064 m_view->tagLines(c.line(), m_start.line()); 00065 } else { 00066 m_view->tagLines(m_previous.line(), m_start.line()); 00067 } 00068 } 00069 } 00070 m_view->updateView( true ); 00071 } 00072 00073 void KateViVisualMode::goToPos( const KateViRange &r ) 00074 { 00075 Cursor c = m_view->cursorPosition(); 00076 m_previous = c; 00077 00078 if ( r.startLine != -1 && r.startColumn != -1 && c == m_start ) { 00079 m_start.setLine( r.startLine ); 00080 m_start.setColumn( r.startColumn ); 00081 c.setLine( r.endLine ); 00082 c.setColumn( r.endColumn ); 00083 } else if ( r.startLine != -1 && r.startColumn != -1 && c < m_start ) { 00084 c.setLine( r.startLine ); 00085 c.setColumn( r.startColumn ); 00086 } else { 00087 c.setLine( r.endLine ); 00088 c.setColumn( r.endColumn ); 00089 } 00090 00091 if ( c.line() >= doc()->lines() ) { 00092 c.setLine( doc()->lines()-1 ); 00093 } 00094 00095 updateCursor( c ); 00096 00097 m_commandRange.startLine = m_start.line(); 00098 m_commandRange.startColumn = m_start.column(); 00099 m_commandRange.endLine = r.endLine; 00100 m_commandRange.endColumn = r.endColumn; 00101 00102 updateDirty(); 00103 } 00104 00105 void KateViVisualMode::reset() 00106 { 00107 m_awaitingMotionOrTextObject.push_back( 0 ); // search for text objects/motion from char 0 00108 00109 m_mode = VisualMode; 00110 00111 // only switch to normal mode if still in visual mode. commands like c, s, ... 00112 // can have switched to insert mode 00113 if ( m_viInputModeManager->getCurrentViMode() == VisualMode 00114 || m_viInputModeManager->getCurrentViMode() == VisualLineMode 00115 || m_viInputModeManager->getCurrentViMode() == VisualBlockMode ) { 00116 startNormalMode(); 00117 } 00118 00119 // TODO: set register < and > (see :help '< in vim) 00120 00121 m_start.setPosition( -1, -1 ); 00122 m_previous.setPosition( -1, -1 ); 00123 00124 // remove highlighting 00125 updateDirty( true ); 00126 } 00127 00128 void KateViVisualMode::init() 00129 { 00130 m_start = m_view->cursorPosition(); 00131 updateDirty(); 00132 00133 m_awaitingMotionOrTextObject.push_back( 0 ); // search for text objects/motion from char 0 00134 00135 m_commandRange.startLine = m_commandRange.endLine = m_start.line(); 00136 m_commandRange.startColumn = m_commandRange.endColumn = m_start.column(); 00137 } 00138 00139 void KateViVisualMode::setVisualLine( bool l ) 00140 { 00141 if ( l ) { 00142 m_mode = VisualLineMode; 00143 } else { 00144 m_mode = VisualMode; 00145 } 00146 updateDirty( true ); 00147 } 00148 00149 void KateViVisualMode::setVisualBlock( bool l ) 00150 { 00151 if ( l ) { 00152 m_mode = VisualBlockMode; 00153 } else { 00154 m_mode = VisualMode; 00155 } 00156 updateDirty( true ); 00157 } 00158 00159 void KateViVisualMode::setVisualModeType( ViMode mode ) 00160 { 00161 Q_ASSERT( mode == VisualMode || mode == VisualLineMode || mode == VisualBlockMode ); 00162 m_mode = mode; 00163 } 00164 00165 void KateViVisualMode::switchStartEnd() 00166 { 00167 Cursor c = m_start; 00168 m_start = m_view->cursorPosition(); 00169 00170 updateCursor( c ); 00171 00172 m_stickyColumn = -1; 00173 00174 updateDirty(); 00175 } 00176 00177 Range KateViVisualMode::getVisualRange() const 00178 { 00179 Cursor c = m_view->cursorPosition(); 00180 00181 int startLine = qMin( c.line(), m_start.line() ); 00182 int endLine = qMax( c.line(), m_start.line() ); 00183 int startCol; 00184 int endCol; 00185 00186 if ( m_mode == VisualBlockMode ) { 00187 startCol = qMin( c.column(), m_start.column() ); 00188 endCol = qMax( c.column(), m_start.column() ); 00189 } else if ( m_mode == VisualLineMode ) { 00190 startCol = 0; 00191 endCol = m_view->doc()->lineLength( endLine ); 00192 } else { 00193 if ( c.line() == endLine ) { 00194 startCol = m_start.column(); 00195 endCol = c.column(); 00196 } else { 00197 startCol = c.column(); 00198 endCol = m_start.column(); 00199 } 00200 } 00201 00202 return Range( startLine, startCol, endLine, endCol ); 00203 } 00204 00205 void KateViVisualMode::initializeCommands() 00206 { 00207 // Remove the commands put in here by KateViNormalMode 00208 qDeleteAll(m_commands); 00209 m_commands.clear(); 00210 00211 // Remove the motions put in here by KateViNormalMode 00212 qDeleteAll(m_motions); 00213 m_motions.clear(); 00214 00215 ADDCMD("J", commandJoinLines, IS_CHANGE ); 00216 ADDCMD("c", commandChange, IS_CHANGE ); 00217 ADDCMD("s", commandChange, IS_CHANGE ); 00218 ADDCMD("C", commandChangeToEOL, IS_CHANGE ); 00219 ADDCMD("d", commandDelete, IS_CHANGE ); 00220 ADDCMD("D", commandDeleteToEOL, IS_CHANGE ); 00221 ADDCMD("x", commandDeleteChar, IS_CHANGE ); 00222 ADDCMD("X", commandDeleteCharBackward, IS_CHANGE ); 00223 ADDCMD("gu", commandMakeLowercase, IS_CHANGE ); 00224 ADDCMD("u", commandMakeLowercase, IS_CHANGE ); 00225 ADDCMD("gU", commandMakeUppercase, IS_CHANGE ); 00226 ADDCMD("U", commandMakeUppercase, IS_CHANGE ); 00227 ADDCMD("y", commandYank, 0 ); 00228 ADDCMD("Y", commandYankToEOL, 0 ); 00229 ADDCMD("p", commandPaste, IS_CHANGE ); 00230 ADDCMD("P", commandPasteBefore, IS_CHANGE ); 00231 ADDCMD("r.", commandReplaceCharacter, IS_CHANGE | REGEX_PATTERN ); 00232 ADDCMD(":", commandSwitchToCmdLine, 0 ); 00233 ADDCMD("/", commandSearch, 0 ); 00234 ADDCMD("m.", commandSetMark, REGEX_PATTERN ); 00235 ADDCMD(">", commandIndentLines, 0 ); 00236 ADDCMD("<", commandUnindentLines, 0 ); 00237 ADDCMD("<c-c>", commandAbort, 0 ); 00238 ADDCMD("<c-[>", commandAbort, 0 ); 00239 ADDCMD("ga", commandPrintCharacterCode, SHOULD_NOT_RESET ); 00240 ADDCMD("v", commandEnterVisualMode, SHOULD_NOT_RESET ); 00241 ADDCMD("V", commandEnterVisualLineMode, SHOULD_NOT_RESET ); 00242 ADDCMD("o", commandToOtherEnd, SHOULD_NOT_RESET ); 00243 ADDCMD("=", commandAlignLines, SHOULD_NOT_RESET ); 00244 ADDCMD("~", commandChangeCase, IS_CHANGE ); 00245 00246 // regular motions 00247 ADDMOTION("h", motionLeft, 0 ); 00248 ADDMOTION("<left>", motionLeft, 0 ); 00249 ADDMOTION("<backspace>", motionLeft, 0 ); 00250 ADDMOTION("j", motionDown, 0 ); 00251 ADDMOTION("<down>", motionDown, 0 ); 00252 ADDMOTION("k", motionUp, 0 ); 00253 ADDMOTION("<up>", motionUp, 0 ); 00254 ADDMOTION("l", motionRight, 0 ); 00255 ADDMOTION("<right>", motionRight, 0 ); 00256 ADDMOTION(" ", motionRight, 0 ); 00257 ADDMOTION("$", motionToEOL, 0 ); 00258 ADDMOTION("<end>", motionToEOL, 0 ); 00259 ADDMOTION("0", motionToColumn0, 0 ); 00260 ADDMOTION("<home>", motionToColumn0, 0 ); 00261 ADDMOTION("^", motionToFirstCharacterOfLine, 0 ); 00262 ADDMOTION("f.", motionFindChar, REGEX_PATTERN ); 00263 ADDMOTION("F.", motionFindCharBackward, REGEX_PATTERN ); 00264 ADDMOTION("t.", motionToChar, REGEX_PATTERN ); 00265 ADDMOTION("T.", motionToCharBackward, REGEX_PATTERN ); 00266 ADDMOTION(";", motionRepeatlastTF, 0 ); 00267 ADDMOTION(",", motionRepeatlastTFBackward, 0 ); 00268 ADDMOTION("n", motionFindNext, 0 ); 00269 ADDMOTION("N", motionFindPrev, 0 ); 00270 ADDMOTION("gg", motionToLineFirst, 0 ); 00271 ADDMOTION("G", motionToLineLast, 0 ); 00272 ADDMOTION("w", motionWordForward, 0 ); 00273 ADDMOTION("W", motionWORDForward, 0 ); 00274 ADDMOTION("b", motionWordBackward, 0 ); 00275 ADDMOTION("B", motionWORDBackward, 0 ); 00276 ADDMOTION("e", motionToEndOfWord, 0 ); 00277 ADDMOTION("E", motionToEndOfWORD, 0 ); 00278 ADDMOTION("ge", motionToEndOfPrevWord, 0 ); 00279 ADDMOTION("gE", motionToEndOfPrevWORD, 0 ); 00280 ADDMOTION("|", motionToScreenColumn, 0 ); 00281 ADDMOTION("%", motionToMatchingItem, 0 ); 00282 ADDMOTION("`.", motionToMark, REGEX_PATTERN ); 00283 ADDMOTION("'.", motionToMarkLine, REGEX_PATTERN ); 00284 ADDMOTION("[[", motionToPreviousBraceBlockStart, 0 ); 00285 ADDMOTION("]]", motionToNextBraceBlockStart, 0 ); 00286 ADDMOTION("[]", motionToPreviousBraceBlockEnd, 0 ); 00287 ADDMOTION("][", motionToNextBraceBlockEnd, 0 ); 00288 ADDMOTION("<c-f>", motionPageDown, 0 ); 00289 ADDMOTION("<pagedown>", motionPageDown, 0 ); 00290 ADDMOTION("<c-b>", motionPageUp, 0 ); 00291 ADDMOTION("<pageup>", motionPageUp, 0 ); 00292 00293 // text objects 00294 ADDMOTION("iw", textObjectInnerWord, 0 ); 00295 ADDMOTION("aw", textObjectAWord, 0 ); 00296 ADDMOTION("i\"", textObjectInnerQuoteDouble, 0 ); 00297 ADDMOTION("a\"", textObjectAQuoteDouble, 0 ); 00298 ADDMOTION("i'", textObjectInnerQuoteSingle, 0 ); 00299 ADDMOTION("a'", textObjectAQuoteSingle, 0 ); 00300 ADDMOTION("i[()]", textObjectInnerParen, REGEX_PATTERN ); 00301 ADDMOTION("a[()]", textObjectAParen, REGEX_PATTERN ); 00302 ADDMOTION("i[\\[\\]]", textObjectInnerBracket, REGEX_PATTERN ); 00303 ADDMOTION("a[\\[\\]]", textObjectABracket, REGEX_PATTERN ); 00304 ADDMOTION("i,", textObjectInnerComma, 0 ); 00305 ADDMOTION("a,", textObjectAComma, 0 ); 00306 }
KDE 4.6 API Reference