Skip to content

Commit

Permalink
Merge pull request #52 from fukatani/extract
Browse files Browse the repository at this point in the history
Suppoet Extract feature
  • Loading branch information
fukatani authored Apr 5, 2020
2 parents 733d1d5 + 2b4a46a commit f0dac96
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 36 deletions.
12 changes: 5 additions & 7 deletions rujaion/command/finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ def keyPressEvent(self, e: QtGui.QKeyEvent) -> None:
class Find(QtWidgets.QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.parent = parent
self.lastMatch = None
self.initUI()

Expand Down Expand Up @@ -102,7 +101,7 @@ def toggle_focus(self):

def find(self):
# Grab the parent's text
text = self.parent.toPlainText()
text = self.parent().toPlainText()

# And the text to find
query = self.findField.toPlainText()
Expand Down Expand Up @@ -130,14 +129,13 @@ def findAndReplace(self):
self.replace()

def replace(self):
cursor = self.parent.textCursor()
cursor = self.parent().textCursor()

if self.lastMatch and cursor.hasSelection():
cursor.insertText(self.replaceField.toPlainText())
self.parent.setTextCursor(cursor)
self.parent().setTextCursor(cursor)

def replaceAll(self):
self.moveCursor(0, 0)
# Initial find() call so that lastMatch is
# potentially not None anymore
self.find()
Expand All @@ -163,7 +161,7 @@ def normalMode(self):
def moveCursor(self, start, end):

# We retrieve the QTextCursor object from the parent's QTextEdit
cursor = self.parent.textCursor()
cursor = self.parent().textCursor()

# Then we set the position to the beginning of the last match
cursor.setPosition(start)
Expand All @@ -175,4 +173,4 @@ def moveCursor(self, start, end):
)

# And finally we set this new cursor as the parent's
self.parent.setTextCursor(cursor)
self.parent().setTextCursor(cursor)
61 changes: 32 additions & 29 deletions rujaion/editor.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import codecs
from collections import defaultdict
import os
import re
import string
import subprocess
from typing import *
Expand All @@ -13,6 +12,7 @@

from rujaion import completer
from rujaion.command import finder
from rujaion.extract import ExtractDialog
from rujaion import syntax
from rujaion import util

