kio
kshellcompletion.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <stdlib.h>
00021 #include <kdebug.h>
00022 #include <qstring.h>
00023 #include <qstringlist.h>
00024 #include <qregexp.h>
00025 #include <kcompletion.h>
00026
00027 #include "kshellcompletion.h"
00028
00029 class KShellCompletionPrivate
00030 {
00031 };
00032
00033 KShellCompletion::KShellCompletion() : KURLCompletion()
00034 {
00035 m_word_break_char = ' ';
00036 m_quote_char1 = '\"';
00037 m_quote_char2 = '\'';
00038 m_escape_char = '\\';
00039 }
00040
00041
00042
00043
00044
00045
00046 QString KShellCompletion::makeCompletion(const QString &text)
00047 {
00048
00049
00050 splitText(text, m_text_start, m_text_compl);
00051
00052
00053
00054 QString tmp = unquote(m_text_compl);
00055 m_text_compl = tmp;
00056
00057
00058
00059 bool is_exe_completion = true;
00060
00061 for ( uint i = 0; i < m_text_start.length(); i++ ) {
00062 if ( m_text_start[i] != m_word_break_char ) {
00063 is_exe_completion = false;
00064 break;
00065 }
00066 }
00067
00068 Mode mode = (is_exe_completion ? ExeCompletion : FileCompletion );
00069
00070 setMode(mode);
00071
00072
00073
00074 return KURLCompletion::makeCompletion( m_text_compl );
00075 }
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 void KShellCompletion::postProcessMatch( QString *match ) const
00086 {
00087
00088
00089
00090 KURLCompletion::postProcessMatch( match );
00091
00092 if ( match->isNull() )
00093 return;
00094
00095 if ( match->right(1) == QChar('/') )
00096 quoteText( match, false, true );
00097 else
00098 quoteText( match, false, false );
00099
00100 match->prepend( m_text_start );
00101
00102
00103
00104 }
00105
00106 void KShellCompletion::postProcessMatches( QStringList *matches ) const
00107 {
00108 KURLCompletion::postProcessMatches( matches );
00109
00110 for ( QStringList::Iterator it = matches->begin();
00111 it != matches->end(); it++ )
00112 {
00113 if ( !(*it).isNull() ) {
00114 if ( (*it).right(1) == QChar('/') )
00115 quoteText( &(*it), false, true );
00116 else
00117 quoteText( &(*it), false, false );
00118
00119 (*it).prepend( m_text_start );
00120 }
00121 }
00122 }
00123
00124 void KShellCompletion::postProcessMatches( KCompletionMatches *matches ) const
00125 {
00126 KURLCompletion::postProcessMatches( matches );
00127
00128 for ( KCompletionMatches::Iterator it = matches->begin();
00129 it != matches->end(); it++ )
00130 {
00131 if ( !(*it).value().isNull() ) {
00132 if ( (*it).value().right(1) == QChar('/') )
00133 quoteText( &(*it).value(), false, true );
00134 else
00135 quoteText( &(*it).value(), false, false );
00136
00137 (*it).value().prepend( m_text_start );
00138 }
00139 }
00140 }
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 void KShellCompletion::splitText(const QString &text, QString &text_start,
00151 QString &text_compl) const
00152 {
00153 bool in_quote = false;
00154 bool escaped = false;
00155 QChar p_last_quote_char;
00156 int last_unquoted_space = -1;
00157 int end_space_len = 0;
00158
00159 for (uint pos = 0; pos < text.length(); pos++) {
00160
00161 end_space_len = 0;
00162
00163 if ( escaped ) {
00164 escaped = false;
00165 }
00166 else if ( in_quote && text[pos] == p_last_quote_char ) {
00167 in_quote = false;
00168 }
00169 else if ( !in_quote && text[pos] == m_quote_char1 ) {
00170 p_last_quote_char = m_quote_char1;
00171 in_quote = true;
00172 }
00173 else if ( !in_quote && text[pos] == m_quote_char2 ) {
00174 p_last_quote_char = m_quote_char2;
00175 in_quote = true;
00176 }
00177 else if ( text[pos] == m_escape_char ) {
00178 escaped = true;
00179 }
00180 else if ( !in_quote && text[pos] == m_word_break_char ) {
00181
00182 end_space_len = 1;
00183
00184 while ( pos+1 < text.length() && text[pos+1] == m_word_break_char ) {
00185 end_space_len++;
00186 pos++;
00187 }
00188
00189 if ( pos+1 == text.length() )
00190 break;
00191
00192 last_unquoted_space = pos;
00193 }
00194 }
00195
00196 text_start = text.left( last_unquoted_space + 1 );
00197
00198
00199 text_compl = text.mid( last_unquoted_space + 1 );
00200
00201
00202
00203
00204
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 bool KShellCompletion::quoteText(QString *text, bool force, bool skip_last) const
00216 {
00217 int pos = 0;
00218
00219 if ( !force ) {
00220 pos = text->find( m_word_break_char );
00221 if ( skip_last && (pos == (int)(text->length())-1) ) pos = -1;
00222 }
00223
00224 if ( !force && pos == -1 ) {
00225 pos = text->find( m_quote_char1 );
00226 if ( skip_last && (pos == (int)(text->length())-1) ) pos = -1;
00227 }
00228
00229 if ( !force && pos == -1 ) {
00230 pos = text->find( m_quote_char2 );
00231 if ( skip_last && (pos == (int)(text->length())-1) ) pos = -1;
00232 }
00233
00234 if ( !force && pos == -1 ) {
00235 pos = text->find( m_escape_char );
00236 if ( skip_last && (pos == (int)(text->length())-1) ) pos = -1;
00237 }
00238
00239 if ( force || (pos >= 0) ) {
00240
00241
00242 text->replace( m_escape_char,
00243 QString( m_escape_char ) + m_escape_char );
00244
00245
00246 text->replace( m_quote_char1,
00247 QString( m_escape_char ) + m_quote_char1 );
00248
00249
00250 text->insert( 0, m_quote_char1 );
00251
00252
00253 if ( skip_last )
00254 text->insert( text->length()-1, m_quote_char1 );
00255 else
00256 text->insert( text->length(), m_quote_char1 );
00257
00258 return true;
00259 }
00260
00261 return false;
00262 }
00263
00264
00265
00266
00267
00268
00269
00270 QString KShellCompletion::unquote(const QString &text) const
00271 {
00272 bool in_quote = false;
00273 bool escaped = false;
00274 QChar p_last_quote_char;
00275 QString result;
00276
00277 for (uint pos = 0; pos < text.length(); pos++) {
00278
00279 if ( escaped ) {
00280 escaped = false;
00281 result.insert( result.length(), text[pos] );
00282 }
00283 else if ( in_quote && text[pos] == p_last_quote_char ) {
00284 in_quote = false;
00285 }
00286 else if ( !in_quote && text[pos] == m_quote_char1 ) {
00287 p_last_quote_char = m_quote_char1;
00288 in_quote = true;
00289 }
00290 else if ( !in_quote && text[pos] == m_quote_char2 ) {
00291 p_last_quote_char = m_quote_char2;
00292 in_quote = true;
00293 }
00294 else if ( text[pos] == m_escape_char ) {
00295 escaped = true;
00296 result.insert( result.length(), text[pos] );
00297 }
00298 else {
00299 result.insert( result.length(), text[pos] );
00300 }
00301
00302 }
00303
00304 return result;
00305 }
00306
00307 void KShellCompletion::virtual_hook( int id, void* data )
00308 { KURLCompletion::virtual_hook( id, data ); }
00309
00310 #include "kshellcompletion.moc"
00311