写作天下
简介
为作家们创造世界而诞生,执云作笔,诉尽平生意。
集简约UI与人性化AI于一体的码字工具,无论是小说、作文、日记、报告,都能轻松驾驭。
QQ交流群:705849222
特点
已有功能:
自由的目录:自动序号,导入导出
一体化界面:全局自定义主题
输入动画:独创文字平滑输入效果、光标平滑移动
智能引号:增删移动全在一键之间
智能空格:缩进、标点、移动光标融为一体
智能回车:双引号内回车、自动添加句末标点、自动缩进
自动标点:语气词后面自动加上标点符号
同音词覆盖:选词错误,无需删除,直接覆盖旧内容
自动分段:换行/排版时,过长段落自动在合适的地方分段
自动提示:输入时自动提示同义词、相关词、常用句
随机取名:最轻便的取名方式,要啥来啥
一键排版:全自动
未来功能(近期繁忙,无力开发):
大纲列表
章节细纲
名片注释
名字高亮
综合搜索
全书替换
右下角通知卡片
自定义主题
自定义快捷键
小黑屋
云同步
排行榜
拼字房间
章节分享
“求评价”广场
主角背包
快捷键
ctrl + ←/→ 按词语移动
alt + ←/→ 按句子移动
ctrl + alt + ←/→ 按段落移动
ctrl + shift + ↑/↓ 扩大/缩小选择
ctrl/alt + ↑/↓ 屏幕滚动,alt更快
空格键 智能空格
引号键 智能引号
回车键 智能回车
Tab键 句子补全+光标跳过
ctrl+T 一键排版
ctrl+D 句内同音词替换(不必连续)
ctrl+F 章内文字搜索
ctrl+P 全局综合搜索
更多快捷键请等待后期加入(或将支持自定义快捷键)
技术特点
开发环境:C++/Qt5.11.3,Qt Creator
运行环境:Windows、Android
1、标点AI
虽然是简单暴力的枚举(都是自己遇到的),但是有特判了上千种情况,也不容易吧……
若是人物语言描写,还能根据人物的表情动作神态来分析情感程度,进一步提高准确度。
手动判断,故覆盖不全,不过在一定情况下,枚举简单易用,是为上上之选!
还有各种常用按键的自动化操作,极大程度上增加效率!
/**
* 小说语气识别的AI类
*/
class NovelAIBase
{
/*...略了一些方法...*/
void operatorSmartSpace(); // 智能空格:按下空格触发
void operatorSmartEnter(); // 智能回车:按下回车触发
void operatorSmartQuotes(); // 智能引号:按下引号触发
void operatorSmartBackspace(); // 智能删除,按下删除触发
bool operatorAutoPunc(); // 自动标点:语气词自动触发
bool operatorSentFinish(); // 句末标点:增加或转化成结尾
void operatorSmartQuotes2(int left, int right); // 智能引号,仅在选中文本的情况下调用
virtual int getWordCount(QString str); // 字数统计,交给 NovelAI
QString getPunc(QString para/*段落*/, int pos/*光标*/); // ☆核心:取标点(句子)
QString getPunc(/*QString fullText, int pos*/); // 这个是全部文本中的某一部分
QString getPunc(int pos); // 全部文本,特定位置的标点
QString getPunc2(int pos); // 把","改成"。"
QString getPunc2(); // 把","改成"。"
int getDescTone(QString sent); // 句子语气标点,影响语气导向
QString getTalkTone(QString sent, QString sent2, int tone, QString left1, QString left2);
void updateCursorChars(); // 修改光标附近的字符
bool canDeletePairPunc(); // 是否能够删除成对文本(能删就删)
bool isCursorInQuote(QString text, int pos); // 是否在引号里面
virtual void moveCursor(int x) = 0; // 移动光标
virtual void insertText(int pos, QString text) = 0; // 插入文本
virtual void insertText(QString text) = 0; // 插入文本
virtual void deleteText(int start, int end) = 0; // 删除文本
// bool isNextLang(); // 是否是后一句话(双引号前面多的是逗号)
bool isSentPunc(QString str); // 是否为句末标点(不包含引号和特殊字符,不包括逗号)
bool isSentSplitPunc(QString str); // 是否为句子分割标点(包含逗号)
bool isSentSplit(QString str); // 是否为句子分割符(各类标点,包括逗号)
bool isASCIIPunc(QString str); // 是否为英文标点(不包含引号和特殊字符)
bool isBlankChar(QString str); // 是否为空白符
bool isBlankChar2(QString str); // 是否为换行之外的空白符
bool isBlankString(QString str); // 是否为空白字符串
bool isSymPairLeft(QString str); // 是否为对称标点左边的
bool isSymPairRight(QString str); // 是否为对称标点右边的
QString getSymPairLeftByRight(QString str); // 根据右边括号获取左边的括号
QString getSymPairRightByLeft(QString str); // 根据右边括号获取左边的括号
QString getCursorFrontSent(); // 获取当前面的句子
QString getCurrentChar(int x); // 获取当前位置的附近汉字
bool isQuoteColon(QString str); // 汉字后面是否需要加标点
protected:
QString _text, _pre_text; // 文本
int _pos, _pre_pos, _dif; // 光标位置和字数差
QString _left1, _left2, _left3, _right1, _right2; // 光标附近的文本
bool isInQuotes; // 是否在引号里面(用来判断是否为语言或者描述)
private:
QString _shuo_blacklists, _dao_whitelists, _wen_blacklists; // “说”黑名单、“道”白名单、“问”黑名单
QString _symbol_pair_lefts, _symbol_pair_rights; // 成对符号左边/右边
QString _quote_no_colon, _quantifiers; // 引号前面没有冒号
QString _sent_puncs, _sent_split, _sent_split_puncs, _blank_chars; // 句末标点、句子分割符、空白符
QString _auto_punc_whitelists; // 自动标点白名单
};
子类为NovelAI,再下一个子类 NovelEditor 使用到了多继承,同时继承 QTextEdit 与 NovelAI。
其实设计得不是很好,AI 类需要大量调用 Edit 的方法,于是加了许多虚函数,将三个类紧紧耦合到一起(不过关系不大,本来就是怕一个文件代码太长而分开的)。
2、仿IDE思路
当今所谓的写作软件,单论写作方面,其实和一个记事本没多少差别,无非多了目录与自动缩进,以及简单的自动保存等。其一些亮点,比如强制写作的小黑屋、多人竞争的在线拼字,都无法从“码字”本身来帮助作者达到更高效的办公,这些附加的功能甚至会让作者分心,无法好好静心创作。
写作天下定位一款单纯的“文学创作”编辑器,主打从“写作”本身提高效率,弱化与文字无关的功能。或许后期将会添加小黑屋、拼字等,但绝不会将这些作为主要功能。
备注:近期繁忙,无力开发,所以只是“思路”!
一些功能:
增强的编辑功能
自动提示
面向对象写作:名片系统
文字高亮(名片高亮)
高度个性化设置(功能细节、快捷键、主题等)
追求自动的编辑器
一句话:能自动的,绝不手动!
为了实现更加人性化的功能,程序中使用了大量的算法。
比如括号匹配功能,输入左括号时自动添加右括号、删除键删除成对的符号,这里使用数据结构中的栈,判断光标前后各自左右括号的数量,入栈出栈,来判断是否需要添加/删除,而不仅仅依靠光标前一个字符。
还有光标移动、在标点前面换行、在语言描写内回车自动插入前后引号、修改引号前面的逗号与冒号等,一个按键,多种功能。
轻松提示
经过多种方案的性能测试,选取了速度最快、运行最稳定的方式。
以下为输入文字后自动提示算法:
/**
* 某个句子的某个位置处进行搜索
* @param sent 欲搜索的完整句子(短句,不包含标点)
* @param cursor 光标在句子中的相对位置
* @return 是否找到
*/
bool Lexicons::surroundSearch(QString sent, int cursor)
{
int len = sent.length();