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 			reader.yieldForce;
38 			auto res = pipes.pid.wait;
39 			context.log("%s exit %s".format(pid, res));
40 			context.logExec("%s exit %s".format(pid, res));
41 		}catch(Throwable t)
42 			writeln(t);
43 	};
44 	task(dg).executeInNewThread;
45 }
46 
47 
48 void openFile(string context, string path){
49 	context.openPath(path, "file");
50 }
51 
52 
53 void openDir(string context, string path){
54 	context.openPath(path, "directory");
55 }
56 
57 
58 void openPath(string context, string path, string type){
59 	auto command = `exo-open "%s" || xdg-open "%s"`.format(path,path);
60 	context.execute(type, path, command);
61 }
62 
63 
64 string[] bangSplit(string text){
65 	return text.split(regex(`(?<!\\)\!`)).map!`a.replace("\\!", "!")`.array;
66 }
67 
68 string bangJoin(string[] parts){
69 	return parts.map!`a.replace("!", "\\!")`.join("!");
70 }
71 
72 
73 string formatExec(long pid, string type, string serialized, string parameter){
74 	return "%s exec %s!%s!%s".format(pid, type, serialized, parameter);
75 }
76 
77 
78 string unixEscape(string path){
79 	return path
80 		.replace(" ", "\\ ")
81 		.replace("(", "\\(")
82 		.replace(")", "\\)");
83 }
84 
85 string unixClean(string path){
86 	return path
87 		.replace("\\ ", " ")
88 		.replace("\\(", "(")
89 		.replace("\\)", ")");
90 }
91 
92 
93 __gshared private Mutex logMutex;
94 
95 shared static this(){
96 	logMutex = new Mutex;
97 }
98 
99 void log(string context, string text){
100 	synchronized(logMutex){
101 		auto path = context ~ ".log";
102 		if(path.exists)
103 			path.append(text ~ '\n');
104 		else
105 			std.file.write(path, text ~ '\n');
106 	}
107 }
108 
109 void logExec(string context, string text){
110 	context.log(text);
111 	synchronized(logMutex){
112 		auto path = context ~ ".exec";
113 		if(path.exists)
114 			path.append(text ~ '\n');
115 		else
116 			std.file.write(path, text ~ '\n');
117 	}
118 }
119