KTextEditor

editorconfig.cpp
1/*
2 SPDX-FileCopyrightText: 2017 Grzegorz Szymaszek <gszymaszek@short.pl>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "editorconfig.h"
8#include "kateconfig.h"
9#include "katedocument.h"
10#include "katepartdebug.h"
11
12/**
13 * @return whether a string value could be converted to a bool value as
14 * supported. The value is put in *result.
15 */
16static bool checkBoolValue(QString val, bool *result)
17{
18 val = val.trimmed().toLower();
19 static const QStringList trueValues{QStringLiteral("1"), QStringLiteral("on"), QStringLiteral("true")};
20 if (trueValues.contains(val)) {
21 *result = true;
22 return true;
23 }
24
25 static const QStringList falseValues{QStringLiteral("0"), QStringLiteral("off"), QStringLiteral("false")};
26 if (falseValues.contains(val)) {
27 *result = false;
28 return true;
29 }
30 return false;
31}
32
33/**
34 * @return whether a string value could be converted to a integer value. The
35 * value is put in *result.
36 */
37static bool checkIntValue(const QString &val, int *result)
38{
39 bool ret(false);
40 *result = val.toInt(&ret);
41 return ret;
42}
43
44EditorConfig::EditorConfig(KTextEditor::DocumentPrivate *document)
45 : m_document(document)
46 , m_handle(editorconfig_handle_init())
47{
48}
49
50EditorConfig::~EditorConfig()
51{
52 editorconfig_handle_destroy(m_handle);
53}
54
55int EditorConfig::parse()
56{
57 const int code = editorconfig_parse(m_document->url().toLocalFile().toStdString().c_str(), m_handle);
58
59 if (code != 0) {
60 if (code == EDITORCONFIG_PARSE_MEMORY_ERROR) {
61 qCDebug(LOG_KTE) << "Failed to parse .editorconfig, memory error occurred";
62 } else if (code > 0) {
63 qCDebug(LOG_KTE) << "Failed to parse .editorconfig, error in line" << code;
64 } else {
65 qCDebug(LOG_KTE) << "Failed to parse .editorconfig, unknown error";
66 }
67
68 return code;
69 }
70
71 // count of found key-value pairs
72 const unsigned int count = editorconfig_handle_get_name_value_count(m_handle);
73
74 // if indent_size=tab
75 bool setIndentSizeAsTabWidth = false;
76
77 // whether corresponding fields were found in .editorconfig
78 bool indentSizeSet = false;
79 bool tabWidthSet = false;
80
81 // the following only applies if indent_size=tab and there isn’t tab_width
82 int tabWidth = m_document->config()->tabWidth();
83
84 for (unsigned int i = 0; i < count; ++i) {
85 // raw values from EditorConfig library
86 const char *rawKey = nullptr;
87 const char *rawValue = nullptr;
88
89 // buffers for integer/boolean values
90 int intValue;
91 bool boolValue;
92
93 // fetch next key-value pair
94 editorconfig_handle_get_name_value(m_handle, i, &rawKey, &rawValue);
95
96 // and convert to Qt strings
97 const QLatin1String key = QLatin1String(rawKey);
98 const QLatin1String value = QLatin1String(rawValue);
99
100 if (QLatin1String("charset") == key) {
101 m_document->setEncoding(value);
102 } else if (QLatin1String("end_of_line") == key) {
103 QStringList eols;
104
105 // NOTE: EOLs are declared in Kate::TextBuffer::EndOfLineMode
106 eols << QStringLiteral("lf") << QStringLiteral("crlf") << QStringLiteral("cr");
107
108 if ((intValue = eols.indexOf(value)) != -1) {
109 m_document->config()->setEol(intValue);
110 m_document->config()->setAllowEolDetection(false);
111 } else {
112 qCDebug(LOG_KTE) << "End of line in .editorconfig other than unix/dos/mac";
113 }
114 } else if (QLatin1String("indent_size") == key) {
115 if (QLatin1String("tab") == value) {
116 setIndentSizeAsTabWidth = true;
117 } else if (checkIntValue(value, &intValue)) {
118 m_document->config()->setIndentationWidth(intValue);
119 indentSizeSet = true;
120 } else {
121 qCDebug(LOG_KTE) << "Indent size in .editorconfig not a number, nor tab";
122 }
123 } else if (QLatin1String("indent_style") == key) {
124 if (QLatin1String("tab") == value) {
125 m_document->config()->setReplaceTabsDyn(false);
126 } else if (QLatin1String("space") == value) {
127 m_document->config()->setReplaceTabsDyn(true);
128 } else {
129 qCDebug(LOG_KTE) << "Indent style in .editorconfig other than tab or space";
130 }
131 } else if (QLatin1String("insert_final_newline") == key && checkBoolValue(value, &boolValue)) {
132 m_document->config()->setNewLineAtEof(boolValue);
133 } else if (QLatin1String("max_line_length") == key && checkIntValue(value, &intValue)) {
134 m_document->config()->setWordWrapAt(intValue);
135 } else if (QLatin1String("tab_width") == key && checkIntValue(value, &intValue)) {
136 m_document->config()->setTabWidth(intValue);
137 tabWidth = intValue;
138 tabWidthSet = true;
139 } else if (QLatin1String("trim_trailing_whitespace") == key && checkBoolValue(value, &boolValue)) {
140 if (boolValue) {
141 m_document->config()->setRemoveSpaces(1 /* remove trailing spaces of modified lines (line modification system) */);
142 } else {
143 m_document->config()->setRemoveSpaces(0);
144 }
145 }
146 }
147
148 if (setIndentSizeAsTabWidth) {
149 m_document->config()->setIndentationWidth(tabWidth);
150 } else if (!tabWidthSet && indentSizeSet) {
151 m_document->config()->setTabWidth(m_document->config()->indentationWidth());
152 }
153
154 return 0;
155}
int toInt(bool *ok, int base) const const
QString toLower() const const
QString trimmed() const const
int indexOf(QStringView str, int from) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Feb 24 2024 20:00:58 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.