Skip to content

Commit 37c80d2

Browse files
committed
Add feature to link to src files as well
1 parent 73d3c46 commit 37c80d2

File tree

3 files changed

+107
-39
lines changed

3 files changed

+107
-39
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#github-linkify-cmssw
22

3-
This Chrome extension turns `#include X` in C/C++ files, and `import X`/`from X import Y`/`process.load(XXX.YYY.ZZZ_cff)` in python config files, into hyperlinks when viewing CMSSW files on Github.com, so you can get to the includes easily. (I don't know why this hasn't been done already.)
3+
This Chrome extension turns `#include X` in C/C++ files, and `import X`/`from X import Y`/`process.load(XXX.YYY.ZZZ_cff)` in python config files, into hyperlinks when viewing CMSSW files on Github.com, so you can get to the includes easily. It works on the central repo AND your forks. (I don't know why this hasn't been done already.)
4+
5+
C++ bonus: it even adds links to the related src files (if they exist).
46

57
## Instructions
68

@@ -32,4 +34,12 @@ Maybe I'll do a Firefox equivalent some day. If I ever get this one done.
3234

3335
8) Once you've made your edits, hit the Reload button below the extension (or ctrl/cmd+R on the chrome://extensions page) and reload your cmssw page to see your work in action!
3436

37+
## TODO/Ideas
38+
39+
- use github API?
40+
- options page to add loacation of headers for non-CMSSW repos?
41+
- or auto lookup - e.g. if #include "myEvent.h" link to same folder/myEvent.h, or #include "../myObj.h" link to ../myObj.h ?
42+
- options page? (keyboard shortcut, etc)
43+
- allow you to custom define where header files are?
44+
3545
Robin Aggleton 2014

contentscript.js

Lines changed: 90 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
// Main script
2+
//
3+
// Turns #include statments into hyperlinks
4+
// Also turns python import/process.load() statements into links as well
5+
//
6+
// Robin Aggleton 2014
7+
8+
19
// console.log("Debugging github-linkify-cmssw");
210

311

@@ -14,32 +22,77 @@ cmssw = cmssw_pattern.exec(url)[0];
1422
rootURL = url.substr(0, url.search(cmssw_pattern)+cmssw.length);
1523
// console.log("URL: " + rootURL);
1624

