Skip to content

Commit f46ea1b

Browse files
author
Todd Whiteman
committed
macros: add alternative location macro
1 parent 73f45ba commit f46ea1b

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ This is a collection of useful Komodo macros.
1818
- [Brace Wrap Selection](#brace-wrap-selection-code)
1919
- [Byte or Char Position](#byte-or-char-position-code)
2020
- [Img Tag Dimensions](#img-tag-dimensions-code)
21+
- [Alternative Location](#alternative-location-code)
2122

2223
- [How to Install](#installing)
2324
- [Contributing](#contributing)
@@ -88,10 +89,18 @@ Show the Byte or Char position of your cursor in the Statusbar beside Ln and
8889
Col.
8990

9091
### Img Tag Dimensions ([code](img_dimensions.js))
92+
9193
Execute the macro insdie an img tag in an html file, which the src attribute
9294
filled in. The macro will load the image and input the height and width of
9395
the image attributes with the correct dimensions
9496

97+
### Alternative Location ([code](alternative_location.js))
98+
99+
Adds an editor tab context menuitem for opening a komodo file in an alternative
100+
location. The alternative locations are read from a *locations.ini*
101+
configuration file in the Komodo profile directory.
102+
103+
95104
## Installing
96105

97106
Create a new macro in your Komodo toolbox and copy/paste the contents into the

alternative_location.js

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// Adds an editor tab context menuitem for opening a komodo file in
2+
// an alternative location. The alternative locations are read from the
3+
// "locations.ini" file in the Komodo profile directory.
4+
//
5+
// Example "locations.ini" config file:
6+
//
7+
// path1 = /home/toddw/src/checkout1/
8+
// path2 = /home/toddw/alt/checkout2/
9+
//
10+
// Given the above configuration, if I had this file open in Komodo:
11+
// /home/toddw/src/checkout1/libs/entry1.py
12+
// I could right click on the tab, choose "Open at location > path2",
13+
// and Komodo would try to open this file:
14+
// /home/toddw/alt/checkout2/libs/entry1.py
15+
//
16+
17+
if (typeof(window.extensions) == 'undefined') {
18+
window.extensions = {};
19+
}
20+
if (typeof(extensions.locations) == 'undefined') {
21+
extensions.locations = {};
22+
}
23+
24+
extensions.locations.paths = [];
25+
26+
extensions.locations.editConfigFile = function() {
27+
var koDirs = Components.classes["@activestate.com/koDirs;1"].getService(Components.interfaces.koIDirs);
28+
var koOs = Components.classes["@activestate.com/koOs;1"].getService(Components.interfaces.koIOs);
29+
var configpath = [koDirs.userDataDir, "locations.ini"].join(koOs.sep);
30+
ko.open.URI(configpath);
31+
}
32+
33+
extensions.locations.openAtIndex = function(idx) {
34+
var view = ko.views.manager.currentView;
35+
var file = view.koDoc.file;
36+
var fpath = file.path;
37+
// Find out what configuration it's coming from.
38+
var prefix = "";
39+
for (var i=0; i < extensions.locations.paths.length; i++) {
40+
var trypath = extensions.locations.paths[i];
41+
// Prefer the longest config path.
42+
if (fpath.startsWith(trypath) && prefix.length < trypath.length) {
43+
prefix = trypath;
44+
break;
45+
}
46+
}
47+
if (!prefix) {
48+
ko.dialogs.alert("This file is not a descendant of any directory in the config file");
49+
return;
50+
}
51+
// Open at the alternative location.
52+
var scimoz = view.scimoz;
53+
var lineno = scimoz.lineFromPosition(scimoz.currentPos) + 1;
54+
var osPathSvc = Components.classes["@activestate.com/koOsPath;1"].getService(Components.interfaces.koIOsPath);
55+
var path = extensions.locations.paths[idx];
56+
var rel_path = fpath.substr(prefix.length);
57+
var path = osPathSvc.join(path, rel_path);
58+
ko.views.manager.doFileOpenAtLineAsync(path, lineno);
59+
}
60+
61+
// Creating the UI.
62+
function createXULElement(tagName, attributes) {
63+
var elem = document.createElement(tagName);
64+
var attr;
65+
for (attr in attributes) {
66+
elem.setAttribute(attr, attributes[attr]);
67+
}
68+
return elem;
69+
}
70+
71+
extensions.locations.reloadConfiguration = function() {
72+
var koDirs = Components.classes["@activestate.com/koDirs;1"].getService(Components.interfaces.koIDirs);
73+
var koOs = Components.classes["@activestate.com/koOs;1"].getService(Components.interfaces.koIOs);
74+
var configpath = [koDirs.userDataDir, "locations.ini"].join(koOs.sep);
75+
76+
var menupopup = document.getElementById("openKomodoLocationMenupopup");
77+
if (!menupopup) {
78+
// Create the menu.
79+
var menu = createXULElement("menu", {
80+
"id": "openKomodoLocationMenu",
81+
"label": "Open at location"
82+
});
83+
var menupopup = createXULElement("menupopup", {
84+
"id": "openKomodoLocationMenupopup"
85+
});
86+
menu.appendChild(menupopup);
87+
var tabContextMenu = document.getElementById("tabContextMenu");
88+
tabContextMenu.insertBefore(menu, document.getElementById("menu_splittab"));
89+
} else {
90+
// Remove all existing openAt menu entries.
91+
while (menupopup.firstChild) {
92+
menupopup.removeChild(menupopup.firstChild);
93+
}
94+
}
95+
96+
// Load the config file and read all the entries.
97+
var kofile = Components.classes["@activestate.com/koFileEx;1"].createInstance(Components.interfaces.koIFileEx);
98+
kofile.URI = ko.uriparse.pathToURI(configpath);
99+
if (!koOs.path.exists(configpath)) {
100+
// Create a template one.
101+
var template = "# Kobranch configuration file\n" +
102+
"#\n" +
103+
"# Format of entries is: <name> = <path>\n" +
104+
"#\n" +
105+
"# Examples:\n" +
106+
"# foo = /home/toddw/src/branch2/src\n" +
107+
"# zoink = C:\path\to\code\directory\n" +
108+
"#\n" +
109+
"";
110+
kofile.open("w");
111+
kofile.puts(template);
112+
kofile.close();
113+
}
114+
kofile.open("r");
115+
var contents = kofile.readfile();
116+
kofile.close();
117+
// Parse the entries: "name = /absolute/path/to/dir"
118+
var lines = contents.split("\n");
119+
var match;
120+
var menuitem = null;
121+
for (var i=0; i < lines.length; i++) {
122+
match = lines[i].match(/^(.*?)\s*=\s*(.*)$/);
123+
if (match && match[1][0] != "#") {
124+
var branchdir = koOs.path.expanduser(match[2]);
125+
// Add directory separator on the end.
126+
if (!branchdir.substr(-1) != koOs.sep) {
127+
branchdir += koOs.sep;
128+
}
129+
if (extensions.locations.paths.indexOf(branchdir) >= 0) {
130+
continue; // That path already exists.
131+
}
132+
menuitem = createXULElement("menuitem", {
133+
"id": "openKomodoLocationMenuitem_" + match[1],
134+
"label": match[1],
135+
"oncommand": "extensions.locations.openAtIndex(" + extensions.locations.paths.length + ")"
136+
});
137+
menupopup.appendChild(menuitem);
138+
extensions.locations.paths.push(branchdir);
139+
}
140+
}
141+
if (menuitem) {
142+
// Items for found - add a separator.
143+
menupopup.appendChild(createXULElement("menuseparator"));
144+
}
145+
// Create menuitem to access the config file.
146+
menuitem = createXULElement("menuitem", {
147+
"id": "openKomodoLocationMenuitem_editfile",
148+
"label": "Edit configuration file",
149+
"oncommand": "extensions.locations.editConfigFile()"
150+
});
151+
menupopup.appendChild(menuitem);
152+
// Create config reload menuitem.
153+
menuitem = createXULElement("menuitem", {
154+
"id": "openKomodoLocationMenuitem_editfile",
155+
"label": "Reload configuration",
156+
"oncommand": "extensions.locations.reloadConfiguration()"
157+
});
158+
menupopup.appendChild(menuitem);
159+
}
160+
161+
// Load for the first time.
162+
extensions.locations.reloadConfiguration();

0 commit comments

Comments
 (0)