⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 codecompletion.cpp

📁 非常好用的可移植的多平台C/C++源代码编辑器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
* This file is part of Code::Blocks Studio, an open-source cross-platform IDE
* Copyright (C) 2003  Yiannis An. Mandravellos
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* Contact e-mail: Yiannis An. Mandravellos <mandrav@codeblocks.org>
* Program URL   : http://www.codeblocks.org
*
* $Id: codecompletion.cpp,v 1.20.2.1 2005/10/25 07:59:01 mandrav Exp $
* $Date: 2005/10/25 07:59:01 $
*/

#include <sdk.h>
#include "codecompletion.h"
#include <wx/mimetype.h>
#include <wx/filename.h>
#include <wx/regex.h>
#include <wx/xrc/xmlres.h>
#include <wx/fs_zip.h>
#include <wx/msgdlg.h>
#include <manager.h>
#include <configmanager.h>
#include <messagemanager.h>
#include <projectmanager.h>
#include <editormanager.h>
#include <sdk_events.h>
#include <incrementalselectlistdlg.h>
#include "insertclassmethoddlg.h"
#include "ccoptionsdlg.h"
#include "parser/parser.h"
#include "cclist.h"

CB_IMPLEMENT_PLUGIN(CodeCompletion);

// menu IDS
// just because we don't know other plugins' used identifiers,
// we use wxNewId() to generate a guaranteed unique ID ;), instead of enum
// (don't forget that, especially in a plugin)
int idMenuCodeComplete = wxNewId();
int idMenuShowCallTip = wxNewId();
int idMenuGotoFunction = wxNewId();
int idEditorSubMenu = wxNewId();
int idClassMethod = wxNewId();
int idGotoDeclaration = wxNewId();
int idOpenIncludeFile = wxNewId();

BEGIN_EVENT_TABLE(CodeCompletion, cbCodeCompletionPlugin)
	EVT_UPDATE_UI_RANGE(idMenuCodeComplete, idMenuGotoFunction, CodeCompletion::OnUpdateUI)

	EVT_MENU(idMenuCodeComplete, CodeCompletion::OnCodeComplete)
	EVT_MENU(idMenuShowCallTip, CodeCompletion::OnShowCallTip)
	EVT_MENU(idMenuGotoFunction, CodeCompletion::OnGotoFunction)
	EVT_MENU(idClassMethod, CodeCompletion::OnClassMethod)
	EVT_MENU(idGotoDeclaration, CodeCompletion::OnGotoDeclaration)
	EVT_MENU(idOpenIncludeFile, CodeCompletion::OnOpenIncludeFile)

	EVT_EDITOR_AUTOCOMPLETE(CodeCompletion::OnCodeComplete)
	EVT_EDITOR_CALLTIP(CodeCompletion::OnShowCallTip)
	EVT_EDITOR_USERLIST_SELECTION(CodeCompletion::OnUserListSelection)
	EVT_EDITOR_SAVE(CodeCompletion::OnReparseActiveEditor)

	EVT_PROJECT_OPEN(CodeCompletion::OnProjectOpened)
	EVT_PROJECT_ACTIVATE(CodeCompletion::OnProjectActivated)
	EVT_PROJECT_CLOSE(CodeCompletion::OnProjectClosed)
	EVT_PROJECT_FILE_ADDED(CodeCompletion::OnProjectFileAdded)
	EVT_PROJECT_FILE_REMOVED(CodeCompletion::OnProjectFileRemoved)

	EVT_CCLIST_CODECOMPLETE(CodeCompletion::OnCodeComplete)
END_EVENT_TABLE()

CodeCompletion::CodeCompletion()
{
    wxFileSystem::AddHandler(new wxZipFSHandler);
    wxXmlResource::Get()->InitAllHandlers();
    wxString resPath = ConfigManager::Get()->Read(_T("data_path"), wxEmptyString);
    wxXmlResource::Get()->Load(resPath + _T("/code_completion.zip#zip:*.xrc"));

    m_PluginInfo.name = _T("CodeCompletion");
    m_PluginInfo.title = _("Code completion");
    m_PluginInfo.version = _T("0.1");
    m_PluginInfo.description = _("This plugin provides a class browser for your projects "
                               "and code-completion inside the editor\n\n"
                               "Note: Only C/C++ language is supported by this plugin...");
    m_PluginInfo.author = _T("Yiannis An. Mandravellos");
    m_PluginInfo.authorEmail = _T("info@codeblocks.org");
    m_PluginInfo.authorWebsite = _T("www.codeblocks.org");
    m_PluginInfo.thanksTo = _T("");
	m_PluginInfo.hasConfigure = true;

    m_PageIndex = -1;
    m_EditMenu = 0L;
	m_SearchMenu = 0L;

	ConfigManager::AddConfiguration(m_PluginInfo.title, _T("/code_completion"));
}