17-
// pattern to do #include matching
18-
var cpp_pattern = /#include/;
19-
var cpp_header_pattern = /[<\"].*[>\"]/; // does "myheader.h" or <myheader.h>
25+
// test line to see if is a valid "#include"
26+
function test_cpp_include(line) {
27+
// var cpp_pattern = /#include/;
28+
if (/#include/.test(line)
29+
&& (/\.h/.test(line))
30+
&& (line.indexOf("/") > 5) // to eliminate STL, the > 2 is to avoid commented lines as well
31+
&& (line.search("boost") == -1) // ignore popular libs
32+
)
33+
return true;
34+
else
35+
return false
36+
}
37+
38+
39+
// test line to see if valid python import/process.load/etc
40+
function test_py_import(line) {
41+
// patterns to do python matching
42+
var py_pattern1 = /from\s.*\simport\s.*/;
43+
var py_pattern2 = /import.*as.*/;
44+
var py_pattern3 = /import/;
45+
var py_pattern4 = /process.load(.*)/;
46+
47+
var config;
48+
if (py_pattern1.test(line)) {
49+
config = line.replace(/from\s/,"");
50+
config = config.replace(/\simport.*/,"");
51+
} else if (py_pattern2.test(line)) {
52+
config = line.replace(/import\s/,"");
53+
config = config.replace(/\sas\s.*/,"");
54+
} else if (py_pattern3.test(line)) {
55+
config = line.replace(/import\s/,"");
56+
} else if (py_pattern4.test(line)) {
57+
config = line.replace("process.load(","");
58+
config = config.replace(")","");
59+
}
60+
// ensure it has a / in it so it isn't a 3rd party library
61+
if ((/\./.test(config) || /\//.test(config)))
62+
return config;
63+
else
64+
return "";
65+
}
66+
67+
68+
// test if URL exists
69+
// slow??
70+
function UrlExists(url) {
71+
var http = new XMLHttpRequest();
72+
http.open('HEAD', url, false);
73+
http.send();
74+
return http.status != 404;
75+
}
2076

21-
// pattern to do python matching
22-
var py_pattern1 = /from\s.*\simport\s.*/;
23-
var py_pattern2 = /import.*as.*/;
24-
var py_pattern3 = /import/;
25-
var py_pattern4 = /process.load(.*)/;
2677

2778
// loop through all rows <tr>
2879
var rows = document.getElementsByTagName("tr");
29-
for (var i = 0; i < rows.length; i++) {
30-
for (var j = 0; j < rows[i].childNodes.length; j++) {
80+
for (var i = 0; i < rows.length; ++i) {
81+
for (var j = 0; j < rows[i].childNodes.length; ++j) {
3182

3283
// check it's a line of the file, not anything else
3384
var file_line_pattern = /js-file-line/;
3485
var cell = rows[i].childNodes[j];
86+
3587
if (file_line_pattern.test(cell.className)) {
3688
var line = cell.textContent;
3789

3890
// check line has a C++ #include, if so pull the header path
3991
// ensure it has a ".h", and a "/", to exclude STL
40-
if (cpp_pattern.test(line) && (/\.h/.test(line)) && (/\//.test(line))) {
92+
if (test_cpp_include(line)) {
93+
var cpp_header_pattern = /[<\"].*[>\"]/; // does "myheader.h" or <myheader.h>
4194
var path = cpp_header_pattern.exec(line)[0];
42-
path = path.replace(/[<>\"]/g,""); //g inmportant - global so replaces all instances
95+
path = path.replace(/[<>\"]/g, ""); //g inmportant - global so replaces all instances
4396
var link = rootURL.concat(path);
4497

4598
// get color of original text by getting class name of <span> or <td> tag that houses it,
@@ -50,37 +103,40 @@ for (var i = 0; i < rows.length; i++) {
50103
header_class = cell.childNodes[k].className;
51104
}
52105
}
53-
if (!header_class){
106+
if (!header_class) {
54107
header_class = cell.className.split(" ")[0];
55108
}
56109

57110
var color = window.getComputedStyle(document.querySelector("."+header_class)).getPropertyValue("color");
58111

59112
// let's replace the text with a link
60113
// keep same colour as before, but underline it to make it noticeable for user
61-
cell.innerHTML = cell.innerHTML.replace(path, "<a href=\""+link+"\" style=\"text-decoration:underline;color:"+color+"\">"+path+"</a>"); // <font color=\"#df5000\">
62-
}
114+
var newText = "<a href=\""+link+"\" style=\"text-decoration:underline;color:"+color+"\">"+path+"</a>";
115+
cell.innerHTML = cell.innerHTML.replace(path, newText); // <font color=\"#df5000\">
63116

64-
// tests for python imports/fragments
65-
var config = "";
66-
if (py_pattern1.test(line)) {
67-
config = line.replace(/from\s/,"");
68-
config = config.replace(/\simport.*/,"");
69-
} else if (py_pattern2.test(line)) {
70-
config = line.replace(/import\s/,"");
71-
config = config.replace(/\sas\s.*/,"");
72-
} else if (py_pattern3.test(line)) {
73-
config = line.replace(/import\s/,"");
74-
} else if (py_pattern4.test(line)) {
75-
config = line.replace("process.load(","");
76-
config = config.replace(")","");
117+
// we add in a tag to go to the src file instead
118+
// THIS ASSUMES THE FILE IS IN /src/ DIRECTORY
119+
// but what if it is in /plugins???
120+
// brutal way atm to tell if it's .cpp or .cc. Need github API here!
121+
var srcPath = link.replace("interface", "src");
122+
var cppSrc = srcPath.replace(".h", ".cpp");
123+
var ccSrc = srcPath.replace(".h", ".cc");
124+
if (UrlExists(cppSrc))
125+
srcPath = cppSrc;
126+
else if (UrlExists(ccSrc))
127+
srcPath = ccSrc;
128+
if (srcPath != link.replace("interface", "src")) {
129+
var srcText = "&nbsp&nbsp&nbsp<a href=\""+srcPath+"\" style=\"text-decoration:underline;\">[goto src]</a>";
130+
cell.innerHTML = cell.innerHTML.concat(srcText);
131+
}
77132
}
78133

134+
// tests for python imports/fragments
135+
var config = test_py_import(line);
79136
// if we have a valid python config, turn it into a path
80-
// ensure it has a / in it so it isn't a 3rd party library
81-
if (config != "" && (/\./.test(config) || /\//.test(config))) {
82-
config = config.replace(/['"]/g,"");
83-
var path = config.replace(/\./g,"/");
137+
if (config != "") {
138+
config = config.replace(/['"]/g, "");
139+
var path = config.replace(/\./g, "/");
84140
var parts = path.split("/");
85141
path = path.replace(parts[parts.length-1],"python/"+parts[parts.length-1]+".py")
86142
var link = rootURL.concat(path)
@@ -101,7 +157,8 @@ for (var i = 0; i < rows.length; i++) {
101157

102158
// let's replace the text with a link
103159
// keep same colour as before, but underline it to make it noticeable for user
104-
cell.innerHTML = cell.innerHTML.replace(config, "<a href=\""+link+"\" style=\"text-decoration:underline;color:"+color+"\">"+config+"</a>");
160+
var newText = "<a href=\""+link+"\" style=\"text-decoration:underline;color:"+color+"\">"+config+"</a>";
161+
cell.innerHTML = cell.innerHTML.replace(config, newText);
105162
}
106163
}
107164
}

manifest.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
{
22
"name": "Github linkify for CMSSW",
3-
"description": "Turns #include statments in C++ files, and import X/from X import Y/process.load(XXX.YYY.ZZZ_cff) in python config files, into links when browing CMSSW on Github.",
4-
"version": "0.2.7",
3+
"description": "Makes browsing CMSSW files waaaay easier.",
4+
"version": "0.3.0",
55
"content_scripts": [
66
{
77
"matches": [
88
"https://www.github.com/*/cmssw/*",
99
"https://github.com/*/cmssw/*"
1010
],
11-
"js": ["contentscript.js"],
12-
"run_at": "document_end" // pay attention to this line
11+
"js": ["contentscript.js"]
12+
// "js": ["contentscript.js", "jquery-2.1.1.min.js"]
13+
// "run_at": "document_end" // pay attention to this line
1314
}
1415
],
15-
"manifest_version":2
16+
"manifest_version": 2
1617
}

0 commit comments

Comments
 (0)