Not a member of Pastebin yet?
                        Sign Up,
                        it unlocks many cool features!                    
                - #!/usr/bin/env rdmd
 - /** A calendar application to inspired by github:quickfur/dcal.
 - * by ARaspiK <[email protected]>
 - * The final product is envisioned to have every feature that util-linux/cal has, and is
 - * meant to be a suitable and hopefully faster replacement of it.
 - * This uses component-based programming (I first read of it and was inspired by it from
 - * https://wiki.dlang.org/Component_programming_with_ranges) and is easy to read,
 - * understand, and modify.
 - * Armed with the understanding of the article's "Component Programming" section:
 - * Source: List of dates
 - * Target: Line-by-line formatted calendar with column-aligned day numbers and month
 - * names, with distinct "month blocks".
 - * Steps: dates -> by month -> format into set of lines -> add month name (centered) ->
 - * join together month blocks -> formatted calendar
 - * Configuration (via options):
 - * First day as monday/sunday.
 - * Show X months (starting with / around / ending with a specified date)
 - * Show a full year / current month / X months / this week / X weeks
 - * Copyright (c) 2018 ARaspiK <[email protected]>
 - *
 - * Permission is hereby granted, free of charge, to any person obtaining
 - * a copy of this software and associated documentation files (the
 - * "Software"), to deal in the Software without restriction, including
 - * without limitation the rights to use, copy, modify, merge, publish,
 - * distribute, sublicense, and/or sell copies of the Software, and to
 - * permit persons to whom the Software is furnished to do so, subject to
 - * the following conditions:
 - *
 - * The above copyright notice and this permission notice shall be
 - * included in all copies or substantial portions of the Software.
 - *
 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 - *
 - * [Except as contained in this notice, the name of ARaspiK
 - * shall not be used in advertising or otherwise to promote the sale, use
 - * or other dealings in this Software without prior written authorization
 - * from ARaspiK.]
 - */
 - module calendar;
 - import std.algorithm; // For everything ranges
 - import std.array; // Arrays and ranges
 - import std.datetime; // Getting date and getting basic info about it
 - import std.getopt; // We use standard parsing methods
 - import std.range; // RANGES EVERYWHERE
 - import std.stdio; // Input/Output anyone?
 - import std.string; // String manipulations during formatting
 - struct CalendarConfig {
 - enum StartDay {sun = false, mon = true}
 - StartDay startOfWeek = StartDay.sun;
 - ubyte monthsPerRow = 3;
 - }
 - static CalendarConfig config;
 - /** Checks if the input type is an input range with element type Date. */
 - enum isDateRange(R) = isInputRange!R && is(ElementType!R : Date);
 - // Quick static test
 - static assert(isDateRange!(typeof(dateList!(a => a.year > 2013)(2013))));
 - /** Get a list of dates starting from @arg year, and keep going until @targ pred is
 - * satisfied.
 - */
 - auto dateList(alias pred)(short year) {
 - return Date(year, 1, 1).recurrence!((a,n) => a[n-1] + 1.days).until!(pred);
 - }
 - /** Convernience function to be used with chunkBy to split by months. */
 - auto myMonth(Date a, Date b) {
 - return a.month == b.month;
 - }
 - /** Convernience function to be used with chunkBy to split by weeks. */
 - auto myWeek(Date a, Date b) {
 - if (config.startOfWeek == CalendarConfig.StartDay.mon)
 - return a.isoWeek() == b.isoWeek();
 - return (a + 1.days).isoWeek() == (b + 1.days).isoWeek();
 - }
 - /** Returns the first day of the week by our configuration. */
 - auto firstDayOfWeek() {
 - if (config.startOfWeek == CalendarConfig.StartDay.mon)
 - return DayOfWeek.mon;
 - return DayOfWeek.sun;
 - }
 - /** Returns the last day of the week by our configuration. */
 - auto lastDayOfWeek() {
 - if (config.startOfWeek == CalendarConfig.StartDay.mon)
 - return DayOfWeek.sun;
 - return DayOfWeek.sat;
 - }
 - /** Formats a single given week into a fixed-length string. */
 - auto formatWeek(Range)(Range week)
 - if (isDateRange!Range) {
 - auto firstDayInWeek = week.front.dayOfWeek;
 - string result = week.map!(d => format!" %2d"(d.day)).join();
 - if (firstDayInWeek != firstDayOfWeek())
 - return result.rightJustify(7 * 3);
 - if (week.front.dayOfWeek /* Last day */ != lastDayOfWeek())
 - return result.leftJustify(7 * 3);
 - return result;
 - }
 - /** Creates an auto-centered month title given the month. */
 - string monthTitle(Month month) {
 - static immutable string[] monthNames = [
 - "January", "Feb", "March", "April", "May", "June",
 - "July", "August", "September", "October", "November", "December"
 - ];
 - return monthNames[month - 1].center(7 * 3);
 - }
 - /** Formats a month by joining monthTitle and calls to chunkBy!myWeek. */
 - auto formatMonth(Range)(Range monthDays)
 - if (isDateRange!Range) {
 - return chain([monthDays.front.month.monthTitle], monthDays.chunkBy!myWeek.array.formatWeek());
 - }
 - /** Formats blocks of pre-formatted months (ranges of lines) into horizontally-placed
 - * blocks, without regard to how many go on each block.
 - */
 - auto blockMonths(Range)(Range months, string sep)
 - if (isForwardRange!Range && is(ElementType!(ElementType!Range) : string)) {
 - struct MonthRow {
 - Range months;
 - string sep;
 - bool isEmpty;
 - this(Range months, string sep) {
 - this.months = months;
 - this.sep = sep;
 - isEmpty = months.empty;
 - }
 - @property bool empty() {return isEmpty;}
 - @property auto front() {
 - return months.save.map!(a => a.front.leftJustify(7 * 3)).join(sep);
 - }
 - void popFront() {
 - assert (!empty);
 - isEmpty = true; // Assume we're out of data
 - ror.each!((ElementType!Range r) {
 - if (!r.empty) {
 - r.popFront();
 - if (!r.empty) isEmpty = false;
 - }
 - });
 - }
 - }
 - return MonthRow(months, sep);
 - }
 - /*auto formatYear(short year) {
 - return dateList!(a => a.year > year)(year).chunkBy!myMonth.chunks(config.monthsPerRow)
 - .map!(r => r.map!formatMonth.array().blockMonths(" ").join("\n")).join("\n\n");
 - }
 - int main(string[] args) {
 - }*/
 
Advertisement
 
                    Add Comment                
                
                        Please, Sign In to add comment