Editor: support line ending

This commit is contained in:
Le Tan 2021-08-28 07:45:10 +08:00
parent ed8cd503b5
commit 0d8bb7eebd
12 changed files with 138 additions and 10 deletions

@ -1 +1 @@
Subproject commit 59e53f2cdc2f5a4b9dc44cbf28c483cca07559ba Subproject commit 0733259fed01ecaa11678fac00fd67397ff7c39c

View File

@ -95,6 +95,11 @@ void EditorConfig::loadCore(const QJsonObject &p_app, const QJsonObject &p_user)
if (m_spellCheckDefaultDictionary.isEmpty()) { if (m_spellCheckDefaultDictionary.isEmpty()) {
m_spellCheckDefaultDictionary = QStringLiteral("en_US"); m_spellCheckDefaultDictionary = QStringLiteral("en_US");
} }
{
auto lineEnding = READSTR(QStringLiteral("line_ending"));
m_lineEnding = stringToLineEndingPolicy(lineEnding);
}
} }
QJsonObject EditorConfig::saveCore() const QJsonObject EditorConfig::saveCore() const
@ -107,6 +112,7 @@ QJsonObject EditorConfig::saveCore() const
obj[QStringLiteral("shortcuts")] = saveShortcuts(); obj[QStringLiteral("shortcuts")] = saveShortcuts();
obj[QStringLiteral("spell_check_auto_detect_language")] = m_spellCheckAutoDetectLanguageEnabled; obj[QStringLiteral("spell_check_auto_detect_language")] = m_spellCheckAutoDetectLanguageEnabled;
obj[QStringLiteral("spell_check_default_dictionary")] = m_spellCheckDefaultDictionary; obj[QStringLiteral("spell_check_default_dictionary")] = m_spellCheckDefaultDictionary;
obj[QStringLiteral("line_ending")] = lineEndingPolicyToString(m_lineEnding);
return obj; return obj;
} }
@ -211,6 +217,44 @@ EditorConfig::AutoSavePolicy EditorConfig::stringToAutoSavePolicy(const QString
} }
} }
QString EditorConfig::lineEndingPolicyToString(LineEndingPolicy p_ending) const
{
switch (p_ending) {
case LineEndingPolicy::Platform:
return QStringLiteral("platform");
case LineEndingPolicy::File:
return QStringLiteral("file");
case LineEndingPolicy::LF:
return QStringLiteral("lf");
case LineEndingPolicy::CRLF:
return QStringLiteral("crlf");
case LineEndingPolicy::CR:
return QStringLiteral("cr");
}
return QStringLiteral("platform");
}
LineEndingPolicy EditorConfig::stringToLineEndingPolicy(const QString &p_str) const
{
auto ending = p_str.toLower();
if (ending == QStringLiteral("file")) {
return LineEndingPolicy::File;
} else if (ending == QStringLiteral("lf")) {
return LineEndingPolicy::LF;
} else if (ending == QStringLiteral("crlf")) {
return LineEndingPolicy::CRLF;
} else if (ending == QStringLiteral("cr")) {
return LineEndingPolicy::CR;
} else {
return LineEndingPolicy::Platform;
}
}
EditorConfig::AutoSavePolicy EditorConfig::getAutoSavePolicy() const EditorConfig::AutoSavePolicy EditorConfig::getAutoSavePolicy() const
{ {
return m_autoSavePolicy; return m_autoSavePolicy;
@ -221,6 +265,16 @@ void EditorConfig::setAutoSavePolicy(EditorConfig::AutoSavePolicy p_policy)
updateConfig(m_autoSavePolicy, p_policy, this); updateConfig(m_autoSavePolicy, p_policy, this);
} }
LineEndingPolicy EditorConfig::getLineEndingPolicy() const
{
return m_lineEnding;
}
void EditorConfig::setLineEndingPolicy(LineEndingPolicy p_ending)
{
updateConfig(m_lineEnding, p_ending, this);
}
const QString &EditorConfig::getBackupFileDirectory() const const QString &EditorConfig::getBackupFileDirectory() const
{ {
return m_backupFileDirectory; return m_backupFileDirectory;

View File

@ -8,6 +8,8 @@
#include <QObject> #include <QObject>
#include <QVector> #include <QVector>
#include "global.h"
namespace vte namespace vte
{ {
class ViConfig; class ViConfig;
@ -127,6 +129,9 @@ namespace vnotex
const QSharedPointer<vte::ViConfig> &getViConfig() const; const QSharedPointer<vte::ViConfig> &getViConfig() const;
LineEndingPolicy getLineEndingPolicy() const;
void setLineEndingPolicy(LineEndingPolicy p_ending);
private: private:
friend class MainConfig; friend class MainConfig;
@ -141,6 +146,9 @@ namespace vnotex
QString autoSavePolicyToString(AutoSavePolicy p_policy) const; QString autoSavePolicyToString(AutoSavePolicy p_policy) const;
AutoSavePolicy stringToAutoSavePolicy(const QString &p_str) const; AutoSavePolicy stringToAutoSavePolicy(const QString &p_str) const;
QString lineEndingPolicyToString(LineEndingPolicy p_ending) const;
LineEndingPolicy stringToLineEndingPolicy(const QString &p_str) const;
void loadImageHost(const QJsonObject &p_app, const QJsonObject &p_user); void loadImageHost(const QJsonObject &p_app, const QJsonObject &p_user);
QJsonObject saveImageHost() const; QJsonObject saveImageHost() const;
@ -174,6 +182,8 @@ namespace vnotex
bool m_clearObsoleteImageAtImageHost = false; bool m_clearObsoleteImageAtImageHost = false;
QSharedPointer<vte::ViConfig> m_viConfig; QSharedPointer<vte::ViConfig> m_viConfig;
LineEndingPolicy m_lineEnding = LineEndingPolicy::LF;
}; };
} }

