Compare commits

..

1 commit

31 changed files with 324 additions and 127 deletions

1
.gitignore vendored
View file

@ -4,4 +4,3 @@ scripts/test.py
scripts/.idea scripts/.idea
scripts/credentials.json scripts/credentials.json
scripts/token.pickle scripts/token.pickle
__pycache__

View file

@ -23,7 +23,7 @@ SOFTWARE.
MIT License MIT License
Copyright (c) 2021,2022 Maximilian Keßler Copyright (c) 2021 Maximilian Keßler
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View file

@ -1,16 +0,0 @@
PKGNAME=university-setup
PREFIX=mkessler
install:
mkdir -p $(DESTDIR)/opt/$(PREFIX)/${PKGNAME}
mkdir -p $(DESTDIR)/etc/opt/$(PREFIX)/${PKGNAME}
cp src/* $(DESTDIR)/opt/$(PREFIX)/${PKGNAME}
cp config/* $(DESTDIR)/etc/opt/$(PREFIX)/${PKGNAME}
install -Dm644 "LICENSE" $(DESTDIR)/usr/share/licenses/$(PREFIX)/${PKGNAME}/LICENSE
uninstall:
rm -rf $(DESTDIR)/opt/$(PREFIX)/${PKGNAME}
rm -rf $(DESTDIR)/etc/opt/$(PREFIX)/${PKGNAME}
rm -rf $(DESTDIR)/usr/share//licenses/$(PREFIX)/${PKGNAME}

View file

@ -1,16 +1,9 @@
# Fork # Fork
This fork of [gillescastell/university-setup][setup] contains my personal customatizations to the setup Gilles uses. The main point is that the `info.yaml` file now contains options for specifying the subfolders for the notes, as well as subfolders for the lectures. This helps me re-use the `current_course` directory for other data as well (e.g. my exercise sheets) while having a single dedicated folder for my lecture notes. It is implemented with an additional `Notes` class that handles this. Possibly, one can extend this to e.g. an `Exercises` class that one can add to each course etc. This fork contains my personal customatizations to the setup Gilles uses. The main point is that the `info.yaml` file now contains options for specifying the subfolders for the notes, as well as subfolders for the lectures. This helps me re-use the `current_course` directory for other data as well (e.g. my exercise sheets) while having a single dedicated folder for my lecture notes. It is implemented with an additional `Notes` class that handles this. Possibly, one can extend this to e.g. an `Exercises` class that one can add to each course etc.
Additionally, this version features a `.courseignore` file you can place in the `ROOT` folder to ignore some directories for the courses. Additionally, this version features a `.courseignore` file you can place in the `ROOT` folder to ignore some directories for the courses.
##
If you want to install this, run `make install` on your favourite unix operating system.
This installs into `/opt/mkessler/university-setup`.
There is also a [PKGBUILD][pkgbuild] for Arch linux available.
# Managing LaTeX lecture notes # Managing LaTeX lecture notes
This repository complements my [third blog post about my note taking setup](https://castel.dev/post/lecture-notes-3). This repository complements my [third blog post about my note taking setup](https://castel.dev/post/lecture-notes-3).
@ -21,7 +14,7 @@ This repository complements my [third blog post about my note taking setup](http
ROOT ROOT
├── riemann-surfaces ├── riemann-surfaces
│   ├── info.yaml │   ├── info.yaml
│   ├── master.texvllt sollte ich │   ├── master.tex
│   ├── lec_01.tex │   ├── lec_01.tex
│   ├── ... │   ├── ...
│   ├── lec_13.tex │   ├── lec_13.tex
@ -159,7 +152,3 @@ Some utility functions
#### `compile-all-masters.py` #### `compile-all-masters.py`
This script updates the `master.tex` files to include all lectures and compiles them. I use when syncing my notes to the cloud. This way I always have access to my compiles notes on my phone. This script updates the `master.tex` files to include all lectures and compiles them. I use when syncing my notes to the cloud. This way I always have access to my compiles notes on my phone.
[setup]: https://github.com/gillescastel/university-setup
[pkgbuild]: https://git.abstractnonsen.se/arch/university-setup-git

265
preamble.tex Normal file
View file

@ -0,0 +1,265 @@
% Some basic packages
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{textcomp}
\usepackage[dutch]{babel}
\usepackage{url}
\usepackage{graphicx}
\usepackage{float}
\usepackage{booktabs}
\usepackage{enumitem}
\pdfminorversion=7
% Don't indent paragraphs, leave some space between them
\usepackage{parskip}
% Hide page number when page is empty
\usepackage{emptypage}
\usepackage{subcaption}
\usepackage{multicol}
\usepackage{xcolor}
% Other font I sometimes use.
% \usepackage{cmbright}
% Math stuff
\usepackage{amsmath, amsfonts, mathtools, amsthm, amssymb}
% Fancy script capitals
\usepackage{mathrsfs}
\usepackage{cancel}
% Bold math
\usepackage{bm}
% Some shortcuts
\newcommand\N{\ensuremath{\mathbb{N}}}
\newcommand\R{\ensuremath{\mathbb{R}}}
\newcommand\Z{\ensuremath{\mathbb{Z}}}
\renewcommand\O{\ensuremath{\emptyset}}
\newcommand\Q{\ensuremath{\mathbb{Q}}}
\newcommand\C{\ensuremath{\mathbb{C}}}
% Easily typeset systems of equations (French package)
\usepackage{systeme}
% Put x \to \infty below \lim
\let\svlim\lim\def\lim{\svlim\limits}
%Make implies and impliedby shorter
\let\implies\Rightarrow
\let\impliedby\Leftarrow
\let\iff\Leftrightarrow
\let\epsilon\varepsilon
% Add \contra symbol to denote contradiction
\usepackage{stmaryrd} % for \lightning
\newcommand\contra{\scalebox{1.5}{$\lightning$}}
% \let\phi\varphi
% Command for short corrections
% Usage: 1+1=\correct{3}{2}
\definecolor{correct}{HTML}{009900}
\newcommand\correct[2]{\ensuremath{\:}{\color{red}{#1}}\ensuremath{\to }{\color{correct}{#2}}\ensuremath{\:}}
\newcommand\green[1]{{\color{correct}{#1}}}
% horizontal rule
\newcommand\hr{
\noindent\rule[0.5ex]{\linewidth}{0.5pt}
}
% hide parts
\newcommand\hide[1]{}
% si unitx
\usepackage{siunitx}
\sisetup{locale = FR}
% Environments
\makeatother
% For box around Definition, Theorem, \ldots
\usepackage{mdframed}
\mdfsetup{skipabove=1em,skipbelow=0em}
\theoremstyle{definition}
\newmdtheoremenv[nobreak=true]{definitie}{Definitie}
\newmdtheoremenv[nobreak=true]{eigenschap}{Eigenschap}
\newmdtheoremenv[nobreak=true]{gevolg}{Gevolg}
\newmdtheoremenv[nobreak=true]{lemma}{Lemma}
\newmdtheoremenv[nobreak=true]{propositie}{Propositie}
\newmdtheoremenv[nobreak=true]{stelling}{Stelling}
\newmdtheoremenv[nobreak=true]{wet}{Wet}
\newmdtheoremenv[nobreak=true]{postulaat}{Postulaat}
\newmdtheoremenv{conclusie}{Conclusie}
\newmdtheoremenv{toemaatje}{Toemaatje}
\newmdtheoremenv{vermoeden}{Vermoeden}
\newtheorem*{herhaling}{Herhaling}
\newtheorem*{intermezzo}{Intermezzo}
\newtheorem*{notatie}{Notatie}
\newtheorem*{observatie}{Observatie}
\newtheorem*{oef}{Oefening}
\newtheorem*{opmerking}{Opmerking}
\newtheorem*{praktisch}{Praktisch}
\newtheorem*{probleem}{Probleem}
\newtheorem*{terminologie}{Terminologie}
\newtheorem*{toepassing}{Toepassing}
\newtheorem*{uovt}{UOVT}
\newtheorem*{vb}{Voorbeeld}
\newtheorem*{vraag}{Vraag}
\newmdtheoremenv[nobreak=true]{definition}{Definition}
\newtheorem*{eg}{Example}
\newtheorem*{notation}{Notation}
\newtheorem*{previouslyseen}{As previously seen}
\newtheorem*{remark}{Remark}
\newtheorem*{note}{Note}
\newtheorem*{problem}{Problem}
\newtheorem*{observe}{Observe}
\newtheorem*{property}{Property}
\newtheorem*{intuition}{Intuition}
\newmdtheoremenv[nobreak=true]{prop}{Proposition}
\newmdtheoremenv[nobreak=true]{theorem}{Theorem}
\newmdtheoremenv[nobreak=true]{corollary}{Corollary}
% End example and intermezzo environments with a small diamond (just like proof
% environments end with a small square)
\usepackage{etoolbox}
\AtEndEnvironment{vb}{\null\hfill$\diamond$}%
\AtEndEnvironment{intermezzo}{\null\hfill$\diamond$}%
% \AtEndEnvironment{opmerking}{\null\hfill$\diamond$}%
% Fix some spacing
% http://tex.stackexchange.com/questions/22119/how-can-i-change-the-spacing-before-theorems-with-amsthm
\makeatletter
\def\thm@space@setup{%
\thm@preskip=\parskip \thm@postskip=0pt
}
% Exercise
% Usage:
% \oefening{5}
% \suboefening{1}
% \suboefening{2}
% \suboefening{3}
% gives
% Oefening 5
% Oefening 5.1
% Oefening 5.2
% Oefening 5.3
\newcommand{\oefening}[1]{%
\def\@oefening{#1}%
\subsection*{Oefening #1}
}
\newcommand{\suboefening}[1]{%
\subsubsection*{Oefening \@oefening.#1}
}
% \lecture starts a new lecture (les in dutch)
%
% Usage:
% \lecture{1}{di 12 feb 2019 16:00}{Inleiding}
%
% This adds a section heading with the number / title of the lecture and a
% margin paragraph with the date.
% I use \dateparts here to hide the year (2019). This way, I can easily parse
% the date of each lecture unambiguously while still having a human-friendly
% short format printed to the pdf.
\usepackage{xifthen}
\def\testdateparts#1{\dateparts#1\relax}
\def\dateparts#1 #2 #3 #4 #5\relax{
\marginpar{\small\textsf{\mbox{#1 #2 #3 #5}}}
}
\def\@lecture{}%
\newcommand{\lecture}[3]{
\ifthenelse{\isempty{#3}}{%
\def\@lecture{Lecture #1}%
}{%
\def\@lecture{Lecture #1: #3}%
}%
\subsection*{\@lecture}
\marginpar{\small\textsf{\mbox{#2}}}
}
% These are the fancy headers
\usepackage{fancyhdr}
\pagestyle{fancy}
% LE: left even
% RO: right odd
% CE, CO: center even, center odd
% My name for when I print my lecture notes to use for an open book exam.
% \fancyhead[LE,RO]{Gilles Castel}
\fancyhead[RO,LE]{\@lecture} % Right odd, Left even
\fancyhead[RE,LO]{} % Right even, Left odd
\fancyfoot[RO,LE]{\thepage} % Right odd, Left even
\fancyfoot[RE,LO]{} % Right even, Left odd
\fancyfoot[C]{\leftmark} % Center
\makeatother
% Todonotes and inline notes in fancy boxes
\usepackage{todonotes}
\usepackage{tcolorbox}
% Make boxes breakable
\tcbuselibrary{breakable}
% Verbetering is correction in Dutch
% Usage:
% \begin{verbetering}
% Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
% tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
% vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
% no sea takimata sanctus est Lorem ipsum dolor sit amet.
% \end{verbetering}
\newenvironment{verbetering}{\begin{tcolorbox}[
arc=0mm,
colback=white,
colframe=green!60!black,
title=Opmerking,
fonttitle=\sffamily,
breakable
]}{\end{tcolorbox}}
% Noot is note in Dutch. Same as 'verbetering' but color of box is different
\newenvironment{noot}[1]{\begin{tcolorbox}[
arc=0mm,
colback=white,
colframe=white!60!black,
title=#1,
fonttitle=\sffamily,
breakable
]}{\end{tcolorbox}}
% Figure support as explained in my blog post.
\usepackage{import}
\usepackage{xifthen}
\usepackage{pdfpages}
\usepackage{transparent}
\newcommand{\incfig}[1]{%
\def\svgwidth{\columnwidth}
\import{./figures/}{#1.pdf_tex}
}
% Fix some stuff
% %http://tex.stackexchange.com/questions/76273/multiple-pdfs-with-page-group-included-in-a-single-page-warning
\pdfsuppresswarningpagegroup=1
% My name
\author{Gilles Castel}

View file

@ -1,5 +0,0 @@
google-api-python-client
google-auth-oauthlib
python-dateutil
pytz
PyYAML

View file

@ -1,6 +1,5 @@
from pathlib import Path from pathlib import Path
import pytz import pytz
# default is 'primary', if you are using a separate calendar for your course schedule, # default is 'primary', if you are using a separate calendar for your course schedule,
# your calendarId (which you can find by going to your Google Calendar settings, selecting # your calendarId (which you can find by going to your Google Calendar settings, selecting
# the relevant calendar and scrolling down to Calendar ID) probably looks like # the relevant calendar and scrolling down to Calendar ID) probably looks like
@ -11,7 +10,7 @@ USERCALENDARID = 'primary'
CURRENT_COURSE_SYMLINK = Path('~/current_course').expanduser() CURRENT_COURSE_SYMLINK = Path('~/current_course').expanduser()
CURRENT_COURSE_ROOT = CURRENT_COURSE_SYMLINK.resolve() CURRENT_COURSE_ROOT = CURRENT_COURSE_SYMLINK.resolve()
CURRENT_COURSE_WATCH_FILE = Path('/tmp/current_course').resolve() CURRENT_COURSE_WATCH_FILE = Path('/tmp/current_course').resolve()
ROOT = Path('~/uni/semester-6').expanduser() ROOT = Path('~/Uni/semester-5').expanduser()
DATE_FORMAT = '%a %d %b %Y' DATE_FORMAT = '%a %d %b %Y'
LOCALE = "de_DE.utf8" LOCALE = "de_DE.utf8"
COURSE_IGNORE_FILE = '.courseignore' COURSE_IGNORE_FILE = '.courseignore'
@ -23,11 +22,10 @@ DEFAULT_NEW_LECTURE_HEADER = r'\lecture[]{{{date}}}{{{title}}}'
DEFAULT_NEW_LECTURE_TITLE = 'Untitled' DEFAULT_NEW_LECTURE_TITLE = 'Untitled'
DEFAULT_LECTURE_SEARCH_REGEX = r'lecture.*({\d*})?{(.*?)}{(.*)}' DEFAULT_LECTURE_SEARCH_REGEX = r'lecture.*({\d*})?{(.*?)}{(.*)}'
DEFAULT_IMPORT_INDENTATION = 4 DEFAULT_IMPORT_INDENTATION = 4
FALLBACK_COURSE_INFO_FILE = Path(__file__).parent.resolve() / 'fallback.yaml'
TIMEZONE = pytz.timezone('CET') TIMEZONE = pytz.timezone('CET')
SCHEDULER_DELAY = 60 SCHEDULER_DELAY = 60
DEFAULT_LATEX_COUNTER_AUX_FILE_EXTENSION = '.cnt' DEFAULT_LATEX_COUNTER_AUX_FILE_EXTENSION = '.cnt'
TERMINAL = 'i3-sensible-terminal'
EDITOR = 'vim'
NEW_EXERCISE_SHEET_HEADER = '\n'.join([ NEW_EXERCISE_SHEET_HEADER = '\n'.join([
r"%! TEX root = ./*.tex", r"%! TEX root = ./*.tex",

View file

@ -20,7 +20,7 @@ from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request from google.auth.transport.requests import Request
from courses import Courses from courses import Courses
from config_loader import USERCALENDARID, TIMEZONE, SCHEDULER_DELAY from config import USERCALENDARID, TIMEZONE, SCHEDULER_DELAY
courses = Courses() courses = Courses()

View file

@ -4,7 +4,7 @@ import warnings
import yaml import yaml
from typing import List from typing import List
from config_loader import ROOT, CURRENT_COURSE_ROOT, CURRENT_COURSE_SYMLINK, CURRENT_COURSE_WATCH_FILE, COURSE_IGNORE_FILE, \ from config import ROOT, CURRENT_COURSE_ROOT, CURRENT_COURSE_SYMLINK, CURRENT_COURSE_WATCH_FILE, COURSE_IGNORE_FILE, \
COURSE_INFO_FILE_NAME, FALLBACK_COURSE_INFO_FILE COURSE_INFO_FILE_NAME, FALLBACK_COURSE_INFO_FILE
from notes import Notes from notes import Notes
from links import Links from links import Links
@ -23,7 +23,13 @@ class Course:
f"file in the directory or add the directory to the course ignore file named" f"file in the directory or add the directory to the course ignore file named"
f" '{COURSE_IGNORE_FILE}' in your root directory ({ROOT})") f" '{COURSE_IGNORE_FILE}' in your root directory ({ROOT})")
self.info = {'title': str(path.stem) + ' (unnamed course)'} self.info = {'title': str(path.stem) + ' (unnamed course)'}
fallback_file = yaml.safe_load(FALLBACK_COURSE_INFO_FILE.open()) if FALLBACK_COURSE_INFO_FILE.is_file():
fallback_file = yaml.safe_load(FALLBACK_COURSE_INFO_FILE.open())
else:
warnings.warn(f"No fallback course info file found. Program might crash if your provided info files do not"
f"have the correct file format or are missing specified values. Provide the fallback course"
f"file at {FALLBACK_COURSE_INFO_FILE}.")
fallback_file = {}
self.info = merge_dictionaries(self.info, fallback_file) self.info = merge_dictionaries(self.info, fallback_file)
self._notes = None self._notes = None
self._links = None self._links = None

View file

@ -2,20 +2,15 @@ from file_list import Files, FileHandle, FileType
from pathlib import Path from pathlib import Path
from typing import Dict from typing import Dict
from utils import normalize from utils import normalize
from config_loader import NEW_EXERCISE_SHEET_HEADER from config import NEW_EXERCISE_SHEET_HEADER
class ExerciseWriteUp(FileHandle): class ExerciseWriteUp(FileHandle):
def __init__(self, root_dir: Path, course): def __init__(self, root_dir: Path, course):
self.root_dir = root_dir self.root_dir = root_dir
self.course = course self.course = course
try: FileHandle.__init__(self, next(self.root_dir.rglob('*.tex')), FileType.tex)
tex_file = next(self.root_dir.rglob('*.tex'))
except StopIteration:
print("No valid '.tex' file found in directory {}, can't instantiate write up here".format(root_dir))
# TODO: raise proper error
exit(1)
FileHandle.__init__(self, tex_file, FileType.tex)
class Exercise: class Exercise:
def __init__(self, course, number: int): def __init__(self, course, number: int):
@ -57,6 +52,7 @@ class Exercises(list):
self._solutions = None self._solutions = None
self._writeups = None self._writeups = None
self._sheets = Files(self.sheet_root) self._sheets = Files(self.sheet_root)
self.ignored_folders = [self.sheet_root, self.solutions_root]
list.__init__(self, (Exercise(self.course, num) for num in map(lambda s: s.number, self._sheets))) list.__init__(self, (Exercise(self.course, num) for num in map(lambda s: s.number, self._sheets)))
@property @property
@ -72,7 +68,7 @@ class Exercises(list):
@property @property
def writeups(self): def writeups(self):
if not self._writeups: if not self._writeups:
dirs = [d for d in self.root.glob('ub*') if d.is_dir()] dirs = list(d for d in self.root.iterdir() if d.is_dir() and d not in self.ignored_folders)
self._writeups = sorted((ExerciseWriteUp(d, self.course) for d in dirs), key=lambda e: e.number) self._writeups = sorted((ExerciseWriteUp(d, self.course) for d in dirs), key=lambda e: e.number)
return self._writeups return self._writeups

View file

@ -17,7 +17,6 @@ literature:
notes: notes:
path: '.' path: '.'
texinputs: '.' texinputs: '.'
build_dir: '.'
master_file: 'master.tex' master_file: 'master.tex'
full_file: 'full.tex' full_file: 'full.tex'
lectures: lectures:

29
scripts/ieeeeqnarray.py Normal file
View file

@ -0,0 +1,29 @@
# A python script designed to parse the contents of an \[ \] in latex (given in the arguments), and make a nice IEEEeqnarray* with correct indent and columns from it.
import sys
indent=len(sys.argv[1])-4 # Indent got by the indent of the leading \[ of equation
topline = sys.argv[2].strip() # Get the content of the first line of the equation
level = 0 # Counts the 'level' of stacked braces
position = 0 # Will save the position of the found = in the top line
parsed_line = '' # Parsed top line
for x in topline:
if x in ['(','[','{']:
level+=1
parsed_line+=x
elif x in [')',']','}']:
level-=1
parsed_line+=x
elif level == 0 and x == '=':
position = len(parsed_line)
parsed_line+='& = &'
else:
parsed_line+=x
# Set correct indent and newline to the parsed line
parsed_line = ' '*(indent+4) + parsed_line[0:-1].strip() + ' \\\\\n'
# Print the output, adding \begin{}, the top line, a new line with '& = &' and \end{}
print(" "*indent +"\\begin{IEEEeqnarray*}{rCl}\n" + parsed_line + ' '*(position+indent+4) + "& = & \n" + " "*indent + "\\end{IEEEeqnarray*}")

View file

@ -46,7 +46,7 @@ def main(args):
arglist = [] arglist = []
if len(args) > 1: if len(args) > 1:
path = Path(args[1]) path = Path(args[1])
arglist = list(path.glob('*.aux')) + list(path.glob('build/*.aux')) arglist = list(path.glob('*.aux'))
else: else:
arglist = ['/home/maximilian/current_course/full.aux'] arglist = ['/home/maximilian/current_course/full.aux']
@ -61,7 +61,6 @@ def main(args):
else: else:
command = selected command = selected
return command.strip() return command.strip()
if __name__ == '__main__': if __name__ == '__main__':

0
src/new-writeup.py → scripts/new-writeup.py Executable file → Normal file
View file

View file

@ -4,7 +4,7 @@ import subprocess
from pathlib import Path from pathlib import Path
from typing import Dict from typing import Dict
from config_loader import LECTURE_START_MARKER, LECTURE_END_MARKER, DEFAULT_IMPORT_INDENTATION, \ from config import LECTURE_START_MARKER, LECTURE_END_MARKER, DEFAULT_IMPORT_INDENTATION, \
DEFAULT_LATEX_COUNTER_AUX_FILE_EXTENSION DEFAULT_LATEX_COUNTER_AUX_FILE_EXTENSION
from window_subprocess import edit from window_subprocess import edit
from lectures import Lectures, number2filename from lectures import Lectures, number2filename
@ -21,7 +21,6 @@ class Notes:
self.full_file: Path = self.root / self.info['full_file'] self.full_file: Path = self.root / self.info['full_file']
self.texinputs: Path = self.root / self.info['texinputs'] self.texinputs: Path = self.root / self.info['texinputs']
self._lectures = None self._lectures = None
self.build_dir: Path = self.root / self.info['build_dir']
@staticmethod @staticmethod
def get_header_footer(filepath): def get_header_footer(filepath):
@ -64,11 +63,8 @@ class Notes:
if not setcounters: if not setcounters:
return '' return ''
if lec - 1 not in lecture_list and self.full_file: if lec - 1 not in lecture_list and self.full_file:
cnt_file = self.full_file.with_suffix(DEFAULT_LATEX_COUNTER_AUX_FILE_EXTENSION)
if not cnt_file.exists():
cnt_file = self.full_file.parent / 'build' / cnt_file.name
return dict2setcounters(parse_counters( return dict2setcounters(parse_counters(
cnt_file, self.full_file.with_suffix(DEFAULT_LATEX_COUNTER_AUX_FILE_EXTENSION),
{'lecture': lec} {'lecture': lec}
)) ))
return '' return ''
@ -102,7 +98,7 @@ class Notes:
def open_full(self): def open_full(self):
result = subprocess.run( result = subprocess.run(
['zathura', str(self.build_dir / self.full_file.with_suffix('.pdf').name)], ['zathura', str(self.full_file.with_suffix('.pdf'))],
stdout=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL stderr=subprocess.DEVNULL
) )
@ -110,7 +106,7 @@ class Notes:
def open_terminal(self): def open_terminal(self):
result = subprocess.Popen( result = subprocess.Popen(
['i3-sensible-terminal'], env=self.environment(), cwd=self.root ['termite'], env=self.environment(), cwd=self.root
) )
def compile_master(self): def compile_master(self):

0
src/open.py → scripts/open.py Executable file → Normal file
View file

View file

@ -2,7 +2,7 @@
import re import re
from pathlib import Path from pathlib import Path
from typing import Dict from typing import Dict
from config_loader import DEFAULT_IMPORT_INDENTATION from config import DEFAULT_IMPORT_INDENTATION
def parse_counters(filepath: Path, break_point: Dict) -> Dict: def parse_counters(filepath: Path, break_point: Dict) -> Dict:

View file

@ -2,6 +2,7 @@
from courses import Courses from courses import Courses
from exercises import Exercises from exercises import Exercises
from rofi import rofi from rofi import rofi
from config import MAX_LEN
import sys import sys

View file

@ -2,7 +2,7 @@
from courses import Courses from courses import Courses
from rofi import rofi from rofi import rofi
from utils import generate_short_title from utils import generate_short_title
from config_loader import MAX_LEN from config import MAX_LEN
notes = Courses().current.notes notes = Courses().current.notes
lectures = notes.lectures lectures = notes.lectures

View file

@ -3,7 +3,7 @@ from datetime import datetime
from typing import Dict from typing import Dict
import warnings import warnings
from config_loader import MAX_LEN from config import MAX_LEN
def beautify(string): def beautify(string):

View file

@ -4,20 +4,14 @@ import subprocess
from pathlib import Path from pathlib import Path
import os import os
from config_loader import TERMINAL, EDITOR
def edit(filepath: Path, rootpath: Path = None, env=os.environ, servername='tex lecture'): def edit(filepath: Path, rootpath: Path = None, env=os.environ, servername='tex lecture'):
if not rootpath: if not rootpath:
rootpath = filepath.root rootpath = filepath.root
subprocess.Popen([ subprocess.Popen([
TERMINAL, "termite",
"-e", "-e",
EDITOR, f"vim --servername {servername} --remote-silent {str(filepath)}"
f"--servername",
f"{servername}",
f"--remote-silent",
f"{str(filepath)}"
], env=env, cwd=str(rootpath)) ], env=env, cwd=str(rootpath))

View file

@ -1,53 +0,0 @@
import shutil
from pathlib import Path
import os
import sys
# We read a configuration file for university setup that is located
# in $XDG_CONFIG_HOME/university-setup/config.cfg
def get_default_file(name: str) -> Path:
# System installation
f1 = Path('/etc/opt/mkessler/university-setup') / name
# no installation, try relative path
f2 = Path(__file__).parent.parent / 'config' / name
if f1.exists():
return f1
if f2.exists():
return f2
raise FileNotFoundError(f'Default file {name} not found, bad installation.')
# Ensure that config.py and fallback.yaml are present
# in the config directory and returns this directory
def get_config_dir() -> Path:
if 'XDG_CONFIG_HOME' in os.environ.keys():
xdg_config_home = Path(os.environ['XDG_CONFIG_HOME']).resolve()
else:
xdg_config_home = Path('~/.config').expanduser().resolve()
config_file = xdg_config_home / 'university-setup' / 'config.py'
fallback_file = xdg_config_home / 'university-setup' / 'fallback.yaml'
config_file.parent.mkdir(exist_ok=True, parents=True)
# Copy defaults if not present already
if not config_file.exists():
shutil.copy(get_default_file('config.py'), config_file)
print(f'Initialized default config file at {str(config_file)}.')
if not fallback_file.exists():
shutil.copy(get_default_file('fallback.yaml'), fallback_file)
print(f'Initialized default fallback file at {str(fallback_file)}.')
return config_file.parent.absolute()
FALLBACK_COURSE_INFO_FILE = get_config_dir() / 'fallback.yaml'
sys.path.append(str(get_config_dir()))
# Note that IDEs will probably complain about this, since they cannot find the module right now
# they might also flag this as an unused import, but the imported config values
# are in turn imported by all the oder scripts
from config import *
# future: potentially check that config in fact defines all symbols that we need