1 module ws.context;
2 
3 
4 import
5 	core.sync.mutex,
6 	std.string,
7 	std.stdio,
8 	std.process,
9 	std.parallelism,
10 	std.regex,
11 	std.algorithm,
12 	std.array,
13 	std.file;
14 
15 
16 void execute(string context, string type, string serialized, string command, string parameter=""){
17 	auto dg = {
18 		try{
19 			string command = (command.strip ~ ' ' ~ parameter).strip;
20 			if(!serialized.length)
21 				serialized = command;
22 			"running: \"%s\" in %s".format(command, context).writeln;
23 			auto pipes = pipeShell(command);
24 			auto pid = pipes.pid.processID;
25 			context.logExec(formatExec(pid, type, serialized, parameter));
26 			auto reader = task({
27 				foreach(line; pipes.stdout.byLine){
28 					if(line.length)
29 						context.log("%s stdout %s".format(pid, line));
30 				}
31 			});
32 			reader.executeInNewThread;
33 			foreach(line; pipes.stderr.byLine){
34 				if(line.length)
35 					context.log("%s stderr %s".format(pid, line));
36 			}
37 			auto res = pipes.pid.wait;
38 			context.log("%s exit %s".format(pid, res));
39 			context.logExec("%s exit %s".format(pid, res));
40 		}catch(Throwable t)
41 			writeln(t);
42 	};
43 	task(dg).executeInNewThread;
44 }
45 
46 
47 void openFile(string context, string path){
48 	context.openPath(path, "file");
49 }
50 
51 
52 void openDir(string context, string path){
53 	context.openPath(path, "directory");
54 }
55 
56 
57 void openPath(string context, string path, string type){
58 	auto command = `exo-open "%s" || xdg-open "%s"`.format(path,path);
59 	context.execute(type, path, command);
60 }
61 
62 
63 string[] bangSplit(string text){
64 	return text.split(regex(`(?<!\\)\!`)).map!`a.replace("\\!", "!")`.array;
65 }
66 
67 string bangJoin(string[] parts){
68 	return parts.map!`a.replace("!", "\\!")`.join("!");
69 }
70 
71 
72 string formatExec(long pid, string type, string serialized, string parameter){
73 	return "%s exec %s!%s!%s".format(pid, type, serialized, parameter);
74 }
75 
76 
77 string unixEscape(string path){
78 	return path
79 		.replace(" ", "\\ ")
80 		.replace("(", "\\(")
81 		.replace(")", "\\)");
82 }
83 
84 string unixClean(string path){
85 	return path
86 		.replace("\\ ", " ")
87 		.replace("\\(", "(")
88 		.replace("\\)", ")");
89 }
90 
91 
92 __gshared private Mutex logMutex;
93 
94 shared static this(){
95 	logMutex = new Mutex;
96 }
97 
98 void log(string context, string text){
99 	synchronized(logMutex){
100 		auto path = context ~ ".log";
101 		if(path.exists)
102 			path.append(text ~ '\n');
103 		else
104 			std.file.write(path, text ~ '\n');
105 	}
106 }
107 
108 void logExec(string context, string text){
109 	context.log(text);
110 	synchronized(logMutex){
111 		auto path = context ~ ".exec";
112 		if(path.exists)
113 			path.append(text ~ '\n');
114 		else
115 			std.file.write(path, text ~ '\n');
116 	}
117 }
118