Some time back I had developed a scripted plugin just for my personal experience. Today I found this within the many folders on my HDD by accident and I think it's worth sharing for people that are interested in such kind of plugins. Take it as an excercise...
What does it do? It searches within a project for broken files - thus, files that are part of the project but do no longer exist on the drive. It shows a list of these files and offers to remove them from the project. Now what is so special about that? Nothing, except this is a scripted plugin. Never heard of such? C::B offers so much more that you can ever imagine... ;-) Scripted plugins use the scripting engine inside C::B and the exposed parts of the C::B SDK to be nearly as powerful as "binary" plugins but do require *no* compilation.
So what do you have to do? Read the documentation about scripting in the WiKi. Install the plugin as following:
- create a file named "find_broken_files.script"
- copy the content of the file (as shown below in the attachment) within this file
- put the file (which already is the ready-to-use plugin!) into: [C::B]\share\CodeBlocks\scripts
- open the startup.script file in the very same folder
- add the line: Include(_T("find_broken_files.script")); just where the comments state to do so
- restart C::B, open a project and right-click on it in the project tree
- notice the new menu entry "Find broken files in project"
- inspect the scripted plugin again to understand it's "magic" - it's very simple!
With regards, Morten.
Attachment (file "find_broken_files.script"):
//
// Script that searches inside a project for invalid (broken) files
// Created by MortenMacFly for Code::Blocks IDE (www.codeblocks.org)
//
class FindBrokenFilesPlugin extends cbScriptPlugin
{
// mandatory to setup the plugin's info
constructor()
{
info.name = _T("Find Broken Files plugin");
info.title = _T("Find Broken Files");
info.version = _T("0.9");
info.license = _T("GPL");
}
// create menubar items
function GetMenu()
{
local entries = ::wxArrayString();
entries.Add(_T("Project/-Find broken files in project"), 1);
return entries;
}
// create context menu entries
function GetModuleMenu(who, data)
{
local entries = ::wxArrayString();
if (who == ::mtProjectManager)
entries.Add(_T("Find broken files in project"), 1);
return entries;
}
// support ExecutePlugin(pluginNameString)
function Execute()
{
// try to open the project manager
local pm = GetProjectManager();
// display a message if project manager could not be located
if (IsNull(pm))
{
ShowError(_T("Could not query the project manager. Cannot continue."));
return 0;
}
// try to query the currently active project (which we will analyse)
local p = pm.GetActiveProject();
// display a message if there is no active project
if (IsNull(p))
{
ShowError(_T("Currently no project is loaded/activated. Cannot continue."));
return 0;
}
// verify that there are files in the project to analyse
local files_count = p.GetFilesCount();
// display a message if the project contains no files
if (files_count<1)
{
ShowError(_T("The active project contains no files. Cannot continue."));
return 0;
}
//else
// ShowInfo(_T("The active project has ") + files_count + _T(" files."));
// search for broken files
local broken_files = 0;
local broken_files_str = _T("");
for (local i=0; i<files_count; i++)
{
local pf = p.GetFile(i);
if (IsNull(pf))
{
ShowError(_T("Could not access project file(s). Cannot continue."));
return 0;
}
local full_path = pf.file.GetFullPath(::wxPATH_NATIVE);
if (!IO.FileExists(full_path))
{
broken_files++;
broken_files_str = broken_files_str + full_path + _T("\n");
}
}
// operate broken files (if any)
if (broken_files>0)
{
ShowInfo(_T("The project has ") + broken_files + _T(" broken files:\n") + broken_files_str);
local msg = _T("Do you want to remove them from the project now?");
local remove_files = Message(msg, _T("Broken Files Plugin"), ::wxICON_QUESTION | ::wxYES_NO);
if (remove_files==::wxID_YES)
{
// search for broken files again and remove them from the project
local removed_files = 0;
for (local i=0; i<files_count; i++)
{
local pf = p.GetFile(i-removed_files);
if (IsNull(pf))
{
ShowError(_T("Could not access project file(s). Cannot continue."));
return 0;
}
local full_path = pf.file.GetFullPath(::wxPATH_NATIVE);
if (!IO.FileExists(full_path))
{
if (p.RemoveFile(i-removed_files))
{
removed_files++;
files_count--;
}
}
}
pm.RebuildTree();
ShowInfo(_T("Operation successfully completed.\n") + removed_files + _T(" files have been removed."));
}
else
ShowInfo(_T("Operation cancelled."));
}
else
ShowInfo(_T("In this project no broken files were found."));
return 0;
}
// callback for menubar items clicking
function OnMenuClicked(index)
{
local result = Execute();
}
// callback for context menu items clicking
function OnModuleMenuClicked(index)
{
local result = Execute();
}
}
// this call actually registers the script plugin with Code::Blocks
RegisterPlugin(FindBrokenFilesPlugin());
Edit1: Fixed a little bug in the script on behalf of killerbot...
Edit2: Fixed another bug that wouldn't allow to remove the duplicate files
great :-)
Thumbs up !!!
Quote from: killerbot on June 13, 2007, 11:21:51 PM
great :-)
Hehe... this actually came into my mind when I saw your changes with r4093. This *could* have been done similarly by a script(ed plugin), too. (Although it surely makes more sense in the SDK). ;-)
here is an adaptation for r7639
local full_path = pf.file.GetFullPath(::wxPATH_NATIVE);
if (!IO.FileExists(full_path))
{
//--> LETARTARE for r7639
// if (p.RemoveFile(i-removed_files))
if (p.RemoveFile(pf))
//<-- LETARTARE
{
removed_files++;
files_count--;
}
}
Morten: Have you thought of putting this in svn?
Also have you tried to put a menu entry in Plugins instead of the context menu of the project, something like "Plugins->Find broken files"?
yes it would be a good idea.
adaptation is easy.
Quote from: oBFusCATed on December 29, 2011, 05:05:57 PM
Morten: Have you thought of putting this in svn?
Both of you: Have you seen that this post is dated back to 2007? Teodor: You can safely apply it if its still working... I don't know, if that's still the case.
I use it very often.
This is a great utility.
It doesn't work for me. It fails on GetFile, LETARTARE, do I need some scripting patch in order to make it work?
yes, it should be svn r7639 (jens)
http://forums.next.codeblocks.org/index.php/topic,15596.msg105399.html#msg105399 (http://forums.next.codeblocks.org/index.php/topic,15596.msg105399.html#msg105399)
Uf, I had to update my working copy :(
It works fine with release 10.05 (new 'find_broken_files.script)
OK, I've committed it to trunk...
Quote from: oBFusCATed on December 29, 2011, 09:02:25 PM
OK, I've committed it to trunk...
BTW: Reminds me: I had an issue with this script the past time I used it: When removing files, some were left and you had to call the script several times to really remove all broken files. Is that still the case?
I've tried it on the codeblocks-unix.cbp and it removed one file successfully :)
Quote from: MortenMacFly on December 30, 2011, 07:50:15 AM
Quote from: oBFusCATed on December 29, 2011, 09:02:25 PM
OK, I've committed it to trunk...
BTW: Reminds me: I had an issue with this script the past time I used it: When removing files, some were left and you had to call the script several times to really remove all broken files. Is that still the case?
Yes it is.
The cause is that you loop forward through the files and remove them.
In general it's better to do this backwards if removing array members, because a removed index does not change the indexes following in the loop.
I fixed it in trunk and now it seems to work as expected.
Quote from: oBFusCATed on December 30, 2011, 09:58:23 AM
I've tried it on the codeblocks-unix.cbp and it removed one file successfully :)
Note that this might not really be a missing file. some of the files are Windows only and are simple "disabled" in Unix.
Quote from: jens on December 30, 2011, 10:22:41 AM
In general it's better to do this backwards if removing array members, because a removed index does not change the indexes following in the loop.
I know, but it was really just a demo and I was to lazy to take care.
Quote from: jens on December 30, 2011, 10:22:41 AM
I fixed it in trunk and now it seems to work as expected.
Thanks! :)
Good year for C::B.
@jens
r7650 in 'src/scripts/plugin_find_broken_files.script',
line of code:
Quoteentries.Add(_T("Plugins/0:-Find broken files in project"), 1);
creates an entry 'Plugins' in the international versions !
I propose instead
Quoteentries.Add(_("&Plugins") + _T("/0:-") + _("Find broken files in project"), 1) ;
which also allows the translation.
Other hand, all the scripts in this directory can be prepared for the translation, I can send
a zip of changed files and 'scripts.pot', that works at home.
As far as I can see you've not tested the change, have you?
I think so, because the correct line is:
entries.Add(_("P&lugins") + _T("/0:-") + _("Find broken files in project"), 1);
Please verify my version of the line is correct and I'll commit it.
I tested and it works with my setup !
In r7650 (English) with '&Plugins', 'P&lugins', 'Plugins' it works !!
and French works as.
So what is the correct line? Your last post is quite confusing.
The '&' is not taken into account.
Take 'Plugins' as 'Jens'.
r7650 : In the source 'src\main.cpp:926' found _('P&lugins').
Yes, I know, that's why I've said that you've not tested your change, but if it doesn't matter I'll commit a version without the '&' character.
@ofuscated
I am sorry but I tested all the possibilities on r7650, before posting:
Quote'Plugins'
Quote'&Plugins'
Quote'P&lugins'
all work on my computer!
In addition, the menus, letters preceded by '&' are no different from others letters.