gio-unix-2.0: Add DesktopAppInfo.launch_uris_as_manager_with_fds()
[vala-gnome.git] / libvaladoc / content / sourcecode.vala
bloba9b74b55856c971a52ed33235fbc5e5103406257
1 /* sourcecode.vala
3 * Copyright (C) 2008-2009 Didier Villevalois
4 * Copyright (C) 2008-2012 Florian Brosch
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Author:
21 * Didier 'Ptitjes Villevalois <ptitjes@free.fr>
25 public class Valadoc.Content.SourceCode : ContentElement, Inline {
26 public enum Language {
27 UNKNOWN,
28 GENIE,
29 VALA,
30 XML,
33 public static Language from_path (string path) {
34 int pos = path.last_index_of (".");
35 if (pos < 0) {
36 return Language.UNKNOWN;
39 string ext = path.substring (pos + 1);
40 return from_string (ext, true);
43 public static Language from_string (string str, bool is_extension = false) {
44 switch (str) {
45 case "genie":
46 if (is_extension) {
47 return Language.UNKNOWN;
49 return Language.GENIE;
50 case "gs":
51 return Language.GENIE;
52 case "xml":
53 return Language.XML;
54 case "vala":
55 return Language.VALA;
56 case "c":
57 case "h":
58 return Language.C;
61 return Language.UNKNOWN;
64 public unowned string to_string () {
65 switch (this) {
66 case Language.GENIE:
67 return "genie";
68 case Language.VALA:
69 return "vala";
70 case Language.XML:
71 return "xml";
72 case Language.C:
73 return "c";
76 assert_not_reached ();
81 public string code {
82 get;
83 set;
86 public Run? highlighted_code {
87 get;
88 private set;
91 public Language language {
92 get;
93 set;
96 internal SourceCode () {
97 base ();
98 _language = Language.VALA;
101 private string? get_path (string path, Api.Node container, string source_file_path,
102 ErrorReporter reporter)
104 // search relative to our file
105 if (!Path.is_absolute (path)) {
106 string relative_to_file = Path.build_path (Path.DIR_SEPARATOR_S,
107 Path.get_dirname (source_file_path),
108 path);
109 if (FileUtils.test (relative_to_file, FileTest.EXISTS | FileTest.IS_REGULAR)) {
110 return (owned) relative_to_file;
114 // search relative to the current directory / absoulte path
115 if (!FileUtils.test (path, FileTest.EXISTS | FileTest.IS_REGULAR)) {
116 string node_segment = (container is Api.Package)? "" : container.get_full_name () + ": ";
117 code = "File '%s' does not exist".printf (path);
118 reporter.simple_warning ("%s: %s{{{".printf (source_file_path, node_segment),
119 "%s", code);
120 return null;
123 return path;
126 private void load_source_code (string _path, Api.Node container, string source_file_path,
127 ErrorReporter reporter)
129 string? path = get_path (_path, container, source_file_path, reporter);
130 if (path == null) {
131 return ;
134 try {
135 string content = null;
136 FileUtils.get_contents (path, out content);
137 _language = Language.from_path (path);
138 code = (owned) content;
139 } catch (FileError err) {
140 string node_segment = (container is Api.Package)? "" : container.get_full_name () + ": ";
141 reporter.simple_error ("%s: %s{{{".printf (source_file_path, node_segment),
142 "Can't read file '%s': %s", path, err.message);
146 private inline bool is_empty_string (string line) {
147 for (int i = 0; line[i] != '\0'; i++) {
148 if (line[i].isspace () == false) {
149 return false;
153 return true;
156 private string strip_code (string code) {
157 string[] lines = code.split ("\n");
158 for (int i = lines.length - 1; i >= 0 && is_empty_string (lines[i]); i--) {
159 lines[i] = null;
162 string** _lines = lines;
163 for (int i = 0; lines[i] != null && is_empty_string (lines[i]); i++) {
164 _lines = &lines[i + 1];
167 return string.joinv ("\n", (string[]) _lines);
170 public override void check (Api.Tree api_root, Api.Node container, string file_path,
171 ErrorReporter reporter, Settings settings)
173 string[] splitted = code.split ("\n", 2);
174 if (splitted[0].strip () == "") {
175 code = splitted[1] ?? "";
176 } else if (splitted[0].has_prefix ("#!")) {
177 unowned string start = (string) (((char*) splitted[0]) + 2);
178 if (start.has_prefix ("include:")) {
179 start = (string) (((char*) start) + 8);
180 string path = start.strip ();
181 load_source_code (path, container, file_path, reporter);
182 } else {
183 string name = start._strip ().down ();
184 _language = Language.from_string (name);
185 code = splitted[1] ?? "";
186 if (_language == Language.UNKNOWN && name != "none") {
187 string node_segment = (container is Api.Package)? "" : container.get_full_name () + ": ";
188 reporter.simple_warning ("%s: %s{{{".printf (file_path, node_segment),
189 "Unsupported programming language '%s'", name);
194 code = strip_code (code);
196 if (_language == Language.VALA) {
197 highlighted_code = api_root.highlighter.highlight_vala (code);
198 } else if (_language == Language.XML) {
199 highlighted_code = api_root.highlighter.highlight_xml (code);
200 } else if (_language == Language.C) {
201 highlighted_code = api_root.highlighter.highlight_c (code);
202 } else {
203 highlighted_code = new Run (Run.Style.MONOSPACED);
204 highlighted_code.content.add (new Text (code));
208 public override void accept (ContentVisitor visitor) {
209 visitor.visit_source_code (this);
212 public override void accept_children (ContentVisitor visitor) {
213 if (highlighted_code != null) {
214 highlighted_code.accept (visitor);
218 public override bool is_empty () {
219 // empty source blocks are visible as well
220 return false;
223 public override ContentElement copy (ContentElement? new_parent = null) {
224 SourceCode source_code = new SourceCode ();
225 source_code.parent = new_parent;
227 source_code.language = language;
228 source_code.code = code;
230 return source_code;