Expand Down Expand Up @@ -50,16 +50,6 @@
"""


def sort_by_levenshtein(center: str, words: Iterable[str], limit: int = 2) -> List[str]:
cands = []
for word in words:
m = StringMatcher.StringMatcher(seq1=center, seq2=word)
dist = m.distance()
if dist <= limit:
cands.append(word)
return cands


CHARS = set(string.ascii_letters + string.digits + "_")


Expand Down Expand Up @@ -108,6 +98,7 @@ def _addCustomMenuItems(self, menu: QtWidgets.QMenu):
and "\u2029" not in self.textCursor().selectedText()
):
menu.addAction(u"Add to watches", self.add_to_watch)
menu.addAction(u"Extract", self.extract)

def add_to_watch(self):
var = self.textCursor().selectedText()
Expand All @@ -116,6 +107,9 @@ def add_to_watch(self):
def find(self):
finder.Find(self).show()

def extract(self):
ExtractDialog(self, sentence=self.textCursor().selectedText()).show()

def default_file_name(self) -> str:
if self.lang == "c++":
return "test1.cpp"
Expand Down Expand Up @@ -396,9 +390,6 @@ def levenshteinize(self):
center = self.textCursor().selectedText()
if center:
self.highlighter.update_levenshtein([center])
# words = set(re.findall(r"\b[a-zA-Z_]+[a-zA-Z1-9_]\b", self.toPlainText(), re.S))
# words = sort_by_levenshtein(center, words, 1)
# self.highlighter.update_levenshtein(words)
else:
self.highlighter.levensteign_rules.clear()
self.highlighter.rehighlight()
Expand Down Expand Up @@ -512,6 +503,9 @@ def keyPressEvent(self, event: QtGui.QKeyEvent):
self.go_to_first_error()
return

if event.key() == QtCore.Qt.Key_E and event.modifiers() == QtCore.Qt.ControlModifier:
self.extract()

super().keyPressEvent(event)

if event.key() == Qt.Key_Home:
Expand Down Expand Up @@ -558,6 +552,26 @@ def remove_whole_line(self):
cursor.removeSelectedText()
cursor.deletePreviousChar()

def clear_and_write_text(self, text: str):
cursor = self.textCursor()
cursor.movePosition(QtGui.QTextCursor.Start)
cursor.movePosition(QtGui.QTextCursor.End, QtGui.QTextCursor.KeepAnchor,1)
cursor.removeSelectedText()
self.insertPlainText(text)

def save_position(self):
cursor = self.textCursor()
line_num = cursor.blockNumber()
char_num = cursor.columnNumber()
scroll_value = self.verticalScrollBar().value()
return line_num, char_num, scroll_value

def load_position(self, line_num, char_num, scroll_value):
cursor = QtGui.QTextCursor(self.document().findBlockByLineNumber(line_num))
cursor.movePosition(QtGui.QTextCursor.NextCharacter, QtGui.QTextCursor.MoveAnchor, char_num)
self.setTextCursor(cursor)
self.verticalScrollBar().setValue(scroll_value)

def save_pre_process(self):
# Get formatted Text
temp_file_name = util.get_temp_file(self.lang)
Expand All @@ -566,27 +580,16 @@ def save_pre_process(self):
if not util.exec_format(self.lang):
return
temp_file = codecs.open(temp_file_name, "r", "utf-8")
all_text = "".join([line for line in temp_file.readlines()])
formatted_text = "".join([line for line in temp_file.readlines()])
temp_file.close()

# Save cursor and scroll bar status
cursor = self.textCursor()
line_num = cursor.blockNumber()
char_num = cursor.columnNumber()
scroll_value = self.verticalScrollBar().value()
pos = self.save_position()

# Clear all Text and insert format result
cursor.movePosition(QtGui.QTextCursor.Start)
cursor.movePosition(QtGui.QTextCursor.End, QtGui.QTextCursor.KeepAnchor, 1)
cursor.removeSelectedText()
self.insertPlainText(all_text)
self.clear_and_write_text(formatted_text)

# recover cursor and scroll bar status
cursor = QtGui.QTextCursor(self.document().findBlockByLineNumber(line_num))
cursor.movePosition(
QtGui.QTextCursor.NextCharacter, QtGui.QTextCursor.MoveAnchor, char_num
)
self.setTextCursor(cursor)
self.verticalScrollBar().setValue(scroll_value)
self.load_position(*pos)
self.edited = False
self.repaint()
82 changes: 82 additions & 0 deletions rujaion/extract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from PyQt5 import QtWidgets, QtGui

from rujaion import util


class ExtractDialog(QtWidgets.QDialog):
def __init__(self, *args, sentence: str):
super().__init__(*args)
self.sentence_edit = util.StateLessTextEdit(sentence, self)
self.name_edit = util.StateLessTextEdit("", self)

self.extract_kind_box = QtWidgets.QGroupBox("Extract kind")
vbox = QtWidgets.QVBoxLayout()
self.extract_var = QtWidgets.QRadioButton("As Variable")
self.extract_var.setChecked(True)
vbox.addWidget(self.extract_var)
self.extract_type = QtWidgets.QRadioButton("As Type")
vbox.addWidget(self.extract_type)
self.extract_kind_box.setLayout(vbox)
self.replace_all_checkbox = QtWidgets.QCheckBox()
self.replace_all_checkbox.setChecked(True)

self.dialogs = (
("Extract...", None),
("Sentence", self.sentence_edit),
("Name", self.name_edit),
("Kind", self.extract_kind_box),
("Replace All", self.replace_all_checkbox),
)
self.resize(500, 100)
self.draw()
self.name_edit.setFocus()

def draw(self, *args):
main_layout = QtWidgets.QVBoxLayout()
for name, widget in self.dialogs:
if not widget:
l_widget = QtWidgets.QGroupBox(name)
l_widget.setStyleSheet(
"""
QGroupBox {
color: white;
border: 1px solid gray;
border-radius: 9px;
margin-top: 0.5em;
}
QGroupBox::title {
color: white;
subcontrol-origin: margin;
left: 10px;
padding: 0 3px 0 3px;
}
"""
)
l_widget.setFlat(False)
section_layout = QtWidgets.QFormLayout()
l_widget.setLayout(section_layout)
main_layout.addWidget(l_widget)
else:
section_layout.addRow(name, widget)
extract_button = QtWidgets.QPushButton("Extract")
extract_button.clicked.connect(self.extract)
main_layout.addWidget(extract_button)
self.setLayout(main_layout)

def extract(self):
if self.extract_var.isChecked():
declaration = "let {} = {};\n".format(self.name_edit.text(), self.sentence_edit.text())

if self.extract_type.isChecked():
declaration = "type {} = {};\n".format(self.name_edit.text(), self.sentence_edit.text())

if self.replace_all_checkbox.isChecked():
pos = self.parent().save_position()
text = self.parent().toPlainText()
self.parent().clear_and_write_text(text.replace(self.sentence_edit.text(), self.name_edit.text()))
self.parent().load_position(*pos)

tc = self.parent().textCursor()
tc.movePosition(QtGui.QTextCursor.StartOfLine)
tc.insertText(declaration)
self.close()

0 comments on commit f0dac96

Please sign in to comment.