• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kate
 

kate

  • kate
  • plugins
  • wordcompletion
docwordcompletion.cpp
1/*
2 This library is free software; you can redistribute it and/or
3 modify it under the terms of the GNU Library General Public
4 License version 2 as published by the Free Software Foundation.
5
6 This library is distributed in the hope that it will be useful,
7 but WITHOUT ANY WARRANTY; without even the implied warranty of
8 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 Library General Public License for more details.
10
11 You should have received a copy of the GNU Library General Public License
12 along with this library; see the file COPYING.LIB. If not, write to
13 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
14 Boston, MA 02110-1301, USA.
15
16 ---
17 file: docwordcompletion.cpp
18
19 KTextEditor plugin to autocompletion with document words.
20 Copyright Anders Lund <anders.lund@lund.tdcadsl.dk>, 2003
21
22 The following completion methods are supported:
23 * Completion with bigger matching words in
24 either direction (backward/forward).
25 * NOT YET Pop up a list of all bigger matching words in document
26
27*/
28//BEGIN includes
29#include "docwordcompletion.h"
30
31#include <tdetexteditor/document.h>
32#include <tdetexteditor/viewcursorinterface.h>
33#include <tdetexteditor/editinterface.h>
34#include <tdetexteditor/variableinterface.h>
35
36#include <tdeapplication.h>
37#include <tdeconfig.h>
38#include <kdialog.h>
39#include <kgenericfactory.h>
40#include <tdelocale.h>
41#include <tdeaction.h>
42#include <knotifyclient.h>
43#include <tdeparts/part.h>
44#include <kiconloader.h>
45
46#include <tqregexp.h>
47#include <tqstring.h>
48#include <tqdict.h>
49#include <tqspinbox.h>
50#include <tqlabel.h>
51#include <tqlayout.h>
52#include <tqhbox.h>
53#include <tqwhatsthis.h>
54#include <tqcheckbox.h>
55
56// #include <kdebug.h>
57//END
58
59//BEGIN DocWordCompletionPlugin
60K_EXPORT_COMPONENT_FACTORY( tdetexteditor_docwordcompletion, KGenericFactory<DocWordCompletionPlugin>( "tdetexteditor_docwordcompletion" ) )
61DocWordCompletionPlugin::DocWordCompletionPlugin( TQObject *parent,
62 const char* name,
63 const TQStringList& /*args*/ )
64 : KTextEditor::Plugin ( (KTextEditor::Document*) parent, name )
65{
66 readConfig();
67}
68
69void DocWordCompletionPlugin::readConfig()
70{
71 TDEConfig *config = tdeApp->config();
72 config->setGroup( "DocWordCompletion Plugin" );
73 m_treshold = config->readNumEntry( "treshold", 3 );
74 m_autopopup = config->readBoolEntry( "autopopup", true );
75}
76
77void DocWordCompletionPlugin::writeConfig()
78{
79 TDEConfig *config = tdeApp->config();
80 config->setGroup("DocWordCompletion Plugin");
81 config->writeEntry("autopopup", m_autopopup );
82 config->writeEntry("treshold", m_treshold );
83}
84
85void DocWordCompletionPlugin::addView(KTextEditor::View *view)
86{
87 DocWordCompletionPluginView *nview = new DocWordCompletionPluginView (m_treshold, m_autopopup, view, "Document word completion");
88 m_views.append (nview);
89}
90
91void DocWordCompletionPlugin::removeView(KTextEditor::View *view)
92{
93 for (uint z=0; z < m_views.count(); z++)
94 if (m_views.at(z)->parentClient() == view)
95 {
96 DocWordCompletionPluginView *nview = m_views.at(z);
97 m_views.remove (nview);
98 delete nview;
99 }
100}
101
102KTextEditor::ConfigPage* DocWordCompletionPlugin::configPage( uint, TQWidget *parent, const char *name )
103{
104 return new DocWordCompletionConfigPage( this, parent, name );
105}
106
107TQString DocWordCompletionPlugin::configPageName( uint ) const
108{
109 return i18n("Word Completion Plugin");
110}
111
112TQString DocWordCompletionPlugin::configPageFullName( uint ) const
113{
114 return i18n("Configure the Word Completion Plugin");
115}
116
117// FIXME provide sucn a icon
118 TQPixmap DocWordCompletionPlugin::configPagePixmap( uint, int size ) const
119{
120 return UserIcon( "kte_wordcompletion", size );
121}
122//END
123
124//BEGIN DocWordCompletionPluginView
125struct DocWordCompletionPluginViewPrivate
126{
127 uint line, col; // start position of last match (where to search from)
128 uint cline, ccol; // cursor position
129 uint lilen; // length of last insertion
130 TQString last; // last word we were trying to match
131 TQString lastIns; // latest applied completion
132 TQRegExp re; // hrm
133 TDEToggleAction *autopopup; // for accessing state
134 uint treshold; // the required length of a word before popping up the completion list automatically
135 int directionalPos; // be able to insert "" at the correct time
136};
137
138DocWordCompletionPluginView::DocWordCompletionPluginView( uint treshold, bool autopopup, KTextEditor::View *view, const char *name )
139 : TQObject( view, name ),
140 KXMLGUIClient( view ),
141 m_view( view ),
142 d( new DocWordCompletionPluginViewPrivate )
143{
144 d->treshold = treshold;
145 view->insertChildClient( this );
146 setInstance( KGenericFactory<DocWordCompletionPlugin>::instance() );
147
148 (void) new TDEAction( i18n("Reuse Word Above"), CTRL+Key_8, this,
149 TQ_SLOT(completeBackwards()), actionCollection(), "doccomplete_bw" );
150 (void) new TDEAction( i18n("Reuse Word Below"), CTRL+Key_9, this,
151 TQ_SLOT(completeForwards()), actionCollection(), "doccomplete_fw" );
152 (void) new TDEAction( i18n("Pop Up Completion List"), 0, this,
153 TQ_SLOT(popupCompletionList()), actionCollection(), "doccomplete_pu" );
154 (void) new TDEAction( i18n("Shell Completion"), 0, this,
155 TQ_SLOT(shellComplete()), actionCollection(), "doccomplete_sh" );
156 d->autopopup = new TDEToggleAction( i18n("Automatic Completion Popup"), 0, this,
157 TQ_SLOT(toggleAutoPopup()), actionCollection(), "enable_autopopup" );
158
159 d->autopopup->setChecked( autopopup );
160 toggleAutoPopup();
161
162 setXMLFile("docwordcompletionui.rc");
163
164 KTextEditor::VariableInterface *vi = KTextEditor::variableInterface( view->document() );
165 if ( vi )
166 {
167 TQString e = vi->variable("wordcompletion-autopopup");
168 if ( ! e.isEmpty() )
169 d->autopopup->setEnabled( e == "true" );
170
171 connect( view->document(), TQ_SIGNAL(variableChanged(const TQString &, const TQString &)),
172 this, TQ_SLOT(slotVariableChanged(const TQString &, const TQString &)) );
173 }
174}
175
176void DocWordCompletionPluginView::settreshold( uint t )
177{
178 d->treshold = t;
179}
180
181void DocWordCompletionPluginView::completeBackwards()
182{
183 complete( false );
184}
185
186void DocWordCompletionPluginView::completeForwards()
187{
188 complete();
189}
190
191// Pop up the editors completion list if applicable
192void DocWordCompletionPluginView::popupCompletionList( TQString w )
193{
194 if ( w.isEmpty() )
195 w = word();
196 if ( w.isEmpty() )
197 return;
198
199 KTextEditor::CodeCompletionInterface *cci = codeCompletionInterface( m_view );
200 cci->showCompletionBox( allMatches( w ), w.length() );
201}
202
203void DocWordCompletionPluginView::toggleAutoPopup()
204{
205 if ( d->autopopup->isChecked() ) {
206 if ( ! connect( m_view->document(), TQ_SIGNAL(charactersInteractivelyInserted(int ,int ,const TQString&)),
207 this, TQ_SLOT(autoPopupCompletionList()) ))
208 {
209 connect( m_view->document(), TQ_SIGNAL(textChanged()), this, TQ_SLOT(autoPopupCompletionList()) );
210 }
211 } else {
212 disconnect( m_view->document(), TQ_SIGNAL(textChanged()), this, TQ_SLOT(autoPopupCompletionList()) );
213 disconnect( m_view->document(), TQ_SIGNAL(charactersInteractivelyInserted(int ,int ,const TQString&)),
214 this, TQ_SLOT(autoPopupCompletionList()) );
215
216 }
217}
218
219// for autopopup FIXME - don't pop up if reuse word is inserting
220void DocWordCompletionPluginView::autoPopupCompletionList()
221{
222 if ( ! m_view->hasFocus() ) return;
223 TQString w = word();
224 if ( w.length() >= d->treshold )
225 {
226 popupCompletionList( w );
227 }
228}
229
230// Contributed by <brain@hdsnet.hu>
231void DocWordCompletionPluginView::shellComplete()
232{
233 // setup
234 KTextEditor::EditInterface * ei = KTextEditor::editInterface(m_view->document());
235 // find the word we are typing
236 uint cline, ccol;
237 viewCursorInterface(m_view)->cursorPositionReal(&cline, &ccol);
238 TQString wrd = word();
239 if (wrd.isEmpty())
240 return;
241
242 TQValueList < KTextEditor::CompletionEntry > matches = allMatches(wrd);
243 if (matches.size() == 0)
244 return;
245 TQString partial = findLongestUnique(matches);
246 if (partial.length() == wrd.length())
247 {
248 KTextEditor::CodeCompletionInterface * cci = codeCompletionInterface(m_view);
249 cci->showCompletionBox(matches, wrd.length());
250 }
251 else
252 {
253 partial.remove(0, wrd.length());
254 ei->insertText(cline, ccol, partial);
255 }
256}
257
258// Do one completion, searching in the desired direction,
259// if possible
260void DocWordCompletionPluginView::complete( bool fw )
261{
262 // setup
263 KTextEditor::EditInterface *ei = KTextEditor::editInterface( m_view->document() );
264 // find the word we are typing
265 uint cline, ccol;
266 viewCursorInterface( m_view )->cursorPositionReal( &cline, &ccol );
267 TQString wrd = word();
268 if ( wrd.isEmpty() )
269 return;
270
271 int inc = fw ? 1 : -1;
272
273 /* IF the current line is equal to the previous line
274 AND the position - the length of the last inserted string
275 is equal to the old position
276 AND the lastinsertedlength last characters of the word is
277 equal to the last inserted string
278 */
279 if ( cline == d-> cline &&
280 ccol - d->lilen == d->ccol &&
281 wrd.endsWith( d->lastIns ) )
282 {
283 // this is a repeted activation
284
285 // if we are back to where we started, reset.
286 if ( ( fw && d->directionalPos == -1 ) ||
287 ( !fw && d->directionalPos == 1 ) )
288 {
289 if ( d->lilen )
290 ei->removeText( d->cline, d->ccol, d->cline, d->ccol + d->lilen );
291
292 d->lastIns = "";
293 d->lilen = 0;
294 d->line = d->cline;
295 d->col = d->ccol;
296 d->directionalPos = 0;
297
298 return;
299 }
300
301 if ( fw )
302 d->col += d->lilen;
303
304 ccol = d->ccol;
305 wrd = d->last;
306
307 d->directionalPos += inc;
308 }
309 else
310 {
311 d->cline = cline;
312 d->ccol = ccol;
313 d->last = wrd;
314 d->lastIns = "";
315 d->line = cline;
316 d->col = ccol - wrd.length();
317 d->lilen = 0;
318 d->directionalPos = inc;
319 }
320
321 d->re.setPattern( "\\b" + wrd + "(\\w+)" );
322 int pos ( 0 );
323 TQString ln = ei->textLine( d->line );
324
325 while ( true )
326 {
327 pos = fw ?
328 d->re.search( ln, d->col ) :
329 d->re.searchRev( ln, d->col );
330
331 if ( pos > -1 ) // we matched a word
332 {
333 TQString m = d->re.cap( 1 );
334 if ( m != d->lastIns )
335 {
336 // we got good a match! replace text and return.
337 if ( d->lilen )
338 ei->removeText( d->cline, d->ccol, d->cline, d->ccol + d->lilen );
339 ei->insertText( d->cline, d->ccol, m );
340
341 d->lastIns = m;
342 d->lilen = m.length();
343 d->col = pos; // for next try
344
345 return;
346 }
347
348 // equal to last one, continue
349 else
350 {
351 d->col = pos; // for next try
352
353 if ( fw )
354 d->col += d->re.matchedLength();
355
356 else
357 {
358 if ( pos == 0 )
359 {
360 if ( d->line > 0 )
361 {
362 d->line += inc;
363 ln = ei->textLine( d->line );
364 d->col = ln.length();
365 }
366 else
367 {
368 KNotifyClient::beep();
369 return;
370 }
371 }
372
373 else
374 d->col--;
375 }
376 }
377 }
378
379 else // no match
380 {
381 if ( (! fw && d->line == 0 ) || ( fw && d->line >= (uint)ei->numLines() ) )
382 {
383 KNotifyClient::beep();
384 return;
385 }
386
387 d->line += inc;
388
389 ln = ei->textLine( d->line );
390 d->col = fw ? 0 : ln.length();
391 }
392 } // while true
393}
394
395// Contributed by <brain@hdsnet.hu>
396TQString DocWordCompletionPluginView::findLongestUnique(const TQValueList < KTextEditor::CompletionEntry > &matches)
397{
398 TQString partial = matches.front().text;
399 TQValueList < KTextEditor::CompletionEntry >::const_iterator i = matches.begin();
400 for (++i; i != matches.end(); ++i)
401 {
402 if (!(*i).text.startsWith(partial))
403 {
404 while(partial.length() > 0)
405 {
406 partial.remove(partial.length() - 1, 1);
407 if ((*i).text.startsWith(partial))
408 {
409 break;
410 }
411 }
412 if (partial.length() == 0)
413 return TQString();
414 }
415 }
416
417 return partial;
418}
419
420// Return the string to complete (the letters behind the cursor)
421TQString DocWordCompletionPluginView::word()
422{
423 uint cline, ccol;
424 viewCursorInterface( m_view )->cursorPositionReal( &cline, &ccol );
425 if ( ! ccol ) return TQString::null; // no word
426 KTextEditor::EditInterface *ei = KTextEditor::editInterface( m_view->document() );
427 d->re.setPattern( "\\b(\\w+)$" );
428 if ( d->re.searchRev(
429 ei->text( cline, 0, cline, ccol )
430 ) < 0 )
431 return TQString::null; // no word
432 return d->re.cap( 1 );
433}
434
435// Scan throught the entire document for possible completions,
436// ignoring any dublets
437TQValueList<KTextEditor::CompletionEntry> DocWordCompletionPluginView::allMatches( const TQString &word )
438{
439 TQValueList<KTextEditor::CompletionEntry> l;
440 uint i( 0 );
441 int pos( 0 );
442 d->re.setPattern( "\\b("+word+"\\w+)" );
443 TQString s, m;
444 KTextEditor::EditInterface *ei = KTextEditor::editInterface( m_view->document() );
445 TQDict<int> seen; // maybe slow with > 17 matches
446 int sawit(1); // to ref for the dict
447 uint cline, ccol;// needed to avoid constructing a word at cursor position
448 viewCursorInterface( m_view )->cursorPositionReal( &cline, &ccol );
449
450 while( i < ei->numLines() )
451 {
452 s = ei->textLine( i );
453 pos = 0;
454 while ( pos >= 0 )
455 {
456 pos = d->re.search( s, pos );
457 if ( pos >= 0 )
458 {
459 // do not construct a new word!
460 if ( i == cline && pos + word.length() == ccol )
461 {
462 pos += word.length();
463 continue;
464 }
465
466 m = d->re.cap( 1 );
467 if ( ! seen[ m ] ) {
468 seen.insert( m, &sawit );
469 KTextEditor::CompletionEntry e;
470 e.text = m;
471 l.append( e );
472 }
473 pos += d->re.matchedLength();
474 }
475 }
476 i++;
477 }
478 return l;
479}
480
481void DocWordCompletionPluginView::slotVariableChanged( const TQString &var, const TQString &val )
482{
483 if ( var == "wordcompletion-autopopup" )
484 d->autopopup->setEnabled( val == "true" );
485 else if ( var == "wordcompletion-treshold" )
486 d->treshold = val.toInt();
487}
488//END
489
490//BEGIN DocWordCompletionConfigPage
491DocWordCompletionConfigPage::DocWordCompletionConfigPage( DocWordCompletionPlugin *completion, TQWidget *parent, const char *name )
492 : KTextEditor::ConfigPage( parent, name )
493 , m_completion( completion )
494{
495 TQVBoxLayout *lo = new TQVBoxLayout( this );
496 lo->setSpacing( KDialog::spacingHint() );
497
498 cbAutoPopup = new TQCheckBox( i18n("Automatically &show completion list"), this );
499 lo->addWidget( cbAutoPopup );
500
501 TQHBox *hb = new TQHBox( this );
502 hb->setSpacing( KDialog::spacingHint() );
503 lo->addWidget( hb );
504 TQLabel *l = new TQLabel( i18n(
505 "Translators: This is the first part of two strings wich will comprise the "
506 "sentence 'Show completions when a word is at least N characters'. The first "
507 "part is on the right side of the N, which is represented by a spinbox "
508 "widget, followed by the second part: 'characters long'. Characters is a "
509 "ingeger number between and including 1 and 30. Feel free to leave the "
510 "second part of the sentence blank if it suits your language better. ",
511 "Show completions &when a word is at least"), hb );
512 sbAutoPopup = new TQSpinBox( 1, 30, 1, hb );
513 l->setBuddy( sbAutoPopup );
514 lSbRight = new TQLabel( i18n(
515 "This is the second part of two strings that will comprise teh sentence "
516 "'Show completions when a word is at least N characters'",
517 "characters long."), hb );
518
519 TQWhatsThis::add( cbAutoPopup, i18n(
520 "Enable the automatic completion list popup as default. The popup can "
521 "be disabled on a view basis from the 'Tools' menu.") );
522 TQWhatsThis::add( sbAutoPopup, i18n(
523 "Define the length a word should have before the completion list "
524 "is displayed.") );
525
526 cbAutoPopup->setChecked( m_completion->autoPopupEnabled() );
527 sbAutoPopup->setValue( m_completion->treshold() );
528
529 lo->addStretch();
530}
531
532void DocWordCompletionConfigPage::apply()
533{
534 m_completion->setAutoPopupEnabled( cbAutoPopup->isChecked() );
535 m_completion->setTreshold( sbAutoPopup->value() );
536 m_completion->writeConfig();
537}
538
539void DocWordCompletionConfigPage::reset()
540{
541 cbAutoPopup->setChecked( m_completion->autoPopupEnabled() );
542 sbAutoPopup->setValue( m_completion->treshold() );
543}
544
545void DocWordCompletionConfigPage::defaults()
546{
547 cbAutoPopup->setChecked( true );
548 sbAutoPopup->setValue( 3 );
549}
550
551//END DocWordCompletionConfigPage
552
553#include "docwordcompletion.moc"
KDialog::spacingHint
static int spacingHint()
KGenericFactory
KXMLGUIClient
TDEAction
TDEConfigBase::readNumEntry
int readNumEntry(const TQString &pKey, int nDefault=0) const
TDEConfigBase::readBoolEntry
bool readBoolEntry(const TQString &pKey, bool bDefault=false) const
TDEConfigBase::writeEntry
void writeEntry(const TQString &pKey, const TQString &pValue, bool bPersistent=true, bool bGlobal=false, bool bNLS=false)
TDEConfigBase::setGroup
void setGroup(const TQString &group)
TDEConfig
TDEToggleAction
KNotifyClient::beep
void beep(const TQString &reason=TQString::null)
TDEStdAccel::name
TQString name(StdAccel id)
TDEStdAccel::completion
const TDEShortcut & completion()
tdelocale.h

kate

Skip menu "kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kate

Skip menu "kate"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kate by doxygen 1.9.4
This website is maintained by Timothy Pearson.