Beralih di antara sumber dan header file
Posted: Selasa, 05 April 2011 by Alfi Haryadi inKetika mengedit file sumber, script ini akan membawa pada file header yang sesuai, dan sebaliknya. Mendukung perluasan ini: cpp c hpp rh h rc. Dapat diperpanjang dengan mengedit array tunggal ('peta'). Pencarian Pertama di direktori yang sama, kemudian melakukan heuristik sedikit demi mengganti bagian dari jalan seperti '\ sumber \' dan '\ include \', untuk menemukan file yang terletak di jalan yang berbeda (seperti file Owl), seperti yang disarankan oleh Jogy . Jika Anda juga menyimpan header Anda secara terpisah dari sumber Anda, Anda dapat menyesuaikan lain array ('dirMap') sesuai dengan kebutuhan anda. Saat ditugaskan untuk
import IDE;
import editor;
declare keyCut = "
declare kbd = IDE.KeyboardManager.GetKeyboard("Editor");
kbd.Assign(keyCut, "CppH_Tog_Launch();");
print("Show Header assigned to " + keyCut);
CppH_Tog_Launch()
{
// just create an object to do the job
new CppH_Tog_Worker();
}
class CppH_Tog_Worker
{
declare topBuf = editor.TopBuffer;
// validate current buffer
if (!topBuf) {
IDE.StatusBar = "CppH_Tog: Invalid top buffer";
return;
}
// You can customize this mapping to better suit your needs.
// It's simply an array of entries, which are themselves
// an array of 2 elements:
// 1. the source extension (of the currently edited file)
// 2. a list (another array) of corresponding extensions, which
// are checked in order of appearance
//
// Note that I've mapped "cpp" first to "h" and then to "hpp".
// That's because I only use .h headers for .cpp files.
// If you're using .hpp headers they will be opened nicely,
// unless you also have a .h with the same name in the directory
// (for interfacing with C programs).
// In that case, just put "hpp" before "h".
//
declare map = {
{ "cpp", {"h", "hpp"} },
{ "h", {"cpp", "c" } },
{ "c", {"h" } },
{ "hpp", {"cpp" } },
{ "rc", {"rh" } },
{ "rh", {"rc" } }
};
// The next array provides mappings for the directory part
// of the filename.
// It's very useful for toggling between Owl source and
// headers, which are in different paths, e.g.
//
// Owl5
// C:\BC5\SOURCE\OWL\window.cpp
// C:\BC5\INCLUDE\OWL\window.h
//
// OwlNext
// C:\Owl\source\owlcore\window.cpp
// C:\Owl\include\owl\window.h
//
// This array contains string pairs. After scanning the directory
// for an open/existing file, we'll start replacing parts of it
// using the 'dirMap' table. The order of the two strings in each pair
// is not significant, since we'll check for both of them and
// replace whichever we find with the other.
// Each modification will be applied to the original path.
// Note that these 'tokens' are delimited by '\' characters
// to avoid partial replacement of directory names.
//
// The predefined pairs are mainly targeted to:
// 1. searching in the same directory;
// a single NULL causes the path to remain unchanged
// 2. Owl5 files.
// 3. OwlNext files.
// 4. Other cases.
// You can add more pairs, and rearrange their order.
//
declare dirMap = {
NULL,
{"\\include\\", "\\source\\"},
{"\\include\\owl\\", "\\source\\owlcore\\"},
{"\\inc\\", "\\src\\"}
};
// get the parts of the buffer's filename
declare drive = topBuf.Drive;
declare path = topBuf.Directory;
declare fname = topBuf.FileName;
declare ext = topBuf.Extension;
// get a list of mapped extensions
declare mapExt = GetMappedExtensions(ext);
// check for unsupported extensions
if (!mapExt) {
IDE.StatusBar = "CppH_Tog: Unsupported extension (" + ext + ")";
return;
}
//======================================
// STEP 1. Check for an existing buffer
//======================================
declare exBuf = GetExistingBuffer();
if (exBuf) {
HandleExistingBuffer(exBuf);
return; // if the above failed, we shouldn't continue
}
//=========================================
// STEP 2. Check if a matching file exists
//=========================================
// iterate through the mapped extensions to check
// if a matching file exists
declare exFile = GetExistingFile();
if (exFile) {
HandleExistingFile(exFile);
return; // if the above failed, we shouldn't continue
}
//======================================================
// STEP 3. Create a new buffer with the first extension
// in the same directory as a last resort.
//======================================================
// the file doesn't really exist, but we open it anyway
HandleExistingFile(drive + path + fname + "." + mapExt[0]);
// THE END
// ----------------------------------
// MEMBER FUNCTIONS FOLLOW:
// ----------------------------------
// ----------------------------------
// Check whether two strings match, ignoring case.
// ----------------------------------
StrIMatch(s1, s2)
{
s1 = (new String(s1)).Upper().Text;
s2 = (new String(s2)).Upper().Text;
return s1 == s2;
}
// ----------------------------------
// Check whether the specified extension
// exists in the mapping array.
// ----------------------------------
GetMappedExtensions(ext)
{
declare ret = NULL;
declare index; // cannot declare this inside 'iterate's parentheses
iterate (declare entry; map; index)
if (StrIMatch("." + entry[0], ext))
return map[index][1];
// we didn't find it
return NULL;
}
// ----------------------------------
// Return the first existing buffer in the IDE that matches
// the mapped extensions, or NULL if non is found.
// ----------------------------------
GetExistingBuffer()
{
declare sentry = 0;
// apply directory mappings
//
iterate (declare tokPair; dirMap)
{
declare xPath = TransformPath(path, tokPair);
if (xPath == NULL) continue; // in case the path didn't change
// walk the buffer list.
//
// explaining the 'for' loop params:
// init: we start checking the next buffer from the top
// cond: a valid buf and not the top buffer (because buffer list is circular)
// CAUTION: don't use "testBuf && (testBuf != topBuf)", it always evals to FALSE (don't know why...)
// step: the next, non-private buffer
//
for (declare testBuf = topBuf.NextBuffer(false);
(testBuf != NULL) && (testBuf != topBuf);
testBuf = testBuf.NextBuffer(false))
{
// iterate through the mapped extensions to check
// if the buffer matches one of them
iterate (declare testExt; mapExt)
{
if (StrIMatch(drive + xPath + fname + "." + testExt,
testBuf.FullName))
return testBuf;
}
// this sentry will terminate the loop
// in case something goes haywire :)
// (perhaps it's not needed...)
if (++sentry >= 1000) break;
}
}
// we couldn't find a valid buffer
return NULL;
}
// ----------------------------------
// If a matching buffer is found, try to open one of its views
// ----------------------------------
HandleExistingBuffer(exBuf)
{
// does it have any views?
if (exBuf.TopView) {
// (is EditView::Window always non-NULL? docs don't mention returning NULL)
exBuf.TopView.Window.IsHidden = false;
exBuf.TopView.Window.Activate();
}
else {
// there are no views attached;
// create a new window; a default view will be created too
declare newWnd = editor.EditWindowCreate(exBuf);
if (newWnd == NULL) {
IDE.StatusBar = "CppH_Tog: Could create new edit window";
return;
}
}
IDE.StatusBar = "CppH_Tog: OK";
}
// ----------------------------------
// Return the first existing file that matches
// the mapped extensions, or NULL if non is found.
// ----------------------------------
GetExistingFile()
{
// apply directory mappings
//
iterate (declare tokPair; dirMap)
{
declare xPath = TransformPath(path, tokPair);
if (xPath == NULL) continue; // in case the path didn't change
// iterate through the mapped extensions to check
// if the file exists
iterate (declare testExt; mapExt)
{
if (FileExists(drive + xPath + fname + "." + testExt))
return drive + xPath + fname + "." + testExt;
}
}
// we couldn't find an existing file
return NULL;
}
// ----------------------------------
// If a matching file is found, try to create a buffer
// and attach a new view to it.
// (NOTE: Assuming a buffer was not found,
// this function will create a new one)
// ----------------------------------
HandleExistingFile(fname)
{
// create an EditBuffer
declare newBuf = editor.EditBufferCreate(fname);
if (newBuf == NULL) {
IDE.StatusBar = "CppH_Tog: Could create new edit buffer";
return;
}
// create an EditWindow - a default view will be created too
declare newWnd = editor.EditWindowCreate(newBuf);
if (newWnd == NULL) {
IDE.StatusBar = "CppH_Tog: Could create new edit window";
return;
}
IDE.StatusBar = "CppH_Tog: OK";
}
// ----------------------------------
// Accepts a string path and a 'dirMap' entry,
// and returns a modified string path.
// By convention, if 'tokPair' is NULL, 'path' is returned
// (to allow searching in the same directory).
// If no replacement was possible, NULL is returned.
// ----------------------------------
TransformPath(path, pair)
{
if (pair == NULL)
return path;
declare n;
declare sPath = (new String(path )).Upper();
declare sTok1 = (new String(pair[0])).Upper();
declare sTok2 = (new String(pair[1])).Upper();
n = sPath.Index(sTok1.Text);
if (n) return StrReplace(path, --n, sTok1.Length, pair[1]);
n = sPath.Index(sTok2.Text);
if (n) return StrReplace(path, --n, sTok2.Length, pair[0]);
return NULL; // could not replace anything
}
// Replaces 'len' characters of string 'src',
// starting at 'pos', with string 'part'.
//
StrReplace(src, pos, len, part)
{
// note that .SubString(n,0) acts like .SubString(n)
// (i.e. it doesn't return "")
//
declare s = new String(src);
return (pos ? s.SubString(0, pos).Text : "")
+ part + s.SubString(pos + len).Text;
}
};