Show HN: Greg – a simple “cal” clone written in C

(greg-calendar.vercel.app)

60 points | by zamfofex 1279 days ago

12 comments

  • JdeBP 1278 days ago
    The program that you likely know as "cal" is itself a clone, named "ncal" and written by Wolfgang Helbig in the 1990s. It was preceded by a clone written for BSD by Kim Letkeman in 1989, which was in turn a replacement for a "cal" written by Bill Joy.

    * https://svnweb.freebsd.org/csrg/usr.bin/cal/cal.c?view=log

    * https://manpages.debian.org/buster/bsdmainutils/ncal.1.en.ht...

  • caymanjim 1278 days ago
    This appears to be a very limited subset of Unix standard cal, without a single new feature, and missing some of the basic cal features (like 'cal 2020').

    Writing something like this is a great way for someone to learn programming basics, but why is this on the HN front page? It's not particularly educational or interesting and has no practical utility for anyone.

    • netmare 1278 days ago
      I love it. As an older Windows coder, it's one of the few things on HN I can fully grasp. There's no monads/shaders/ML/business involved--just plain old C. Almost everything else posted here makes me feel depressed and inadequate.

      Some people view abstraction as something they can happily ignore. They use libraries, upon frameworks, in VMs, on blockchains, just so that they can pile on. If all we do is add, there's no purpose. Absolutum obsoletum.

      Maybe it's some sort of existential crisis I'm going through, but I'm starting to ditch many advanced programs/services in favor of simple tools I can fully build and understand myself. YMMV, of course.

      • miccah 1277 days ago
        > simple tools I can fully build and understand myself

        This reminds me of an excerpt from PoC||GTFO.

        "[W]hen you’re tooling around with a from-scratch tool and your neighbors tell you to use this or use that, look ’em in the eye and say, “I’m building my own fucking birdfeeder.”" [1]

        [1] https://q3k.org/birdfeeder.pdf

      • xupybd 1278 days ago
        Have you looked into these tools? https://suckless.org/
      • easytiger 1278 days ago
        > Maybe it's some sort of existential crisis I'm going through, but I'm starting to ditch many advanced programs/services in favor of simple tools I can fully build and understand myself. YMMV, of course

        It isn't just you. A lot of my own energy wasted on tools and other things that don't really help you solve problems.

      • cblum 1278 days ago
        I share the feeling. You're not alone :)
    • zamfofex 1278 days ago
      Well, although not very compelling, a couple new features are (1) you can highlight any and multiple days of the month (with different colors, even), and (2) you can choose the first day of the week more freely.

      I didn’t want for it to get to the front page at all, by the way! I was honestly not expecting this to get more than the three points it got yesterday, to be honest!

    • pvg 1278 days ago
      • caymanjim 1277 days ago
        Fair enough. I didn't realize there were Show HN specific rules.
  • zamfofex 1279 days ago
    Hello, everyone! Having known about this website for a while, this is my first time deciding to create an account and making a post.

    I have (somewhat) recently decided to start working on a simple C project. It is a “replacement” for the Unix utility ‘cal’.

    Of course, it is far from actually hoping to replace anything, it is more of a clone with some different functionalities than anything else.

    One of my friends mentioned that in his classes for his degree in computer science, he was assigned to fix a ‘cal’ clone the teacher had written in Java.

    Since I was always kinda interested by calendars and timekeeping, that sparked some interest in me. I decided to start the project because I felt like it would be fun to try to come up with something simple to display the calendar.

    I chose C because it is a (relatively) straightfoward language, and it is very popular, so basically anyone can understand it.

    Initially, the program was really short, but lacked a lot of functionalities. As the time went on, and I felt periodically bored enough to work on it, I decided to sacrifice some simplicity for more useful features.

    I feel like now it has gotten to the point in which it is “mature enough”, and could potentially be used by people who regularly use ‘cal’.

    Don’t mind the bugs too much. (But of course, feel free to bring them up!) One that I know exists and just haven’t gotten around fixing yet is the overflow handling for my function for parsing integers.

    I’m looking forward to know what people might think about it! Any kind of feedback is really appreciated, be it regarding functionality, code style, or anything else!

    P.S., You can try it through a Web interface through the first link on the website. Try e.g. ‘greg -yh’ for output very similar to ‘cal’.

    • JdeBP 1278 days ago
      You haven't done a complete clone until you have included Latin, by the way.

      * https://unix.stackexchange.com/q/572653/5132

    • xzlzx 1278 days ago
      Although this looks like it has a ways to go before being a viable replacement to cal, I give you props for putting yourself out there and gathering feedback. That's never an easy thing to do.
    • raldi 1278 days ago
      The link could really use a quick description of why someone would want to install it (e.g., features cal doesn’t have) and a copy of the manual.
      • zamfofex 1278 days ago
        I made it because I felt like it would be fun! There is not much reason to actually install it if you already have ‘cal’, unless for some reason you really want your weeks to start on e.g. Wednesday.
  • DiabloD3 1278 days ago
    My hands are physically unable to write "gre" and not finish with "p".
    • parenthesis 1278 days ago
      Put your right hand behind your back first (in standard qwerty touch-typing, `greg' is an all-left-hand word).
    • Skunkleton 1278 days ago
      Easier?

      $(rev <<<gerg)

  • petemc_ 1278 days ago
    Nice, it even has the missing weeks in September 1752..

      $ wapm install zamfofex/greg@2020.10.10
      Package zamfofex/greg@2020.10.10 installed successfully!
      → Installed commands: greg
      $ cal 9 1752
         September 1752   
      Su Mo Tu We Th Fr Sa
             1  2 14 15 16
      17 18 19 20 21 22 23
      24 25 26 27 28 29 30
    • zamfofex 1278 days ago
      Well, I wanted to mention that to use the program, you should type ‘greg’, not ‘cal’. But it does also skip those couple days in 1752 with the same arguments: ‘greg 9 1752’.
      • petemc_ 1278 days ago
        Whoops! Should have had my coffee before commenting. Cheers.
    • EdSchouten 1278 days ago
      I always find that behaviour somewhat arbitrary, as it was just the British empire that switched from the Julian to the Gregorian calendar that month. Most of mainland Europe already switched around 1582.
  • raverbashing 1278 days ago
    Ah yes the util I love to hate

    There's nothing easier than just typing cal on the terminal and getting the calendar. Cool

    But the one in Linux works in one way, the one in MacOS works in a different way and if you try to install gcal it's still different.

    And it also has these crazy usability issues. No, I don't want the calendar of year 11 thanks.

    • raldi 1278 days ago
      Big upvote for that last point.

      I got into the habit of never looking up a specific month just because of getting repeatedly bitten by this hazard. If I want to see November I'll type `cal 2020` and eyeball the whole year.

  • mouldysammich 1278 days ago
    Semi unrelated, but I had never seen that webasembly site wapm, its pretty cool!
  • eggy 1277 days ago
    I have never used cal or Greg, but it reminds me of the J programming language's calendar function:

    calendar 2020 //for the full year in one row

    3 4 $ calendar 2020 //full year in 4 row/3 column layout

    You can do all sorts of ranges and views too.

    Granted it doesn't show the missing days in September 1752 like one poster (petemc_21) replied in this thread, but I keep the J term open on my desktop for all sorts of calculator/programming goodies. Nothing geekier than an ASCII calendar at your fingertips in a full programming terminal!

  • tzs 1278 days ago
    Calendars can be fun. When I realized that my HP-48SX display had enough lines and was wide enough to display a one month calendar, I wrote one.

    My first try was annoyingly slow, and I determined that the problem was with the code to actually draw the calendar. Going through each day and telling it "draw this number here" was just not efficient enough.

    I switched to a string based approach. Here is what it would look like in Python. This draws a cal-style calendar or a month given the day of the week of the first day of the month (Sunday == 0, Monday == 1, ...) and the number of days in the month:

      def print_cal(first_day, num_days):
        hdr_str = "Su Mo Tu We Th Fr Sa "
        cal_str = "                  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 "
        offset = 3*(6-first_day)
        cal_flat = cal_str[offset:18+3*num_days]
        cal_flat += "                     "
        print(hdr_str)
        print(cal_flat[0:21])
        print(cal_flat[21:42])
        print(cal_flat[42:63])
        print(cal_flat[63:84])
        print(cal_flat[84:105])
    
    All the string operations were primitives in the calculator's slow interpreted language, implemented in fast assembly language, so this was very fast.

    Calculating the first day and number of days for a year/month was in the slow interpreted language, but that isn't much computation so it wasn't noticeable. In Python, it would be something like this:

      def first_and_length(year, month):
        # Correction for centuries 16, 17, 18, 19
        # Repeats every 4 centuries.
        century_table = [2, 0, 5, 3]
        # Correction for each month for years that are not leap years.
        # For leap years, need to subtract 1 for January and February.
        month_table = [4, 0, 0, 3, 5, 1, 3, 6, 2, 4, 0, 2]
        month_length = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        num_days = month_length[month-1]
        first_day_on = 1
        first_day_on += century_table[(year//100)%4]
        first_day_on += year%100 + (year%100)//4
        first_day_on += month_table[month-1]
        if month <= 2 and year%4 == 0:
            if year%400 == 0 or year%100 != 0:
                first_day_on -= 1
                if month == 2: num_days += 1
        return first_day_on%7, num_days
  • sgt 1278 days ago
    cal is supposed to optionally take YYYY as the only parameter. When running greg 2020 I get the usage screen.
    • zamfofex 1278 days ago
      ‘greg’ is not able to display more than one month by itself. If you only provide one argument, it’ll consider it as a month number, e.g. ‘greg 9’ for September (of the current year).

      I had made a simple Bash script that displayed the calendar of a given month using ‘greg’ with ‘paste’, ‘columns’, and some other common utilities, but I haven’t uploaded it anywhere yet.

  • zabzonk 1278 days ago
    Any reason for not using C Standard Library functions such as (for example) strlen and isdigit?
    • zamfofex 1278 days ago
      Not really, to be honest!

      Originally, I had written a linker script that could generate really small ELF executables, using the information I found on this website: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.htm...

      That meant I had to implement functions for myself, including ‘write’ in x86 assembly.

      As soon as I started storing function pointers, however, my program started to segfault, and I didn’t bother to figure out how to fix it. Do I stopped providing those builds on the website, and decided to start using other standard library functions, such as the time‐related functions.

      Since I already had those functionalities there, I decided to keep them anyway. It would make sense to reuse the library functions, though, I agree!

  • bla3 1278 days ago
    Nice!

    The time math in the source looks like stuff gmtime()/mktime() do internally -- maybe you could delete some code by using these and working with Unix timestamps.