View File

@ -133,6 +133,14 @@ namespace vnotex
int m_length = -1; int m_length = -1;
}; };
enum class LineEndingPolicy
{
Platform,
File,
LF,
CRLF,
CR
};
} // ns vnotex } // ns vnotex
Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::FindOptions); Q_DECLARE_OPERATORS_FOR_FLAGS(vnotex::FindOptions);

View File

@ -145,8 +145,8 @@ void HistoryMgr::add(const QString &p_path,
file.m_mode = p_mode; file.m_mode = p_mode;
file.m_readOnly = p_readOnly; file.m_readOnly = p_readOnly;
if (m_lastClosedFiles.size() > 100) { if (m_lastClosedFiles.size() > s_maxHistoryCount) {
m_lastClosedFiles.remove(0, m_lastClosedFiles.size() - 100); m_lastClosedFiles.remove(0, m_lastClosedFiles.size() - s_maxHistoryCount);
} }
} }

View File

@ -119,7 +119,9 @@
"ApplySnippet" : "Ctrl+G, I" "ApplySnippet" : "Ctrl+G, I"
}, },
"spell_check_auto_detect_language" : false, "spell_check_auto_detect_language" : false,
"spell_check_default_dictionary" : "en_US" "spell_check_default_dictionary" : "en_US",
"//comment" : "platform/file/lf/crlf/cr",
"line_ending" : "lf"
}, },
"text_editor" : { "text_editor" : {
"theme" : "", "theme" : "",

View File

@ -6,7 +6,9 @@
#include <QTemporaryFile> #include <QTemporaryFile>
#include <QJsonDocument> #include <QJsonDocument>
#include "../core/exception.h" #include <core/exception.h>
#include <core/global.h>
#include "pathutils.h" #include "pathutils.h"
using namespace vnotex; using namespace vnotex;
@ -25,11 +27,12 @@ QByteArray FileUtils::readFile(const QString &p_filePath)
QString FileUtils::readTextFile(const QString &p_filePath) QString FileUtils::readTextFile(const QString &p_filePath)
{ {
QFile file(p_filePath); QFile file(p_filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { if (!file.open(QIODevice::ReadOnly)) {
Exception::throwOne(Exception::Type::FailToReadFile, Exception::throwOne(Exception::Type::FailToReadFile,
QString("failed to read file: %1").arg(p_filePath)); QString("failed to read file: %1").arg(p_filePath));
} }
// TODO: determine the encoding of the text.
QString text(file.readAll()); QString text(file.readAll());
file.close(); file.close();
return text; return text;
@ -55,7 +58,7 @@ void FileUtils::writeFile(const QString &p_filePath, const QByteArray &p_data)
void FileUtils::writeFile(const QString &p_filePath, const QString &p_text) void FileUtils::writeFile(const QString &p_filePath, const QString &p_text)
{ {
QFile file(p_filePath); QFile file(p_filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { if (!file.open(QIODevice::WriteOnly)) {
Exception::throwOne(Exception::Type::FailToWriteFile, Exception::throwOne(Exception::Type::FailToWriteFile,
QString("failed to write to file: %1").arg(p_filePath)); QString("failed to write to file: %1").arg(p_filePath));
} }

View File

@ -42,6 +42,23 @@ void EditorPage::setupUI()
this, &EditorPage::pageIsChanged); this, &EditorPage::pageIsChanged);
} }
{
m_lineEndingComboBox = WidgetsFactory::createComboBox(this);
m_lineEndingComboBox->setToolTip(tr("Line ending"));
m_lineEndingComboBox->addItem(tr("Follow Platform"), (int)LineEndingPolicy::Platform);
m_lineEndingComboBox->addItem(tr("Follow File"), (int)LineEndingPolicy::File);
m_lineEndingComboBox->addItem(tr("LF (Linux/macOS)"), (int)LineEndingPolicy::LF);
m_lineEndingComboBox->addItem(tr("CR LF (Windows)"), (int)LineEndingPolicy::CRLF);
m_lineEndingComboBox->addItem(tr("CR"), (int)LineEndingPolicy::CR);
const QString label(tr("Line ending:"));
mainLayout->addRow(label, m_lineEndingComboBox);
addSearchItem(label, m_lineEndingComboBox->toolTip(), m_lineEndingComboBox);
connect(m_lineEndingComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &EditorPage::pageIsChanged);
}
{ {
m_toolBarIconSizeSpinBox = WidgetsFactory::createSpinBox(this); m_toolBarIconSizeSpinBox = WidgetsFactory::createSpinBox(this);
m_toolBarIconSizeSpinBox->setToolTip(tr("Icon size of the editor tool bar")); m_toolBarIconSizeSpinBox->setToolTip(tr("Icon size of the editor tool bar"));
@ -105,6 +122,12 @@ void EditorPage::loadInternal()
m_autoSavePolicyComboBox->setCurrentIndex(idx); m_autoSavePolicyComboBox->setCurrentIndex(idx);
} }
{
int idx = m_lineEndingComboBox->findData(static_cast<int>(editorConfig.getLineEndingPolicy()));
Q_ASSERT(idx != -1);
m_lineEndingComboBox->setCurrentIndex(idx);
}
m_toolBarIconSizeSpinBox->setValue(editorConfig.getToolBarIconSize()); m_toolBarIconSizeSpinBox->setValue(editorConfig.getToolBarIconSize());
{ {
@ -122,6 +145,11 @@ bool EditorPage::saveInternal()
editorConfig.setAutoSavePolicy(static_cast<EditorConfig::AutoSavePolicy>(policy)); editorConfig.setAutoSavePolicy(static_cast<EditorConfig::AutoSavePolicy>(policy));
} }
{
auto ending = m_lineEndingComboBox->currentData().toInt();
editorConfig.setLineEndingPolicy(static_cast<LineEndingPolicy>(ending));
}
editorConfig.setToolBarIconSize(m_toolBarIconSizeSpinBox->value()); editorConfig.setToolBarIconSize(m_toolBarIconSizeSpinBox->value());
{ {

View File

@ -32,6 +32,8 @@ namespace vnotex
QSpinBox *m_toolBarIconSizeSpinBox = nullptr; QSpinBox *m_toolBarIconSizeSpinBox = nullptr;
QComboBox *m_spellCheckDictComboBox = nullptr; QComboBox *m_spellCheckDictComboBox = nullptr;
QComboBox *m_lineEndingComboBox = nullptr;
}; };
} }

View File

@ -863,7 +863,8 @@ QSharedPointer<vte::MarkdownEditorConfig> MarkdownViewWindow::createMarkdownEdit
auto textEditorConfig = TextViewWindowHelper::createTextEditorConfig(p_config.getTextEditorConfig(), auto textEditorConfig = TextViewWindowHelper::createTextEditorConfig(p_config.getTextEditorConfig(),
p_editorConfig.getViConfig(), p_editorConfig.getViConfig(),
themeMgr.getFile(Theme::File::MarkdownEditorStyle), themeMgr.getFile(Theme::File::MarkdownEditorStyle),
themeMgr.getMarkdownEditorHighlightTheme()); themeMgr.getMarkdownEditorHighlightTheme(),
p_editorConfig.getLineEndingPolicy());
auto editorConfig = QSharedPointer<vte::MarkdownEditorConfig>::create(textEditorConfig); auto editorConfig = QSharedPointer<vte::MarkdownEditorConfig>::create(textEditorConfig);
editorConfig->overrideTextFontFamily(p_config.getEditorOverriddenFontFamily()); editorConfig->overrideTextFontFamily(p_config.getEditorOverriddenFontFamily());

View File

@ -176,7 +176,8 @@ QSharedPointer<vte::TextEditorConfig> TextViewWindow::createTextEditorConfig(con
auto config = TextViewWindowHelper::createTextEditorConfig(p_config, auto config = TextViewWindowHelper::createTextEditorConfig(p_config,
p_editorConfig.getViConfig(), p_editorConfig.getViConfig(),
themeMgr.getFile(Theme::File::TextEditorStyle), themeMgr.getFile(Theme::File::TextEditorStyle),
themeMgr.getEditorHighlightTheme()); themeMgr.getEditorHighlightTheme(),
p_editorConfig.getLineEndingPolicy());
return config; return config;
} }

View File

@ -66,7 +66,8 @@ namespace vnotex
static QSharedPointer<vte::TextEditorConfig> createTextEditorConfig(const TextEditorConfig &p_config, static QSharedPointer<vte::TextEditorConfig> createTextEditorConfig(const TextEditorConfig &p_config,
const QSharedPointer<vte::ViConfig> &p_viConfig, const QSharedPointer<vte::ViConfig> &p_viConfig,
const QString &p_themeFile, const QString &p_themeFile,
const QString &p_syntaxTheme) const QString &p_syntaxTheme,
LineEndingPolicy p_lineEndingPolicy)
{ {
auto editorConfig = QSharedPointer<vte::TextEditorConfig>::create(); auto editorConfig = QSharedPointer<vte::TextEditorConfig>::create();
@ -141,6 +142,24 @@ namespace vnotex
editorConfig->m_expandTab = p_config.getExpandTabEnabled(); editorConfig->m_expandTab = p_config.getExpandTabEnabled();
editorConfig->m_tabStopWidth = p_config.getTabStopWidth(); editorConfig->m_tabStopWidth = p_config.getTabStopWidth();
switch (p_lineEndingPolicy) {
case LineEndingPolicy::Platform:
editorConfig->m_lineEndingPolicy = vte::LineEndingPolicy::Platform;
break;
case LineEndingPolicy::File:
editorConfig->m_lineEndingPolicy = vte::LineEndingPolicy::File;
break;
case LineEndingPolicy::LF:
editorConfig->m_lineEndingPolicy = vte::LineEndingPolicy::LF;
break;
case LineEndingPolicy::CRLF:
editorConfig->m_lineEndingPolicy = vte::LineEndingPolicy::CRLF;
break;
case LineEndingPolicy::CR:
editorConfig->m_lineEndingPolicy = vte::LineEndingPolicy::CR;
break;
}
return editorConfig; return editorConfig;
} }