1 module served.commands.color;
2 
3 import std.conv;
4 import std.format;
5 import std.regex;
6 
7 import served.types;
8 
9 static immutable colorRegex = ctRegex!`#([0-9a-fA-F]{2}){3,4}|"#([0-9a-fA-F]{2}){3,4}"`;
10 
11 @protocolMethod("textDocument/documentColor")
12 ColorInformation[] provideDocumentColor(DocumentColorParams params)
13 {
14 	Document document = documents[params.textDocument.uri];
15 	if (document.getLanguageId != "dml")
16 		return null;
17 
18 	ColorInformation[] ret;
19 
20 	{
21 		// if we ever want to make serve-d multi-threaded, want to lock here
22 		// document.lock();
23 		// scope (exit)
24 		// 	document.unlock();
25 
26 		size_t cacheBytes;
27 		Position cachePos;
28 		foreach (match; matchAll(document.rawText, colorRegex))
29 		{
30 			const(char)[] text = match.hit;
31 			if (text[0] == '"')
32 				text = text[1 .. $ - 1];
33 			assert(text[0] == '#', "broken regex match");
34 			text = text[1 .. $];
35 			assert(text.length == 6 || text.length == 8, "broken regex match");
36 
37 			TextRange range;
38 			cachePos = range.start = document.movePositionBytes(cachePos, cacheBytes, cacheBytes = match.pre.length);
39 			cachePos = range.end = document.movePositionBytes(cachePos, cacheBytes, cacheBytes = match.pre.length + match.hit.length);
40 
41 			Color color;
42 			if (text.length == 8)
43 			{
44 				color.alpha = text[0 .. 2].to!int(16) / 255.0;
45 				text = text[2 .. $];
46 			}
47 			color.red = text[0 .. 2].to!int(16) / 255.0;
48 			color.green = text[2 .. 4].to!int(16) / 255.0;
49 			color.blue = text[4 .. 6].to!int(16) / 255.0;
50 			ret ~= ColorInformation(range, color);
51 		}
52 	}
53 
54 	return ret;
55 }
56 
57 @protocolMethod("textDocument/colorPresentation")
58 ColorPresentation[] provideColorPresentations(ColorPresentationParams params)
59 {
60 	Document document = documents[params.textDocument.uri];
61 	if (document.getLanguageId != "dml")
62 		return null;
63 
64 	// only hex supported
65 	string hex;
66 	if (params.color.alpha != 1)
67 		hex = format!"#%02x%02x%02x%02x"(
68 			cast(int)(params.color.alpha * 255),
69 			cast(int)(params.color.red * 255),
70 			cast(int)(params.color.green * 255),
71 			cast(int)(params.color.blue * 255)
72 		);
73 	else
74 		hex = format!"#%02x%02x%02x"(
75 			cast(int)(params.color.red * 255),
76 			cast(int)(params.color.green * 255),
77 			cast(int)(params.color.blue * 255)
78 		);
79 
80 	return [ColorPresentation(hex)];
81 }