Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使QSCINTILA像SublimateText一样自动缩进?_Python_C++_Pyqt5_Sublimetext_Qscintilla - Fatal编程技术网

Python 如何使QSCINTILA像SublimateText一样自动缩进?

Python 如何使QSCINTILA像SublimateText一样自动缩进?,python,c++,pyqt5,sublimetext,qscintilla,Python,C++,Pyqt5,Sublimetext,Qscintilla,考虑以下mcve: import sys import textwrap from PyQt5.Qsci import QsciScintilla from PyQt5.Qt import * if __name__ == '__main__': app = QApplication(sys.argv) view = QsciScintilla() view.SendScintilla(view.SCI_SETMULTIPLESELECTION, True)

考虑以下mcve:

import sys
import textwrap

from PyQt5.Qsci import QsciScintilla
from PyQt5.Qt import *


if __name__ == '__main__':

    app = QApplication(sys.argv)
    view = QsciScintilla()

    view.SendScintilla(view.SCI_SETMULTIPLESELECTION, True)
    view.SendScintilla(view.SCI_SETMULTIPASTE, 1)
    view.SendScintilla(view.SCI_SETADDITIONALSELECTIONTYPING, True)

    view.setAutoIndent(True)
    view.setTabWidth(4)
    view.setIndentationGuides(True)
    view.setIndentationsUseTabs(False)
    view.setBackspaceUnindents(True)

    view.setText(textwrap.dedent("""\
        def foo(a,b):
            print('hello')
    """))

    view.show()
    app.exec_()
当与诸如或之类的编辑器进行比较时,上面代码段的自动缩进行为非常糟糕。首先,让我们看看SublimateText中的自动缩进功能在单个或多个选择中的表现有多好

现在让我们看看自动缩进是如何与上述代码片段一起工作的:

与SublimateText相比,当使用单/多选择启用自动缩进时,QSCINTILA的工作方式是软硬的,非常糟糕/不可用

使小部件更像SublimiteText/Codemirror的第一步是断开导致自动缩进行为不好的当前插槽,我们可以通过执行以下操作来实现:

print(view.receivers(view.SCN_CHARADDED))
view.SCN_CHARADDED.disconnect()
print(view.receivers(view.SCN_CHARADDED))
此时,您已经准备好连接
SCN\u CHARADDED
,您的自定义插槽正在发挥所有的魔力:)

问题:您将如何修改上述代码段,以便保留所有选择,并且自动缩进的行为与SublimitText、Codemirror或任何严肃的文本编辑器完全相同

参考文献:

  • ,下面您可以看到我们使用
    disconnect
    断开的专用插槽的外观:

QSCISCINTILA.h

qsciscintilla.cpp


<强>重要:我决定发布相关的C++位,这样你就可以得到更多关于缩进如何实现内部的背景,从而给出关于可能替换的更多线索…这个线程的目标是试图找到一个纯python解决方案。我希望避免修改QSCINTILA源代码(如果可能的话),这样维护/升级将尽可能简单,QSCINTILA dep仍然可以被视为一个黑匣子。

看起来您必须编写自己的版本,安装一章中已经提到了最重要的一点:

提供的QSCINTILA将作为共享库/DLL构建,并安装在与Qt库相同的目录中,包括文件

如果希望构建库的静态版本,请在qmake命令行上传递CONFIG+=staticlib

如果要对配置进行更重要的更改,请编辑Qt4Qt5目录中的文件QSCINTILA.pro

如果确实进行了更改,特别是更改了安装目录的名称或库的名称,则可能还需要更新Qt4Qt5/features/qscintra2.prf文件*


这里还解释了进一步的步骤。

qscintula
中没有使自动缩进工作的集成方法(尤其是在
sublimitext
中)。这种行为是特定于语言和用户的。本机文档包括如何触发自动缩进的示例。很抱歉,它是用C.写的。我还没有发现它是用Python编写的

下面是一个代码(我知道qscintula是Qt的一个端口,这个面向闪烁体的代码也应该与qscintula一起工作,或者最坏的情况下,您可以将其改编为C++):


希望这有帮助。

