Posts

Showing posts from 2023

GNU Emacs as a Shopping App

Image
  How do you find the best price for items while shopping online? You can go to each website and compare yourself manually. Or let Emacs do the hard work for you!! You can start with a shopping list in a normal buffer. shop-mode minor mode allows you to search, compare and add products to your cart across multiple providers (presently Bigbasket and Jiomart ). You can finish the payment on the provider's website. Note: You can use (url-cookie-store) for managing cookies. Keybindings s     Search the item o     Order the results by price, unit price, brand etc. q     Quit Unit price comparison allows better deals   Config (require 'shop)   ;; For webp image support (setq image-converter 'imagemagick)  ;; An example. Add appropriate cookies changing name, value and domain. (url-cookie-store "_bb_vid" "NTY2NzQ4MDAwNw==" "-1" "www.bigbasket.com" "/" t)   Code https://github.com/atamariya/tumblesocks/blob/dev/shop.el

Stream ListenBrainz.org Music Playlist in GNU Emacs

Image
    Here's an Emacs Multimedia System (EMMS) extension for streaming ListenBrainz.org music playlist using mpv player (with ytdl support). Irrespective of how satisfied you are with your music streaming service, you should plan for maintaining a playlist of your favorite music in an open format. The popular service might be forced to close down because of non-profitability even when you are willing to pay for ad-free music streaming. e.g. Worldspace radio customers even paid for the device in addition to the subscription fees. The code uses following function from tumblesocks codebase. In case you don't use tumblesocks, you'll need to define it yourself. (defun tumblesocks-api-process-response (&optional service)   "Process Tumblr's response in the current buffer, returning JSON or signaling an error for other requests."   (decode-coding-region (point-min) (point-max) 'utf-8-dos)   ;; the following copied from url.el   (goto-char (point-min))   (sk

Zen Emacs: First Look

Image
  Zen is a minimal Emacs ( pl. Emacsen ) with multi-thread support . It is a fork of Zepl . (Edit 3/9/23: Zen Emacs is a better name compared to Zep). Demo The video demonstrates: Split window Indirect/cloned buffer - same content but different points (cursor) Asynchronous shell command (top) execution and view update Parallel editing while the command runs in the other window   Components Zepl - Editor backend tinylisp - Lisp interpreter ncurses - Terminal UI Code https://gitlab.com/atamariya/tinylisp (dev branch)  

Tinylisp and Multi-threaded Emacs

Image
TAME-ing the beast!! Here's a fork of tinylisp and a glimpse of a possible multi-threaded future. Below is the content of the file a.el in the demo. It creates one read thread which waits for non-nil value of global-var and a set thread which sleeps for 5s before modifying global-var and notifying the waiting threads. Since these are running in separate threads, main loop is free for user input. (define list (lambda args args)) (define defun (macro (f v . x) (list 'define f (list 'lambda v (cons 'progn x))))) (setq make-condition-variable make-cond) (setq condition-wait cond-wait) (setq condition-notify cond-signal) (setq message p) (setq sleep-for sleep) (setq global-var nil) ;; Create a mutex and an associated condition variable (setq mutex (make-mutex "mutex")) (setq cond-var (make-condition-variable mutex "cond-var")) ;; Read and set functions used by read and set threads (defun set-global-var ()   (mutex-lock mutex)   (sleep 5)   (setq global-

GNU Emacs as a lightweight IDE - Assembly

Image
CEDET support for Assembly language Auto-completion using company and speedbar outline view Jump to label Jump to include file Auto-completion using company Speedbar outline view     ASM file extensions supported - .s, .S and .asm   Grammar file: https://gitlab.com/atamariya/emacs/-/blob/dev/admin/grammars/asm.wy

Molly Kernel

Image
Molly kernel is a bare kernel (32kB size) for x86 based on JamesM's kernel development tutorials for learning purpose. It also adds keyboard support from Bran's kernel development tutorials .   Build The original version of the code is in master branch . The modifications (bug fixes + enhancements) are in dev branch .   ;; Pre-requisites sudo apt install nasm gcc make kvm bochs   git clone https://gitlab.com/atamariya/molly.git make -C src ./update_image.sh ./run.sh     ;; Optional ;; Run floppy image kvm -fda floppy.img     ;; Run kernel binary kvm -kernel src/kernel -initrd initrd.img     Debugging You can use GDB to debug the kernel while executing it under qemu. Start qemu with "-s -S" flags and attach GDB remote session using "target remote localhost:1234". Make sure you match the architecture (i386 in this case) for qemu command and the kernel.   qemu-system- i386 -kernel src/kernel -initrd initrd.img -s -S     References Debugging 16-bit in QEMU

Meta git (mgit)

Image
  Meta git (mgit) is a wrapper around magit , which is a wrapper around git . If the output looks familiar, it's because it's the output from command git status -v. For the discerning eye, it uses the font-lock defaults from diff mode (notice the highlight on ;;). diff-mode uses repeated diff commands to highlight the refinements. Use diff-mode or diff-refine-hunk if you must have the eye-candy. Motivation Magit is a handy tool for working with git repository in GNU Emacs. However, if you work with a large enough repository, you'll hit a performance road-block. Here's an attempt to deconstruct the problem and find a solution. Magit provides an information rich dashboard for git status. However, this comes with multiple calls to git command. If you run M-x magit-toggle-verbose-refresh and then run magit-status, you'll see the following output: Refreshing buffer ‘magit: src<anand>’...   magit-insert-error-header                          2.031e-06   magit-inser

Git graph in GNU Emacs

Image
  Get a decent view of git tree in GNU Emacs (M-x magit-pg-repo ). By default, it draws the graph with last 100 commits. If you want a different behaviour, edit the following constant. (defconst magit-pg-command   (concat "git --no-pager log --branches --decorate=full "           "--pretty=format:\"%H%x00%P%x00%an%x00%ar%x00%s%x00%d\" "           " -n 100 ")   "The command used to fill the raw output buffer.")     If you want to use the script in terminal ( temacs -batch -l $PWD/magit-pretty-graph.el -f magit-pg-repo ), add the following path (adjust for versions) to the top of the script and uncomment line 238. (setq path '("~/.emacs.d/elpa/magit-20220603.1738/"          "~/.emacs.d/elpa/compat-28.1.1.1/"          "~/.emacs.d/elpa/dash-20220602.2113/"          "~/.emacs.d/elpa/magit-section-20220513.1429/"          "~/.emacs.d/elpa/with-editor-20220506.420/"          "~/.emac

GNU Emacs as a LISP interpreter

Image
  After applying the following patch, you can run GNU Emacs as a standalone LISP interpreter for batch usage. It basically disables the command loop and non-essential symbols in batch mode.   temacs is Emacs sans any bootstrap elisp code. It is the first artifact generated during the Emacs build process. So you might not find it in your package installation. You can use the emacs binary too for the same effect - just understand that underneath they are not the same.   modified   src/keyboard.c @@ -1067,6 +1067,7 @@ command_loop (void)      while (1)        {      internal_catch (Qtop_level, top_level_1, Qnil); +    if (!noninteractive)      internal_catch (Qtop_level, command_loop_2, Qnil);      executing_kbd_macro = Qnil;   @@ -2631,9 +2632,9 @@ read_char (int commandflag, Lisp_Object map,    if (minibuf_level == 0        && !end_time        && !current_kboard->immediate_echo +      && ! noninteractive        && (this_command_key_count > 0       

Towards GNU/MINIX - libstdc++

Image
Cross-compiled C++ program running on Minix   To compile a C++ program, we need C++ standard library. While Clang libc++.so comes with Minix distribution, GCC version of libstdc++.so has to be cross-compiled . Interestingly, while GNU C library Glibc is a separate project, libstdc++ is part of the GCC project. In other words, you can use a different C library (like musl or ulibc) with GCC if you want. Lessons Learnt Clang uses inline namespaces by default whereas GCC does not. anand@PureBook:~/work/minix/usr/lib$ nm -s libstdc++.so | c++filt | grep cout 00328a20 b __gnu_internal::buf_cout_sync 00329080 b __gnu_internal::buf_wcout_sync 00328ae0 b __gnu_internal::buf_cout 00329140 b __gnu_internal::buf_wcout 003285c0 B std::cout 00328840 B std::wcout anand@PureBook:~/work/minix/usr/lib$ nm -s libc++.so | c++filt | grep cout 000c2b00 B std::__1::cout 000c2c54 B std::__1::wcout   You can use objcopy to alter symbol name in an object file or library. mthread.h has provisions for supporti

Micro Emacs on GNU/Minix

Image
Following the filesystem creation on GNU/Minix, the next step is to port an application. Here's a basic port of Micro Emacs (v3.5) running on GNU/Minix (v3.3.0). ./configure --without-curses     Since configure doesn't support Minix, we need to manually edit the CC and LIBOBJS (for reallocarray() function) variable in generated Makefile. LIBOBJS =  ${LIBOBJDIR}fparseln$U.o ${LIBOBJDIR}strlcpy$U.o ${LIBOBJDIR}strlcat$U.o ${LIBOBJDIR}strtonum$U.o ${LIBOBJDIR}reallocarray$U.o   Also we need following patches. modified   src/def.h @@ -12,7 +12,8 @@    #include    "config.h"   -#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) +#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) \ +  || defined(__minix)  # include    <sys/queue.h>  # include    <sys/tree.h>  # ifdef __FreeBSD__ @@ -23,15 +24,14 @@  #else /* __NotBSD__, DragonFly BSD, or macOS */  # include    "queue.h"  # include    "tree.h" +#ifd

Towards GNU/MINIX - Filesystem

Image
In this post, we will look at populating Minix filesystem with some files of our own (specifically the welcome message) using GNU tools. Extract files from distribution CD into three folders - isodir, root.dir and usr.dir. Create a text file grub-hd.cfg . p0 denotes first partition. insmod part_msdos menuentry "GNU MINIX 3" {     multiboot /kernel rootdevname= c0d0p0 verbose=1          module /mod01_ds     module /mod02_rs     module /mod03_pm     module /mod04_sched     module /mod05_vfs     module /mod06_memory     module /mod07_tty     module /mod08_mfs     module /mod09_vm     module /mod10_pfs     module /mod11_init }   Create a text file partition.txt for your partition definition . label: dos label-id: 0x40fbf996 device: minix.img unit: sectors sector-size: 512 minix.img1 : start=        2048, size=         +64M, type=81, bootable     The script below will create a disk image. Then create a Minix partition (code 81). For creating the filesystem (MinixFS v3), you'

Creating a bootable hard-disk image with Grub2

Here's a shell script for creating a bootable hard-disk image with Grub2 (v2.06). You need parted, kpartx and grub2. It's a derived version of original script here . # Create the actual disk image - 20MB dd if=/dev/zero of=disk.img count=20 bs=1048576   # Make the partition table, partition and set it bootable. parted --script disk.img mklabel msdos mkpart p ext2 1 100% set 1 boot on   # Map the partitions from the image file kpartx -a disk.img   # sleep a sec, wait for kpartx to create the device nodes sleep 1   # Make an ext2 filesystem on the first partition. mkfs.ext2 /dev/mapper/loop0p1   # Make the mount-point mkdir -p /mnt   # Mount the filesystem via loopback mount /dev/mapper/loop0p1 /mnt   # Copy in the files from the staging directory # cp -r build/* /mnt   # Create a device map for grub mkdir -p /mnt/boot/grub echo "(hd0) /dev/loop0" > /mnt/boot/grub/device.map # Use grub2-install to actually install Grub. The options are: #   * No floppy polling. #   *

Towards GNU/MINIX - Cross-compiler

Image
Cross-compiled executable running on Minix   In this post, we will cross compile a binary on Linux using GNU tools and run the same in Minix with a minimal setup. Build a generic cross-compiler You can build a generic ELF compiler for x86 platform following the instructions here .   Copy C runtime files from the distribution CD. $PREFIX and $TARGET are variables set in previous step. $ sudo kpartx -a myos.iso $ sudo mount /dev/mapper/loop0p3 -t minix /mnt $ mkdir usr $ cp /mnt/lib usr $ cp /mnt/include usr $ sudo umount /mnt $ ln -s $PWD/usr $PREFIX/$TARGET/   Create hello.c  #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) {  printf("Hello\n");  return 0; }   Compile and link hello.c . Use -static for static linking and -dynamic-linker /usr/libexec/ld.elf_so (use appropriate ld path) for dynamic linking. $ i686-elf-gcc -o hello.o -c hello.c $ i686-elf-ld -static -m elf_i386 -o hello -L./usr/lib ./usr/lib/crt0.o ./usr/lib/crti.o ./usr/

Towards GNU/MINIX - Bootloader

Image
  GNU/MINIX = GNU Tools with MINIX kernel Repackage MINIX 3.3 kernel to boot with GRUB 2.06 MINIX CD has three partitions - boot, ramdisk image and usr filesystem image. It uses NetBSD bootloader and userland tools. $ sudo sfdisk -l minix.iso  Disk minix.iso: 577.53 MiB, 605581312 bytes, 1182776 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x00000000 Device     Boot Start     End Sectors   Size Id Type minix.iso1          0   12287   12288     6M 81 Minix / old Linux minix.iso2      12288   82087   69800  34.1M 81 Minix / old Linux minix.iso3      82088 1182775 1100688 537.4M 81 Minix / old Linux   Extract files required for booting from boot partition by mounting it and copy the files to isodir . $ sudo mount minix.iso /mnt mount: /mnt: WARNING: source write-protected, mounted read-only. $ ls /mnt boot      mod01_ds  mod04_sched   mod07_tty  m