170 lines
4.4 KiB
Python
Executable File
170 lines
4.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
from argparse import ArgumentParser
|
|
import atexit
|
|
import csv
|
|
import os
|
|
import readline
|
|
import sys
|
|
from cmd import Cmd
|
|
|
|
def init_readline():
|
|
histfile = os.path.join(os.path.expanduser("~"), ".hmwebot_history")
|
|
|
|
try:
|
|
readline.read_history_file(histfile)
|
|
h_len = readline.get_current_history_length()
|
|
except FileNotFoundError:
|
|
open(histfile, 'wb').close()
|
|
h_len = 0
|
|
|
|
def save(prev_h_len, histfile):
|
|
new_h_len = readline.get_current_history_length()
|
|
readline.set_history_length(1000)
|
|
readline.append_history_file(new_h_len - prev_h_len, histfile)
|
|
atexit.register(save, h_len, histfile)
|
|
|
|
|
|
def rlinput(prompt, prefill=''):
|
|
readline.set_startup_hook(lambda: readline.insert_text(prefill))
|
|
try:
|
|
return input(prompt) # or raw_input in Python 2
|
|
finally:
|
|
readline.set_startup_hook()
|
|
|
|
|
|
class CSVEditor:
|
|
def __init__(self, filename):
|
|
self.filename = filename
|
|
with open(filename, 'r') as f:
|
|
reader = csv.DictReader(f)
|
|
self.fieldnames = reader.fieldnames
|
|
self.data = [data for data in reader]
|
|
|
|
def get_list(self, title_field):
|
|
return [(idx, data[title_field]) for idx, data in enumerate(self.data)]
|
|
|
|
def get(self, idx):
|
|
try:
|
|
return self.data[idx]
|
|
except IndexError:
|
|
return None
|
|
|
|
def show(self, idx):
|
|
line = self.get(idx)
|
|
if line is None:
|
|
return "Índice fuera de rango"
|
|
output = [
|
|
f"{field}: {value}"
|
|
for field, value in line.items()
|
|
]
|
|
return "\n".join(output)
|
|
|
|
def edit(self, idx, item):
|
|
self.data[idx] = item
|
|
|
|
def delete(self, idx):
|
|
if idx in self.data:
|
|
del self.data[idx]
|
|
|
|
def _edit(self, item):
|
|
editing = True
|
|
while editing:
|
|
for fieldname in self.fieldnames:
|
|
item[fieldname] = rlinput(f"{fieldname}: ", prefill=item.get(fieldname, ''))
|
|
|
|
editing = rlinput('Terminado (s/N)?').lower() == 'n'
|
|
|
|
def edit(self, idx):
|
|
item = self.get(idx)
|
|
if item is None:
|
|
return
|
|
self._edit(item)
|
|
self.data[idx] = item
|
|
|
|
def add(self):
|
|
item = {}
|
|
self._edit(item)
|
|
self.data.append(item)
|
|
|
|
def write(self):
|
|
with open(self.filename, 'w') as f:
|
|
writer = csv.DictWriter(f, fieldnames=self.fieldnames)
|
|
writer.writeheader()
|
|
writer.writerows(self.data)
|
|
|
|
|
|
class CSVEditorCmd(Cmd):
|
|
"Editor interactivo de ficheros csv"
|
|
|
|
def __init__(self, filename, title_field=None):
|
|
super().__init__()
|
|
self.csveditor = CSVEditor(filename)
|
|
self.title_field = title_field
|
|
if title_field is None:
|
|
self.title_field = self.csveditor.fieldnames[0]
|
|
self.do_help('')
|
|
|
|
def do_list(self, arg):
|
|
"Listar el contenido del csv"
|
|
for idx, item in self.csveditor.get_list(self.title_field):
|
|
print(f"{idx}) {item}")
|
|
|
|
def do_show(self, arg):
|
|
"Mostrar la línea con el índice indicado"
|
|
try:
|
|
idx = int(arg)
|
|
except ValueError:
|
|
print("Tienes que indicar un número")
|
|
return
|
|
print(self.csveditor.show(idx))
|
|
|
|
def do_add(self, arg):
|
|
"Añadir una nueva entrada"
|
|
self.csveditor.add()
|
|
|
|
def do_edit(self, arg):
|
|
"Editar la entrada con el índice indicado"
|
|
try:
|
|
idx = int(arg)
|
|
except ValueError:
|
|
print("Tienes que indicar un número")
|
|
return
|
|
self.csveditor.edit(idx)
|
|
|
|
def do_delete(self, arg):
|
|
"Quitar la entrada con el índice indicado"
|
|
try:
|
|
idx = int(arg)
|
|
except ValueError:
|
|
print("Tienes que indicar un número")
|
|
return
|
|
self.csveditor.delete(idx)
|
|
|
|
def do_save(self, arg):
|
|
"Guardar la lista actualizada"
|
|
self.csveditor.write()
|
|
|
|
def do_quit(self, arg):
|
|
"Terminar"
|
|
return True
|
|
|
|
do_EOF = do_quit
|
|
|
|
|
|
parser = ArgumentParser(
|
|
description='Editor sencillo de ficheros CSV')
|
|
|
|
parser.add_argument('csvfile', help='Fichero que hay que editar.')
|
|
parser.add_argument('-t', '--title', help='Columna principal del CSV, por defecto la primera.')
|
|
|
|
|
|
def main():
|
|
init_readline()
|
|
# bot = Bot()
|
|
args = parser.parse_args()
|
|
cmd = CSVEditorCmd(args.csvfile, args.title)
|
|
cmd.cmdloop()
|
|
|
|
if __name__ == '__main__':
|
|
main()
|