CodeCompletion::~CodeCompletion()
{
}

int CodeCompletion::Configure()
{
	CCOptionsDlg dlg(Manager::Get()->GetAppWindow());
	if (dlg.ShowModal() == wxID_OK)
	{
		m_NativeParsers.RereadParserOptions();
	}
	return 0;
}

void CodeCompletion::BuildMenu(wxMenuBar* menuBar)
{
    // if not attached, exit
    if (!m_IsAttached)
        return;

//	if (m_EditMenu)
//    	return; // already set-up

    int pos = menuBar->FindMenu(_("&Edit"));
    if (pos != wxNOT_FOUND)
    {
		m_EditMenu = menuBar->GetMenu(pos);
        m_EditMenu->AppendSeparator();
        m_EditMenu->Append(idMenuCodeComplete, _("Complete code\tCtrl-Space"));
        m_EditMenu->Append(idMenuShowCallTip, _("Show call tip\tCtrl-Shift-Space"));
    }
    else
    	Manager::Get()->GetMessageManager()->DebugLog(_("Could not find Edit menu!"));
    pos = menuBar->FindMenu(_("Sea&rch"));
    if (pos != wxNOT_FOUND)
    {
		m_SearchMenu = menuBar->GetMenu(pos);
        m_SearchMenu->Append(idMenuGotoFunction, _("Goto function...\tCtrl-Alt-G"));
    }
    else
    	Manager::Get()->GetMessageManager()->DebugLog(_("Could not find Search menu!"));
}

void CodeCompletion::BuildModuleMenu(const ModuleType type, wxMenu* menu, const wxString& arg)
{
    // if not attached, exit
	if (!menu || !m_IsAttached)
		return;

	if (type == mtEditorManager)
	{
	    cbStyledTextCtrl* control = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor()->GetControl();
	    if (control)
	    {
            int pos = control->GetCurrentPos();
            wxString line = control->GetLine(control->LineFromPosition(pos));

            wxRegEx reg(_T("^[ \t]*#[ \t]*include[ \t]+[\"<]([^\">]+)[\">]"));
            wxString inc;
            if (reg.Matches(line))
                inc = reg.GetMatch(line, 1);
            m_LastIncludeFile.Clear();
	        if (!inc.IsEmpty())
	        {
                wxString msg;
                msg.Printf(_("Open #include file: '%s'"), inc.c_str());
                menu->Insert(0, idOpenIncludeFile, msg);
                menu->Insert(1, wxID_SEPARATOR, wxEmptyString);
                m_LastIncludeFile = inc;
	        }
	        else // either #include or keyword-search
	        {
                int ws = control->WordStartPosition(pos, true);
                int we = control->WordEndPosition(pos, true);
                wxString txt = control->GetTextRange(ws, we);
                m_LastKeyword.Clear();
                if (!txt.IsEmpty())
                {
                    wxString msg;
                    msg.Printf(_("Find declaration of: '%s'"), txt.c_str());
                    menu->Insert(0, idGotoDeclaration, msg);
                    menu->Insert(1, wxID_SEPARATOR, wxEmptyString);
                    m_LastKeyword = txt;
                }
	        }
	    }
        int insertId = menu->FindItem(_("Insert..."));
        if (insertId != wxNOT_FOUND)
        {
            wxMenuItem* insertMenu = menu->FindItem(insertId, NULL);
            if (insertMenu)
            {
                wxMenu* subMenu = insertMenu->GetSubMenu();
                if (subMenu)
                {
                    subMenu->Append(idClassMethod, _("Class method declaration/implementation..."));
                }
                else
                    Manager::Get()->GetMessageManager()->DebugLog(_("Could not find Insert menu 3!"));
            }
            else
                Manager::Get()->GetMessageManager()->DebugLog(_("Could not find Insert menu 2!"));
        }
        else
            Manager::Get()->GetMessageManager()->DebugLog(_("Could not find Insert menu!"));
	}
}

