Just In Time Lazy-Loading

In personal computing, there are multiple scenarios where Just in time (JIT) lazy-loading is desirable since what can be shown to the user at any point of time is limited by the screen real estate.

This involves two steps:

  1. Detect changes
  2. Refresh the visible changed part during idle time

Consequently, a framework to support these scenarios is desirable. Specific logic related to refreshing, like image loading or font coloring, can be encapsulated in individual functions which will be called by the framework.


Detect Changes

While editing a document, the number of changes will be huge. So it's better to track the extent of changes or the changed region instead of individual changes. When the file is loaded, the whole file is considered to be changed.


Refresh the changed part in idle time

Run a timer which kicks off when the computer is idle i.e. the user is not interacting with the computer. This is to ensure that the user never faces a lag in his interaction.

If an idle timer is not available, after every change cancel the current one-shot timer and add a new one.

Points to consider while refreshing:

  • If there are changed parts in the document but it's not visible, there's no point in refreshing the same.
  • Keep track of pending functions to run to avoid redundant runs.
  • Before running a function check if user input is pending. We want to remain as responsive as possible without user having to cancel a task in between.
  • In case of deletion, start and end might be the same. However, ensure atleast a character is marked so that the refresh cycle can begin.
  • If a process is expected to take time e.g. fetching image from a URL, use a separate idle timer function for fetching the image.

 

Refresh Functions

A refresh function receives the extent of changed region and visible region i.e. the beginning and end points. However, it should expand the region considered based on the context (context region). e.g. a line comment function needs to operate in the context of whole line. At the very minimum, a context will include the word (or symbol in case of programs) being edited outside of string and comments.

A refresh function should refresh the whole context region within the visible area. The region outside the visible area should be marked for future refresh. However, if the context cannot be established within the visible region, the function should skip refresh.

A few categories of refresh functions are listed below:

1. Static Keywords

These are keywords defined in the specifications for a programming language.

2. Dynamic Keywords

These are type, function and variable defined in the code. These might change in each run. e.g. a variable might be deleted or its name might be changed.

3. Preprocessor

Preprocessor needs to be dealt with separately. e.g. In C, preprocessor ifdef can make a big chunk of code inactive.

4. Images

Always insert a placeholder image with information of the final image to be rendered. When the placeholder comes into view, the information is used to fetch the image and is inserted in place of the placeholder. Some typical use cases would be -

  1. Fetching image from a URL
  2. Extracting image from an archive

5. Strings

Changing inside a string region doesn't affect semantic context. However deleting quote character at start should unfontify till the end. Deleting quote character at end should fontify till the next quote character.

6. Comments

Changing inside a comment section doesn't affect semantic context. However, deleting start comment character effects whole line for single line comment and multiple lines for multiline comment. Deleting comment end character at end should fontify till the next comment end character.

7. Doc comments

Documentation in comments might have its own set of syntax e.g. Javadoc or perldoc.

 

GNU Emacs

GNU Emacs uses the hook fontification-functions for fontification. When enabled (fontification-functions has a non nil function symbol), the display engine (C code) calls this function (Lisp code) with the first location where fontified property is nil. The function is expected to set the font-lock-face property value with appropriate value and fontified property to a non nil value. The special face property value always applies.

Warning: Don't try to edebug the fontification function - you run the risk of Emacs hanging!

Only generic functions should be added to a global hook. Any specialized function should be added to local hook. This way the function will not need special checks before execution.


Minor modes

semantic-font-lock-mode depends on CEDET package. Language keywords are obtained from semantic-lex-keywords. Dynamic keywords are generated from parsed tags.  semantic-fl-update-keywords ensures only symbols from valid imports are highlighted.
(require 'jit)
 
image-font-lock-mode
semantic-font-lock-mode
 
;; Configure timer delay
(setq jit-delay 0.1)
(jit-timer)
 

Image insert functions

;; In case JIT image-font-lock-mode is not supported, img is displayed (primarily for backward compatibility)

(jit-insert-image-from-file file &optional img w)
(jit-insert-image-from-url url &optional img w)
(jit-insert-image-from-archive file &optional img w)
 
 

Code


Comments

Popular posts from this blog

GNU Emacs as a Comic Book Reader

Data Visualization with GNU Emacs

Tinylisp and Multi-threaded Emacs