I encountered this problem when I was trying to edit files inside the initramfs. This was the only thread I found so instead of hunting for another fix, I wrote a python script to make a simple text editor that works inside the initramfs (and other feature poor terminals)
It's pretty simple, only displays one line at a time so you press up and down to change lines and left and right to move the cursor and enter to save. Nothing fancy, but it seems to work okay for quick edits.
It requires only the readchar module: python3 -m pip install readchar
#!/usr/bin/python3
#Edit a text file inside the initramfs (when other text editors don't work)
'''Compile with:
libgcc=$(find /lib -name libgcc_s.so.1 | head -n 1)
libutil=$(ldd /usr/bin/python3 | grep libutil | cut -d ' ' -f 3)
pyinstaller --onefile editfile.py --add-data="$libgcc:." --add-data="$libutil:." --hidden-import readchar
'''
import shutil, sys, readchar
'''
Allow user to edit a line of text complete with support for line wraps and a cursor | you can move back and forth with the arrow keys.
lines = initial text supplied to edit
prompt= Decoration presented before the text (not editable and not returned)
'''
def text_editor(lines=[], prompt=''):
term_width = shutil.get_terminal_size()[0] - 1
line_num = 0
if type(lines) in (list, tuple):
multiline=True
else:
multiline=False
lines=[lines]
text = list(lines[line_num])
ptr = len(text)
prompt = list(prompt)
space = [' ']
c = 0
while True:
if ptr and ptr > len(text):
ptr = len(text)
copy = text.copy()
if ptr < len(text):
copy.insert(ptr,'|')
copy = list(str(line_num)) + space + prompt + copy
#Line wraps support:
if len(copy) > term_width:
cut = len(copy) + 3 - term_width
if ptr > len(copy) / 2:
copy = ['<']*3 + copy[cut:]
else:
copy = copy[:-cut] + ['>']*3
print('\r'*term_width+''.join(copy), end=' '*(term_width-len(copy)), flush=True)
if c in (53,54):
#Page up/down bug
c = readchar.readkey()
if c == '~':
continue
else:
c = readchar.readkey()
if len(c) > 1:
#Control Character
c = ord(c[-1])
#Save current line on line change
if c in (53, 54, 65, 66):
lines[line_num] = ''.join(text)
if c == 65: #Up
line_num -= 1
elif c == 66: #Down
line_num += 1
elif c == 68: #Left
ptr -= 1
elif c == 67: #Right
ptr += 1
elif c == 54: #PgDn
line_num += 10
elif c == 53: #PgUp
line_num -= 10
elif c == 70: #End
ptr = len(text)
elif c == 72: #Home
ptr = 0
else:
print("\nUnknown control character:", c)
print("Press ctrl-c to quit.")
continue
if ptr < 0:
ptr = 0
if ptr > len(text):
ptr = len(text)
#Check if line changed
if c in (53, 54, 65, 66):
if multiline == False:
line_num = 0
continue
if line_num < 0:
line_num = 0
while line_num > len(lines) - 1:
lines.append('')
text = list(lines[line_num])
else:
num = ord(c)
if num in (13, 10): #Enter
print()
lines[line_num] = ''.join(text)
if multiline:
return lines
else:
return lines[0]
elif num == 127: #Backspace
if text:
text.pop(ptr-1)
ptr -=1
elif num == 3: #Ctrl-C
sys.exit(1)
else:
text.insert(ptr, c)
ptr += 1
#Main
if len(sys.argv) == 1:
print("Usage: ./editfile <filename>")
sys.exit(1)
f = open(sys.argv[1], 'r')
strings = f.read().split('\n')
f.close()
strings = text_editor(strings)
#Trim empty lines on end
for x in range(len(strings) -1,0, -1):
if len(strings[x]):
break
else:
strings.pop(-1)
f = open(sys.argv[1], 'w')
f.write('\n'.join(strings)+'\n')