这是一个
C++
问题,也是一个
Python
问题,也许添加
C++
标记会有所帮助。@LogicalBranch嗯,你说得对。。。问题是,我想首先知道是否有一个纯python解决方案可以解决给定的问题。为什么?嗯,现在我们决定修改内部版本(由riverbank所有),我们将无法再通过pypi轻松升级版本。。。而且,为所有主要平台重新编译也不是那么简单。我之所以发布内部C++位,是为了向潜在的贡献者提供相关信息。这有意义吗?作为python解决方案,您需要一个观察者,不知道您是否能够以某种方式将其挂钩。另一个解决方案是QSCINTILA的makro——只是头脑风暴,这是一个有趣的问题。我知道这有点骇人听闻,但由于您使用多个游标,当选择多个游标时,您不能将游标的位置/位置存储在临时变量中吗?然后,当插入空白字符时,将光标恢复到其原始位置,让用户在这些位置继续键入。嘿,伙计们,我一直在玩,它工作得很好,这个编辑器基于闪烁。。。对于那些不知道的人,Qscintula也在窗帘后面使用闪烁体。尽管记事本++不支持多重选择(至少在默认情况下是如此)。。。不管怎样,你正在做的头脑风暴很酷,继续吧。。。不确定是否有某种方法可以断开私人插槽的连接,并以某种黑客方式钩住我们自己的功能:/…嗨,首先,感谢您的尝试,不确定我是否有足够的时间在赏金到期之前测试该代码。。。但是让我问你,如果我能够将它移植到python中,自动缩进的行为会像升华文本一样(即使在处理多个选择时)?另外,您在回答中说,没有一种完整的方法来进行自动缩进,请确保您再次阅读我的问题,以了解发生了什么,因为我的全部观点是,设置自动缩进不会像升华一样。在任何情况下,该代码在哪里使用(我可以使用任何windows exe吗?)我的同事说这是一个闪烁的代码,他在windows中测试了它。老实说,我不是百分之百确定它是否适用于多种选择。但我的同事说是的。
class QSCINTILLA_EXPORT QsciScintilla : public QsciScintillaBase
{
    Q_OBJECT

public:
    ...
    private slots:
        void handleCharAdded(int charadded);
    ...
    private:
        void autoIndentation(char ch, long pos);
connect(this,SIGNAL(SCN_CHARADDED(int)),
         SLOT(handleCharAdded(int)));

...

// Handle the addition of a character.
void QsciScintilla::handleCharAdded(int ch)
{
    // Ignore if there is a selection.
    long pos = SendScintilla(SCI_GETSELECTIONSTART);

    if (pos != SendScintilla(SCI_GETSELECTIONEND) || pos == 0)
        return;

    // If auto-completion is already active then see if this character is a
    // start character.  If it is then create a new list which will be a subset
    // of the current one.  The case where it isn't a start character seems to
    // be handled correctly elsewhere.
    if (isListActive() && isStartChar(ch))
    {
        cancelList();
        startAutoCompletion(acSource, false, use_single == AcusAlways);

        return;
    }

    // Handle call tips.
    if (call_tips_style != CallTipsNone && !lex.isNull() && strchr("(),", ch) != NULL)
        callTip();

    // Handle auto-indentation.
    if (autoInd)
    {
        if (lex.isNull() || (lex->autoIndentStyle() & AiMaintain))
            maintainIndentation(ch, pos);
        else
            autoIndentation(ch, pos);
    }

    // See if we might want to start auto-completion.
    if (!isCallTipActive() && acSource != AcsNone)
    {
        if (isStartChar(ch))
            startAutoCompletion(acSource, false, use_single == AcusAlways);
        else if (acThresh >= 1 && isWordCharacter(ch))
            startAutoCompletion(acSource, true, use_single == AcusAlways);
    }
}
private void Scintilla_InsertCheck(object sender, InsertCheckEventArgs e) {

    if ((e.Text.EndsWith("" + Constants.vbCr) || e.Text.EndsWith("" + Constants.vbLf))) {
        int startPos = Scintilla.Lines(Scintilla.LineFromPosition(Scintilla.CurrentPosition)).Position;
        int endPos = e.Position;
        string curLineText = Scintilla.GetTextRange(startPos, (endPos - startPos)); 
        // Text until the caret so that the whitespace is always
        // equal in every line.

        Match indent = Regex.Match(curLineText, "^[ \\t]*");
        e.Text = (e.Text + indent.Value);
        if (Regex.IsMatch(curLineText, "{\\s*$")) {
            e.Text = (e.Text + Constants.vbTab);
        }
    }
}

private void Scintilla_CharAdded(object sender, CharAddedEventArgs e) {

    //The '}' char.
    if (e.Char == 125) {
        int curLine = Scintilla.LineFromPosition(Scintilla.CurrentPosition);

        if (Scintilla.Lines(curLine).Text.Trim() == "}") { 
        //Check whether the bracket is the only thing on the line. 
        //For cases like "if() { }".
            SetIndent(Scintilla, curLine, GetIndent(Scintilla, curLine) - 4);
        }
    }
}

//Codes for the handling the Indention of the lines.
//They are manually added here until they get officially 
//added to the Scintilla control.

#region "CodeIndent Handlers"
    const int SCI_SETLINEINDENTATION = 2126;
    const int SCI_GETLINEINDENTATION = 2127;
    private void SetIndent(ScintillaNET.Scintilla scin, int line, int indent) {
        scin.DirectMessage(SCI_SETLINEINDENTATION, new IntPtr(line), new IntPtr(indent));
    }
    private int GetIndent(ScintillaNET.Scintilla scin, int line) {
        return (scin.DirectMessage(SCI_GETLINEINDENTATION, new IntPtr(line), null).ToInt32);
    }
#endregion