kshellcompletion.cpp
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 
 
This file is part of the documentation for kio Library Version 3.2.0.