free software resistance
the cost of computing freedom is eternal vigilance
### she21.py
*originally posted:* jun 2025
she21.py- gui rebuilt from tk.py, she finally features word wrap.
tk.py is a project to rebuild the gui that she uses. she 2.1 is the first version to use this gui code instead.
at this point the whole project could probably be relicensed 0-clause bsd, but it will retain the gpl 3 license for now.
most of the code should be the same, instances of text indices like tk.INSERT are now unprefixed such as INSERT, testing of version 2.1 has been limited but looks good so far. indentation for the largest function was not altered, it was simply moved to another class. line count is roughly identical. menu font has changed, underlines in the menu are gone. those would be good to put back.
```
#!/usr/bin/pypy2
# coding: utf-8
# Copyright 2020, 2021, 2022, 2024, 2025 mn, fcr
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
import os
from sys import argv, stdin
from Tkinter import *
import tkFileDialog as filedialog
class Application(Frame):
def ctrlq(self, *args):
root.destroy()
def set_window_title(self,name = None):
if name:
self.master.title(name)
else:
self.master.title("she " + self.ver + " - Untitled - path:" + os.getcwd())
def newfile(self, *args):
self.textarea.delete(1.0, END)
self.filename = None
self.set_window_title()
def savefile(self, *args):
if self.filename:
try:
textarea_content = self.textarea.get(1.0,END)
with open(self.filename,"w") as f:
f.write(textarea_content.encode('utf-8'))
except Exception as e :
print(e)
else:
self.saveasfile()
def saveasfile(self, *args):
try:
new_file = filedialog.asksaveasfilename(
initialfile = "untitled.txt",
defaultextension = ".txt",
filetypes = [("All Files", "*.*"),
("Text File", "*.txt"),
("Python file", "*.py"),
("FIG ", "*.fig"),
("FIG PLUS ", "*.fgp"),
("PAVUM", "*.pav"),
("JavaScript", "*.js"),
("HTML Documents", "*.html"),
("CSS Document", "*.css")])
textarea_content = self.textarea.get(1.0,END)
with open(new_file, "w") as f:
f.write(textarea_content.encode('utf-8'))
self.filename = new_file
self.set_window_title(self.filename)
except Exception as e:
print(e)
def openfile(self, *args):
self.filename = filedialog.askopenfilename(
defaultextension = "",
filetypes = [("All Files","*.*"),
("Text File","*.txt"),
("Python file","*.py"),
("FIG ","*.fig"),
("FIG PLUS ","*.fgp"),
("PAVUM","*.pav"),
("JavaScript","*.js"),
("HTML Documents","*.html"),
("CSS Document","*.css")])
if self.filename:
self.textarea.delete(1.0, END)
with open(self.filename, "r") as f:
self.textarea.insert(1.0, f.read())
self.set_window_title(self.filename + " - she " + self.ver + " - path:" + os.getcwd())
def about(self, *args):
nl = chr(10)
text = "# about she " + self.ver + "\n\n# she is a text editor originally based on ej, which lets you run shell commands in the editor. to run the text on the current line, just use ctrl+t.\n\n# copyright 2020, 2021, 2022, 2024, 2025 mn, fcr\n\n# This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n\n# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\n# You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/."
self.textarea.insert(INSERT, nl + text + " " + nl)
def ctrlt(self, *args):
try:
sf = self.filename
except:
sf = ""
nl = chr(10) ; from os import popen as po
# self.textarea.insert(1.0, "hello" + " " + nl)
try:
selectflag = 0
sel = [""]
sel = self.textarea.get(SEL_FIRST, SEL_LAST).split(nl)
selectflag = 1
cmd = sel[0].rstrip()
except:
cmd = self.textarea.get(1.0,END).split(nl)
cmd = cmd[int(self.textarea.index(INSERT).split(".")[0]) - 1]
try:
first = cmd.split()[0].lower()
amp = (chr(32) + cmd.split(nl)[0]).rstrip()[-1]
except:
first = ""
amp = ""
if first == "cd":
try: second = cmd.split()[1] ; os.chdir(second) ; self.textarea.insert(INSERT, nl + " " + nl)
except: pass
self.set_window_title("she " + self.ver + " - path:" + os.getcwd())
elif first == "=" + ">":
try:
second = cmd.split()[1]
except:
second = ""
try:
self.hist += ["=" + ">" + chr(32) + os.path.abspath(second)]
if len(self.hist) > self.histlimit:
self.hist = self.hist[-self.histlimit:]
hists = chr(10).join(self.hist) + chr(10)
with open(second, "r") as f:
self.textarea.delete(1.0,END)
self.textarea.insert(1.0, hists + f.read())
self.filename = second
except:
self.textarea.insert(INSERT, nl + "unable to open " + second + ", might not exist or wrong folder " + nl)
try:
uwd = "/".join((second + ".html").split("/")[:-1])
os.chdir(uwd) ; self.textarea.insert(INSERT, nl + " " + nl)
except: pass
self.set_window_title(second + " - she " + self.ver + " - path:" + os.getcwd())
elif cmd.strip() == "cls":
self.textarea.delete(INSERT, END)
self.textarea.insert(END, chr(32) + chr(10))
elif first == "appto":
try:
second = cmd.split()[1]
added = ""
with open(second, "a") as outfile:
for each in sel[1:]:
outfile.write((each + nl).encode('utf-8'))
outfile.close()
added = nl + "= added ="
self.textarea.insert(INSERT, added + nl + " " + nl)
except: pass
elif first == "mk":
eno = -1
import sys
try:
second = cmd.lstrip()[len("mk") + 1:].split("|")
except: second = []
try:
eno = 0
f = []
if selectflag:
selget = sel[1:]
else:
selget = self.textarea.get(1.0,END).split(nl)
bdir = os.getcwd()
udir = '/home/' + os.getlogin() + '/she'
try:
os.chdir('/root/she')
udir = '/root/she'
except:
pass
os.chdir(bdir)
try:
if not udir in sys.path:
sys.path.insert(0, udir)
import custom
from custom import mkcustom
reload(custom)
from custom import mkcustom
f = mkcustom(selget, second)
except:
f = [udir + '/custom.py error']
os.chdir(bdir)
except: pass
self.textarea.insert(INSERT, nl + "\n".join(f) + " " + nl)
elif first == "sort":
try:
f = []
if selectflag:
selget = sel[1:]
else:
selget = self.textarea.get(1.0, END).split(nl)
selget.sort()
for each in selget:
f += [each]
except: pass
self.textarea.insert(INSERT, nl + "\n".join(f) + " " + nl)
elif first == "rev":
try:
f = []
if selectflag:
selget = sel[1:]
else:
selget = self.textarea.get(1.0,END).split(nl)
for each in selget:
f += [each[::-1]]
except: pass
self.textarea.insert(INSERT, nl + "\n".join(f) + " " + nl)
elif first == "seek":
try:
second = cmd.lstrip()[len("seek") + 1:].split("|")
f = []
if selectflag:
selget = sel[1:]
else:
selget = self.textarea.get(1.0,END).split(nl)
for each in selget:
for parts in second:
if parts.lower() in each.lower():
f += [each]
break
except: pass
self.textarea.insert(INSERT, nl + "\n".join(f) + " " + nl)
elif first == "unseek":
try:
second = cmd.lstrip()[len("unseek") + 1:].split("|")
f = []
if selectflag:
selget = sel[1:]
else:
selget = self.textarea.get(1.0, END).split(nl)
for each in selget:
flag = 1
for parts in second:
if parts.lower() in each.lower():
flag = 0
break
if flag:
f += [each]
except: pass
self.textarea.insert(INSERT, nl + "\n".join(f) + " " + nl)
elif first == "replace":
try:
second = cmd.lstrip()[len("replace") + 1:].split("|")
f = []
rfrom = second[0].replace("\\n", "\n")
rfto = second[1].replace("\\n", "\n")
if selectflag:
selget = sel[1:]
else:
selget = self.textarea.get(1.0,END).split(nl)
for each in "\n".join(selget).replace(rfrom, rfto).split("\n"):
f += [each]
except: pass
self.textarea.insert(INSERT, nl + "\n".join(f) + " " + nl)
elif first == "saferbrowse":
if self.saferbrowse == 0:
self.saferbrowse = 1
self.textarea.insert(INSERT, nl + "saferbrowse on " + nl)
else:
self.saferbrowse = 0
self.textarea.insert(INSERT, nl + "saferbrowse off " + nl)
elif first == "wcl":
try:
if selectflag:
f = sel
else:
f = self.textarea.get(1.0,END).split(nl)[1:]
except: pass
self.textarea.insert(INSERT, nl + str(len(f) - 1) + " " + nl)
else:
try:
if amp == "&":
if not ">" in cmd.split(nl)[0] or self.saferbrowse == 0:
f = os.system(cmd.split(nl)[0].encode('utf-8'))
self.textarea.insert(INSERT, nl + " " + nl)
if ">" in cmd.split(nl)[0] and self.saferbrowse != 0:
self.textarea.insert(INSERT, nl + "saferbrowse is on; run the saferbrowse command to toggle file redirection " + nl)
else:
if first[0] != "*":
if not ">" in cmd.split(nl)[0] or self.saferbrowse == 0:
f = po(cmd.split(nl)[0].encode('utf-8'))
self.textarea.insert(INSERT, nl + f.read().rstrip() + " " + nl)
if ">" in cmd.split(nl)[0] and self.saferbrowse != 0:
self.textarea.insert(INSERT, nl + "saferbrowse is on; run the saferbrowse command to toggle file redirection " + nl)
except: pass
def controls(self):
self.menus = Menu(self)
root.config(menu=self.menus)
file_menu = Menu(self.menus)
file_menu.add_command(label = "new file", command = self.newfile)
file_menu.add_command(label = "open file", command = self.openfile)
file_menu.add_command(label = "save", command = self.savefile)
file_menu.add_command(label = "save as", command = self.saveasfile)
file_menu.add_separator()
file_menu.add_command(label = "quit", command = root.destroy)
self.menus.add_cascade(label = "file", menu = file_menu)
about_menu = Menu(self.menus)
about_menu.add_command(label = "about", command = self.about)
self.menus.add_cascade(label = "about", menu = about_menu)
self.textarea = Text(self, wrap=WORD)
self.menus.configure(font = ("monospace", 16), bg = "#e7e7e7")
self.textarea.configure(font = ("monospace", 16), bg = "#e7e7e7")
self.textarea.pack({"side": "left", "fill": "both", "expand": "true"})
self.scroll = Scrollbar(self, command = self.textarea.yview)
self.textarea.configure(yscrollcommand = self.scroll.set)
self.scroll.pack({"side": "right", "fill": "y"})
self.textarea.bind('<' + 'Control-t>', self.ctrlt)
self.textarea.bind('<' + 'Control-n>', self.newfile)
self.textarea.bind('<' + 'Control-o>', self.openfile)
self.textarea.bind('<' + 'Control-s>', self.savefile)
self.textarea.bind('<' + 'Control-S>', self.saveasfile)
self.textarea.bind('<' + 'Control-b>', self.ctrlt)
self.textarea.bind('<' + 'Control-q>', self.ctrlq)
def __init__(self, master = None):
Frame.__init__(self, master)
self.pack({"side": "left", "fill": "both", "expand": "true"})
self.controls()
self.ver = "2.1"
self.saferbrowse = 1
self.histlimit = 10
self.hist = []
root.title("untitled - she " + self.ver + " - path:" + os.getcwd())
self.master = master
self.filename = None
pst = ""
if not os.isatty(stdin.fileno()):
for p in stdin:
pst += str(p[:-1]) + chr(10)
self.textarea.insert(1.0, pst)
try:
if argv[1:][0]:
self.filename = argv[1:][0]
with open(self.filename, "r") as f:
self.textarea.insert(1.0, f.read())
self.set_window_title(self.filename + " - she " + self.ver + " - path:" + os.getcwd())
except:
pass
root = Tk()
app = Application(master = root)
app.mainloop()
try:
root.destroy()
except:
pass
```
license: gpl, version 3 or later
=> https://freesoftwareresistance.neocities.org