diff --git a/LICENSE b/LICENSE index 7a3094a..eadf858 100644 --- a/LICENSE +++ b/LICENSE @@ -1,11 +1,14 @@ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 Copyright (C) 2004 Sam Hocevar -Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed. +Everyone is permitted to copy and distribute verbatim or modified copies of +this license document, and changing it is allowed as long as the name is changed. DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - 0. You just DO WHAT THE FUCK YOU WANT TO. + 0. You just DO WHAT THE FUCK YOU WANT TO. \ No newline at end of file diff --git a/README.md b/README.md index 40889cf..19b1fff 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,10 @@ -# libcurses +# Libcurses +Regroupe des fonctions faites maison pour l'utilisation personnelle simplifiée de la bibliothèque curses. + +## Contributions + +Toute contribution est la bienvenue, et peut m'être adressée à l'adresse + +## Licence +[WTFPL](http://www.wtfpl.net/) diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..450577d --- /dev/null +++ b/TODO.md @@ -0,0 +1,3 @@ +# TODO LIST + +Faire des tests ? diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d4bb2cb --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..7231b51 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,70 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, '/home/david/dev_python_packaging/libcurses/libcurses') + + +# -- Project information ----------------------------------------------------- + +project = 'libcurses' +copyright = '2020, Author' +author = 'Author' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.viewcode', + 'sphinx.ext.todo', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'en' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + + +# -- Extension configuration ------------------------------------------------- + +# -- Options for todo extension ---------------------------------------------- + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..6b51550 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,21 @@ +.. libcurses documentation master file, created by + sphinx-quickstart on Sat May 9 17:50:38 2020. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to libcurses's documentation! +===================================== + +.. toctree:: + :maxdepth: 4 + :caption: Contents: + + libcurses + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/libcurses.rst b/docs/libcurses.rst new file mode 100644 index 0000000..ed4fe23 --- /dev/null +++ b/docs/libcurses.rst @@ -0,0 +1,30 @@ +libcurses package +================= + +Submodules +---------- + +libcurses.constantes\_curses module +----------------------------------- + +.. automodule:: libcurses.constantes_curses + :members: + :undoc-members: + :show-inheritance: + +libcurses.libcurses module +-------------------------- + +.. automodule:: libcurses.libcurses + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: libcurses + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..2119f51 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/libcurses/__init__.py b/libcurses/__init__.py new file mode 100644 index 0000000..e3737c7 --- /dev/null +++ b/libcurses/__init__.py @@ -0,0 +1 @@ +from libcurses.libcurses import * diff --git a/libcurses/constantes_curses.py b/libcurses/constantes_curses.py new file mode 100644 index 0000000..7819f03 --- /dev/null +++ b/libcurses/constantes_curses.py @@ -0,0 +1,32 @@ +"""Constantes de la bibliothèque libcurses + + version + encoding + + touche_haut : chaîne de caractère du clavier + touche_bas : chaîne de caractère du clavier + touche_entree : entier désignant la touche entrée (10) + + quitter : chaîne de caractère pour quitter une fenêtre curses à tout moment + terminer : chaîne de caractère alternative pour quitter une boucle infinie + suivant : chaîne de caractère pour passer à l'écran suivant + +""" +version = "1.0" + +## Encodage +encoding = 'utf8' + +## Configuration du clavier +touche_haut = 'n' +touche_bas = 't' # pour se déplacer dans un menu +touche_entree = 10 + +## Chaîne de caractères pour quitter un programme +quitter = 'quitter' + +## Chaîne de caractères pour sortir d'une saisie dont le type est contraint +terminer = 'terminer' + +## Chaîne de caractères pour saisir la question suivantes d'un barème +suivant = 'suivant' diff --git a/libcurses/libcurses.py b/libcurses/libcurses.py new file mode 100644 index 0000000..b53247d --- /dev/null +++ b/libcurses/libcurses.py @@ -0,0 +1,204 @@ +import curses +import sys +from . import constantes_curses as constantes +#import constantes_curses as constantes + +def create_newwin(): + """Initialise une fenêtre + """ + window = curses.newwin(0,0) + window.border(0) + return window + +def init_curses(): + """Initialise la biliothèque curses + """ + stdscr = curses.initscr() + curses.noecho() + curses.cbreak() + stdscr.keypad(True) + return stdscr + +def close_curses(stdscr): + """Ferme la fenêtre + """ + stdscr.keypad(0) + curses.nocbreak() + curses.echo() + curses.endwin() + +def init_colors(): + """Initialisation des couleurs de la fenêtre + """ + curses.start_color() + curses.init_pair(1,curses.COLOR_RED,curses.COLOR_BLACK) + curses.init_pair(2,curses.COLOR_BLACK,curses.COLOR_RED) + +class Echo(): + """Décorateur permettant de garantir que ce qui est écrit au clavier sera vu à l'écran + """ + + + def __init__(self,f): + self.f = f + + def __call__(self,*args,**kwargs): + curses.echo() + return self.f(*args,**kwargs) + curses.noecho() + +def add_line(window,pos,nombre_lignes): + """Permet de passer à la ligne suivante lors d'une saisie utilisateur : on ré-initialise la fenêtre si on est descendu trop bas. + """ + if pos == nombre_lignes-2: + pos = 1 + window = curses.newwin(0,0) + window.border(0) + window.refresh() + return pos + else: + pos +=1 + return pos + +@Echo +def get_user_entry(window,encoding=constantes.encoding): + """Récupère la saisie d'un message à l'écran + """ + userentry = window.getstr() + return userentry.decode(encoding) + +def get_entry(window,message,pos,nombre_lignes,encoding=constantes.encoding): + """ + Récupère la saisie utilisateur, en affichant un message d'erreur et demandant la re-saisie si la fonction decode plante (effacement d'un seul caractère au lieu de deux lors d'une saisie erronée d'un caractère accentué). + """ + while True: + try: + window.addstr(pos,1,message,curses.color_pair(1)) + return [get_user_entry(window,encoding),add_line(window,pos,nombre_lignes)] + except: + pos = add_line(window,pos,nombre_lignes) + window.addstr(pos,1,"Erreur de saisie, merci de recommencer",curses.color_pair(1)) + pos = add_line(window,pos,nombre_lignes) + +def display_menu(title,menu,window,active=1): + """Affiche un menu, qui ne doit pas avoir plus de lignes que la taille de l'écran (non vérifié). + """ + window.addstr(1,1,title,curses.color_pair(1)) + item_pos = 6 ## WTF ?? + pos = 1 + for item in menu: + if pos == active: + color = curses.color_pair(2) + else: + color = curses.A_NORMAL + if item == 'Quitter': + item_pos +=1 + window.addstr(item_pos,1," %d. %s" %(pos,item),color) + pos +=1 + else: + window.addstr(item_pos,1," %d. %s" %(pos,item),color) + item_pos +=1 + pos +=1 + window.refresh() + +def getkey(final,title,menu,window,active_pos=1): + """Permet de se balader dans un menu + """ + c = None + while c != constantes.touche_entree: + c = window.getch() + if c == ord(constantes.touche_bas): + if active_pos != final: + active_pos +=1 + else: + active_pos = 1 + elif c == ord(constantes.touche_haut): + if active_pos != 1: + active_pos -=1 + else: + active_pos = final + display_menu(title,menu,window,active_pos) + return active_pos + + +class Stdscr(): + """Décorateur permettant d'initialiser une fenêtre curses + """ + + + def __init__(self,f): + self.f = f + + def __call__(self,*args): + window = init_curses() + nombre_lignes = curses.LINES + init_colors() + window = create_newwin() + window.refresh() + try: + return self.f(*args,window,nombre_lignes) + finally: + close_curses(window) + +@Stdscr +def saisie_message_std(message,window,nombre_lignes): + """Retourne la saisie de l'utilisateur, et quitte le programme si cette saisie est constantes.quitter + """ + pos = 1 + user_entry = get_entry(window,message,pos,nombre_lignes,encoding=constantes.encoding)[0] + if user_entry.lower() == constantes.quitter: + quit() # pourquoi pas sys.exit() ? + else: + return user_entry + +@Stdscr +def afficher_message_std(message,window,nombre_lignes): + """Permet d'afficher un unique message à l'écran + """ + pos = 1 + fin_message = " (appuyer sur une touche pour continuer) " + c = None + window.addstr(pos,1,message+fin_message,curses.color_pair(1)) + while c == None: + c = window.getch() + return None + +def saisie_message(pos,message,window,nombre_lignes): + """Retourne la saisie de l'utilisateur, et quitte le programme si cette saisie est constantes.quitter + """ + user_entry,pos = get_entry(window,message,pos,nombre_lignes,encoding=constantes.encoding) + if user_entry.lower() == constantes.quitter: + sys.exit() + else: + return [user_entry, pos] + +def afficher_message(pos,message,window,nombre_lignes): + """Permet d'afficher un message à l'écran dans une fenêtre déjà initialisée + """ + fin_message = " (appuyer sur une touche pour continuer) " + c = None + window.addstr(pos,1,message+fin_message,curses.color_pair(1)) + while c == None: + c = window.getch() + return add_line(window,pos,nombre_lignes) + +def is_forceable(info,type_info): + """Détermine si l'info peut être considérée comme un 'type_info' + """ + try: + return type_info(info) + except: + return False + +def get_clean_info(type_info,message,pos,window,nombre_lignes): + """Permet de s'assurer que l'information récupérée est bien du type voulue. + """ + var = False + while not var: + var,pos = saisie_message(pos,message,window,nombre_lignes) + if var == constantes.terminer: #cas particulier de nécessité de sortie de boucle + return [var,pos] + var = is_forceable(var,type_info) + if (var is 0) and type_info == int: #cas particulier du zéro interprété comme False + return [var, pos] + return [var, pos] diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..8152c2b --- /dev/null +++ b/setup.py @@ -0,0 +1,18 @@ +from setuptools import setup, find_packages +from libcurses.constantes_curses import version + +setup( + name="libcurses", + version=version, + packages=find_packages(), + + author="David Denoncin", + author_email="math@denoncin.fr", + url="math.denoncin.fr", + description="Mes fonctions perso pour faciliter l'utilisation de la bibliothèque curses", + classifiers=[ + "Licence :: WTFPL" + ] +) + +