bool CodeCompletion::BuildToolBar(wxToolBar* toolBar)
{
	// no need for toolbar items
	return false;
}

void CodeCompletion::OnAttach()
{
	m_NativeParsers.CreateClassBrowser();

	// parse all active projects
	ProjectManager* prjMan = Manager::Get()->GetProjectManager();
	for (unsigned int i = 0; i < prjMan->GetProjects()->GetCount(); ++i)
		m_NativeParsers.AddParser(prjMan->GetProjects()->Item(i));
}

void CodeCompletion::OnRelease(bool appShutDown)
{
	m_NativeParsers.RemoveClassBrowser(appShutDown);
	m_NativeParsers.ClearParsers();
	CCList::Free();

/* TODO (mandrav#1#): Delete separator line too... */
	if (m_EditMenu)
	{
		m_EditMenu->Delete(idMenuCodeComplete);
		m_EditMenu->Delete(idMenuShowCallTip);
	}
	if (m_SearchMenu)
		m_SearchMenu->Delete(idMenuGotoFunction);
}

int CodeCompletion::CodeComplete()
{
	if (!m_IsAttached)
		return -1;

	EditorManager* edMan = Manager::Get()->GetEditorManager();
    if (!edMan)
		return -2;
    cbEditor* ed = edMan->GetBuiltinActiveEditor();
    if (!ed)
		return -3;

	FileType ft = FileTypeOf(ed->GetShortName());
	if ( ft != ftHeader && ft != ftSource) // only parse source/header files
		return -4;

	Parser* parser = m_NativeParsers.FindParserFromActiveEditor();
	if (!parser)
	{
		Manager::Get()->GetMessageManager()->DebugLog(_("Active editor has no associated parser ?!?"));
		return -4;
	}

    if (m_NativeParsers.MarkItemsByAI(parser->Options().useSmartSense))
    {
        CCList::Free(); // free any previously open cc list
        CCList::Get(this, ed->GetControl(), parser)->Show();
        return 0;
    }
	return -5;
}

void CodeCompletion::CodeCompleteIncludes()
{
	if (!m_IsAttached)
		return;

    cbProject* pPrj = Manager::Get()->GetProjectManager()->GetActiveProject();
    if (!pPrj)
        return;

	EditorManager* edMan = Manager::Get()->GetEditorManager();
    if (!edMan)
		return;
    cbEditor* ed = edMan->GetBuiltinActiveEditor();
    if (!ed)
		return;

	Parser* parser = m_NativeParsers.FindParserFromActiveEditor();
	bool caseSens = parser ? parser->Options().caseSensitive : false;

	FileType ft = FileTypeOf(ed->GetShortName());
	if ( ft != ftHeader && ft != ftSource) // only parse source/header files
		return;

    int pos = ed->GetControl()->GetCurrentPos();
    int lineStartPos = ed->GetControl()->PositionFromLine(ed->GetControl()->GetCurrentLine());
    wxString line = ed->GetControl()->GetLine(ed->GetControl()->GetCurrentLine());
    //Manager::Get()->GetMessageManager()->DebugLog("#include cc for \"%s\"", line.c_str());
    line.Trim();
    if (line.IsEmpty() || !line.StartsWith(_T("#include")))
        return;

    // find opening quote (" or <)
    int idx = pos - lineStartPos;
    int found = -1;
    wxString filename;
    while (idx > 0)
    {
        wxChar c = line.GetChar(idx);
        if (c == _T('>'))
            return; // the quote is closed already...
        else if (c == _T('"') || c == _T('<'))
        {
            if (found != -1)
                return; // the already found quote was the closing one...
            found = idx + 1;
        }
        else if (c != _T(' ') && c != _T('\t') && !found)
            filename << c;
        --idx;
    }

    // take care: found might point at the end of the string (out of bounds)
    // in this case: #include "(<-code-completion at this point)
    //Manager::Get()->GetMessageManager()->DebugLog("#include using \"%s\" (starting at %d)", filename.c_str(), found);
    if (found == -1)
        return;

    // fill a list of matching project files
    wxArrayString files;
    for (int i = 0; i < pPrj->GetFilesCount(); ++i)
    {
        ProjectFile* pf = pPrj->GetFile(i);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -