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