Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch diff-keyboard-navigation Excluding Merge-Ins
This is equivalent to a diff from 9b263d87c1 to facfbbd552
|
2026-01-11
| ||
| 17:04 | Modify the accordion panel style to hide only vertical overflow and keep the box shadows of selected and current timeline entries visible in the context section of /info pages. Set the CSS property to `clip' instead of `hidden' to disallow any vertical scrolling (for example, by tabbing through hyperlinks), although this is probably not relevant for accordion panels. check-in: b0188ce122 user: florian tags: trunk | |
|
2026-01-10
| ||
| 14:17 | Sync with trunk. Leaf check-in: ceee00be59 user: florian tags: standard-cli-colors | |
| 14:10 | Sync with trunk. Leaf check-in: e4556126da user: florian tags: diff-word-wrap | |
| 14:05 | Sync with trunk. Leaf check-in: facfbbd552 user: florian tags: diff-keyboard-navigation | |
| 14:02 | Sync with trunk. check-in: c50c8ed9d7 user: florian tags: timeline-keyboard-navigation | |
| 11:52 | Do not try to use "notepad" as a text editor on non-windows systems. check-in: 9b263d87c1 user: drh tags: trunk | |
|
2026-01-09
| ||
| 16:44 | Update the built-in SQLite to the latest trunk check-in for testing. check-in: 2b2530dd07 user: drh tags: trunk | |
|
2025-09-26
| ||
| 12:53 | Sync with trunk. check-in: f3ff04466d user: florian tags: diff-keyboard-navigation | |
Changes to src/fossil.diff.js.
| ︙ | ︙ | |||
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
/* Toggle all entries to match this new state. We use click()
instead of ckbox.checked=... so that the on-change event handler
fires. */
if(ckbox.checked!==show) ckbox.click();
}
}, false);
}
});
window.fossil.onPageLoad(function(){
const F = window.fossil, D = F.dom;
const Diff = F.diff = {
e:{/*certain cached DOM elements*/},
config: {
chunkLoadLines: (
F.config.diffContextLines * 3
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
/* Toggle all entries to match this new state. We use click()
instead of ckbox.checked=... so that the on-change event handler
fires. */
if(ckbox.checked!==show) ckbox.click();
}
}, false);
}
function resetToggles(){
var cb = document.querySelectorAll(
'input[type="checkbox"].diff-toggle:not(:checked)');
for( var i=0; i<cb.length; i++ ) cb[i].checked = true;
}
setTimeout(resetToggles);
});
/*
** Diff keyboard navigation shortcuts:
**
** ### NOTE: The keyboard shortcuts are listed in the /vdiff help screen. ###
**
** Ideas and TODOs:
**
** o The `timeline-keyboard-navigation' branch removes the unload handler from
** pages containing timeline snippets, so it's no longer necessary to reset
** the diff toggles on back/forward navigation in case the mentioned branch
** is merged with `diff-keyboard-navigation'.
*/
(function(){
window.addEventListener('load',function(){
function btnScrollIntoView(e){
e = e.parentElement;
var rc = e.getBoundingClientRect();
var y = 0;
do{
y += e.offsetTop;
}while( e = e.offsetParent );
window.scrollTo(0,y-6*rc.height);
}
document.addEventListener('keydown',function(evt){
if( evt.target.tagName=='INPUT' || evt.target.tagName=='SELECT' ) return;
var
mSHIFT = 1<<13,
kSHOW = mSHIFT | 73 /* SHIFT+I */,
kHIDE = 73 /* I */,
kNEXT = 80 /* P */,
kPREV = 79 /* O (Letter O) */,
kUNID = 85 /* U */,
kSBSD = mSHIFT | 85 /* SHIFT+U */,
kNULD = 48 /* 0 (Digit Zero) */,
kUDCD = 68 /* D */,
mod = evt.altKey<<15|evt.ctrlKey<<14|evt.shiftKey<<13|evt.metaKey<<12,
key = ( evt.which || evt.keyCode ) | mod;
switch( key ){
case kSHOW:
case kHIDE:
case kNEXT:
case kPREV:
case kUNID:
case kSBSD:
case kNULD:
case kUDCD: break;
default: return;
}
evt.preventDefault();
evt.stopPropagation();
if( key==kSHOW || key==kHIDE ){
var btn = document.getElementsByClassName('diff-toggle');
if( btn.length>0 ){
var chg = 0;
for( var i=0; i<btn.length; i++ ){
if( btn[i].checked && key==kHIDE ){
btn[i].click();
chg++;
}
else if( !btn[i].checked && key==kSHOW ){
btn[i].click();
chg++;
}
}
if( chg>0 ) btnScrollIntoView(btn[0]);
}
}
else if( key==kNEXT || key==kPREV ){
var btn = document.getElementsByClassName('diff-toggle');
if( btn.length>1 ){
var nFolded = 0, n = -2;
for( var i=0; i<btn.length; i++ ){
if( !btn[i].checked ) nFolded++;
}
if( nFolded==0 ){
n = ( key==kNEXT ? 0 : btn.length-1 );
for( var i=0; i<btn.length; i++ ){
if( n!=i ) btn[i].click();
}
}
else{
for( var i=0; i<btn.length; i++ ){
if( btn[i].checked ){
if( n==-2 ) n = ( key==kNEXT ? i+1 : i-1 );
if( n!=i ) btn[i].click();
}
}
}
if( n==-2 ) n = ( key==kNEXT ? 0 : btn.length-1 );
if( n in btn ){
if( !btn[n].checked ) btn[n].click();
btnScrollIntoView(btn[n]);
}
}
else if( btn.length>0 ){
btn[0].click();
btnScrollIntoView(btn[0]);
}
}
else if( key==kUNID || key==kSBSD || key==kNULD ){
var T={}; T[kUNID]='unified', T[kSBSD]='side-by-side', T[kNULD]='hide';
var
type = T[key],
link = document.querySelector('.smb-'+type+'-diff')
|| document.querySelector('.sml-'+type+'-diff'),
href;
if( link ){
if( link.dataset.href ) href = link.dataset.href; // anti-bot
else href = link.href;
}
if( href && href!=location.href.slice(-href.length) ){
location.href = href;
}
}
else if( key==kUDCD ){
if( !/[?&]udc=1/.test(location.href) ){
var sep = /\?/.test(location.href) ? '&' : '?';
location.href += sep + 'udc=1';
}
}
}/*,true*/);
},false);
}());
window.fossil.onPageLoad(function(){
const F = window.fossil, D = F.dom;
const Diff = F.diff = {
e:{/*certain cached DOM elements*/},
config: {
chunkLoadLines: (
F.config.diffContextLines * 3
|
| ︙ | ︙ |
Changes to src/info.c.
| ︙ | ︙ | |||
460 461 462 463 464 465 466 |
}
}
/*
** Generate javascript to enhance HTML diffs.
*/
void append_diff_javascript(int diffType){
| | | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 |
}
}
/*
** Generate javascript to enhance HTML diffs.
*/
void append_diff_javascript(int diffType){
/* Load fossil.diff.js even if diffType==0 to enable keyboard shortcuts. */
builtin_fossil_js_bundle_or("diff", NULL);
}
/*
** Construct an appropriate diffFlag for text_diff() based on query
** parameters and the to boolean arguments.
*/
|
| ︙ | ︙ | |||
647 648 649 650 651 652 653 654 |
}else{
DCfg.diffFlags |= DIFF_LINENO | DIFF_HTML | DIFF_NOTTOOBIG;
}
@ <div class="section" id="changes_section">Changes</div>
DCfg.diffFlags |= DIFF_NUMSTAT; /* Show stats in the 'Changes' section */
@ <div class="sectionmenu info-changes-menu">
zW = (DCfg.diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
if( diffType!=1 ){
| > > > > > > > | > > | | 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 |
}else{
DCfg.diffFlags |= DIFF_LINENO | DIFF_HTML | DIFF_NOTTOOBIG;
}
@ <div class="section" id="changes_section">Changes</div>
DCfg.diffFlags |= DIFF_NUMSTAT; /* Show stats in the 'Changes' section */
@ <div class="sectionmenu info-changes-menu">
zW = (DCfg.diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
if( diffType!=0 ){
/* Class "smb-hide-diff" required by the fossil.diff.js script. */
const char *zBtnClass = "button smb-hide-diff";
@ %z(chref(zBtnClass,"%R?diff=0"))Hide Diff</a>
}
if( diffType!=1 ){
/* Class "smb-unified-diff" required by the fossil.diff.js script. */
const char *zBtnClass = "button smb-unified-diff";
@ %z(chref(zBtnClass,"%R?diff=1%s",zW))Unified Diff</a>
}
if( diffType!=2 ){
/* Class "smb-side-by-side-diff" required by the fossil.diff.js script. */
const char *zBtnClass = "button smb-side-by-side-diff";
@ %z(chref(zBtnClass,"%R?diff=2%s",zW))Side-by-Side Diff</a>
}
if( diffType!=0 ){
if( *zW ){
@ %z(chref("button","%R?diff=%d",diffType))\
@ Show Whitespace Changes</a>
}else{
@ %z(chref("button","%R?diff=%d&w",diffType))Ignore Whitespace</a>
|
| ︙ | ︙ | |||
839 840 841 842 843 844 845 846 847 848 849 850 851 852 |
** when using "fossil ui --from PATH", the --from argument becomes the value
** of the exbase query parameter for the start page. Note that if PATH
** is a pure hexadecimal string, it is decoded first before being used as
** the pathname. Real pathnames should contain at least one directory
** separator character.
**
** Other query parameters related to diffs are also accepted.
*/
void ckout_page(void){
int vid;
const char *zHome; /* Home directory */
int nHome;
const char *zExBase;
char *zHostname;
| > > > | 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 |
** when using "fossil ui --from PATH", the --from argument becomes the value
** of the exbase query parameter for the start page. Note that if PATH
** is a pure hexadecimal string, it is decoded first before being used as
** the pathname. Real pathnames should contain at least one directory
** separator character.
**
** Other query parameters related to diffs are also accepted.
**
** See the help screen for the /vdiff web page for a list of available
** keyboard shortcuts.
*/
void ckout_page(void){
int vid;
const char *zHome; /* Home directory */
int nHome;
const char *zExBase;
char *zHostname;
|
| ︙ | ︙ | |||
906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 |
**
** Display information about a particular check-in. The exact
** same information is shown on the /info page if the name query
** parameter to /info describes a check-in.
**
** The ARTIFACTID can be a unique prefix for the HASH of the check-in,
** or a tag or branch name that identifies the check-in.
*/
void ci_page(void){
Stmt q1, q2, q3;
int rid;
int isLeaf;
int diffType; /* 0: no diff, 1: unified, 2: side-by-side */
const char *zName; /* Name of the check-in to be displayed */
const char *zUuid; /* Hash of zName, found via blob.uuid */
const char *zParent; /* Hash of the parent check-in (if any) */
const char *zRe; /* regex parameter */
ReCompiled *pRe = 0; /* regex */
const char *zW; /* URL param for ignoring whitespace */
const char *zPage = "vinfo"; /* Page that shows diffs */
const char *zBrName; /* Branch name */
DiffConfig DCfg,*pCfg; /* Type of diff */
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
style_set_current_feature("vinfo");
zName = P("name");
| > > > > | 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 |
**
** Display information about a particular check-in. The exact
** same information is shown on the /info page if the name query
** parameter to /info describes a check-in.
**
** The ARTIFACTID can be a unique prefix for the HASH of the check-in,
** or a tag or branch name that identifies the check-in.
**
** See the help screen for the /vdiff web page for a list of available
** keyboard shortcuts.
*/
void ci_page(void){
Stmt q1, q2, q3;
int rid;
int isLeaf;
int diffType; /* 0: no diff, 1: unified, 2: side-by-side */
const char *zName; /* Name of the check-in to be displayed */
const char *zUuid; /* Hash of zName, found via blob.uuid */
const char *zParent; /* Hash of the parent check-in (if any) */
const char *zRe; /* regex parameter */
ReCompiled *pRe = 0; /* regex */
const char *zW; /* URL param for ignoring whitespace */
const char *zPage = "vinfo"; /* Page that shows diffs */
const char *zPageHide = "ci"; /* Page that hides diffs */
const char *zBrName; /* Branch name */
DiffConfig DCfg,*pCfg; /* Type of diff */
login_check_credentials();
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
style_set_current_feature("vinfo");
zName = P("name");
|
| ︙ | ︙ | |||
1181 1182 1183 1184 1185 1186 1187 1188 |
@ <div class="accordion_panel">
@ <div class="sectionmenu info-changes-menu">
/* ^^^ .info-changes-menu is used by diff scroll sync */
pCfg = construct_diff_flags(diffType, &DCfg);
DCfg.diffFlags |= DIFF_NUMSTAT; /* Show stats in the 'Changes' section */
DCfg.pRe = pRe;
zW = (DCfg.diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
if( diffType!=1 ){
| > > > > > > > > | > > | | 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 |
@ <div class="accordion_panel">
@ <div class="sectionmenu info-changes-menu">
/* ^^^ .info-changes-menu is used by diff scroll sync */
pCfg = construct_diff_flags(diffType, &DCfg);
DCfg.diffFlags |= DIFF_NUMSTAT; /* Show stats in the 'Changes' section */
DCfg.pRe = pRe;
zW = (DCfg.diffFlags&DIFF_IGNORE_ALLWS)?"&w":"";
if( diffType!=0 ){
/* Class "smb-hide-diff" required by the fossil.diff.js script. */
const char *zBtnClass = "button smb-hide-diff";
@ %z(chref(zBtnClass,"%R/%s/%T?diff=0",zPageHide,zName))\
@ Hide Diff</a>
}
if( diffType!=1 ){
/* Class "smb-unified-diff" required by the fossil.diff.js script. */
const char *zBtnClass = "button smb-unified-diff";
@ %z(chref(zBtnClass,"%R/%s/%T?diff=1%s",zPage,zName,zW))\
@ Unified Diff</a>
}
if( diffType!=2 ){
/* Class "smb-side-by-side-diff" required by the fossil.diff.js script. */
const char *zBtnClass = "button smb-side-by-side-diff";
@ %z(chref(zBtnClass,"%R/%s/%T?diff=2%s",zPage,zName,zW))\
@ Side-by-Side Diff</a>
}
if( diffType!=0 ){
if( *zW ){
@ %z(chref("button","%R/%s/%T?diff=%d",zPage,zName,diffType))
@ Show Whitespace Changes</a>
}else{
|
| ︙ | ︙ | |||
1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 |
** dc=N show N lines of context around each diff
** w=BOOLEAN ignore whitespace when computing diffs
** nohdr omit the description at the top of the page
** nc omit branch coloration from the header graph
** inv "Invert". Exchange the roles of from= and to=
**
** Show all differences between two check-ins.
*/
void vdiff_page(void){
int ridFrom, ridTo;
int diffType = 0; /* 0: none, 1: unified, 2: side-by-side */
Manifest *pFrom, *pTo;
ManifestFile *pFileFrom, *pFileTo;
const char *zBranch;
| > > > > > > > > > > > > > > | 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 |
** dc=N show N lines of context around each diff
** w=BOOLEAN ignore whitespace when computing diffs
** nohdr omit the description at the top of the page
** nc omit branch coloration from the header graph
** inv "Invert". Exchange the roles of from= and to=
**
** Show all differences between two check-ins.
**
** Keyboard navigation shortcuts:
**
** I Show all file changes.
** i Hide all file changes.
** p Show only next file change.
** o Show only previous file change.
** u Reload page in Unified Diff mode.
** U Reload page in Side-By-Side Diff mode.
** 0 Reload page in Hidden Diff mode.
** d Reload page and set current Diff mode as default.
**
** The keyboard shortcuts also apply to /ckout, /vinfo, /ci and /fdiff
** pages, and to /info pages describing check-in information.
*/
void vdiff_page(void){
int ridFrom, ridTo;
int diffType = 0; /* 0: none, 1: unified, 2: side-by-side */
Manifest *pFrom, *pTo;
ManifestFile *pFileFrom, *pFileTo;
const char *zBranch;
|
| ︙ | ︙ | |||
1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 |
blob_appendf(&qp, "&w");
}
cgi_check_for_malice();
style_set_current_feature("vdiff");
if( zBranch==0 ){
style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
}
if( diffType!=2 ){
style_submenu_element("Side-by-Side Diff", "%R/vdiff?diff=2&%b%b", &qp,
&qpGlob);
}
if( diffType!=1 ) {
style_submenu_element("Unified Diff", "%R/vdiff?diff=1&%b%b", &qp, &qpGlob);
}
| > > > | 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 |
blob_appendf(&qp, "&w");
}
cgi_check_for_malice();
style_set_current_feature("vdiff");
if( zBranch==0 ){
style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
}
if( diffType!=0 ){
style_submenu_element("Hide Diff", "%R/vdiff?diff=0&%b%b", &qp, &qpGlob);
}
if( diffType!=2 ){
style_submenu_element("Side-by-Side Diff", "%R/vdiff?diff=2&%b%b", &qp,
&qpGlob);
}
if( diffType!=1 ) {
style_submenu_element("Unified Diff", "%R/vdiff?diff=1&%b%b", &qp, &qpGlob);
}
|
| ︙ | ︙ | |||
1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 |
**
** dc=N Show N lines of context around each diff
** patch Use the patch diff format
** regex=REGEX Only show differences that match REGEX
** sbs=BOOLEAN Turn side-by-side diffs on and off (default: on)
** verbose=BOOLEAN Show more detail when describing artifacts
** w=BOOLEAN Ignore whitespace
*/
void diff_page(void){
int v1, v2;
int isPatch = P("patch")!=0;
int diffType; /* 0: none, 1: unified, 2: side-by-side */
char *zV1;
char *zV2;
| > > > | 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 |
**
** dc=N Show N lines of context around each diff
** patch Use the patch diff format
** regex=REGEX Only show differences that match REGEX
** sbs=BOOLEAN Turn side-by-side diffs on and off (default: on)
** verbose=BOOLEAN Show more detail when describing artifacts
** w=BOOLEAN Ignore whitespace
**
** See the help screen for the /vdiff web page for a list of available
** keyboard shortcuts.
*/
void diff_page(void){
int v1, v2;
int isPatch = P("patch")!=0;
int diffType; /* 0: none, 1: unified, 2: side-by-side */
char *zV1;
char *zV2;
|
| ︙ | ︙ | |||
3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 |
**
** The NAME argument is any valid artifact name: an artifact hash,
** a timestamp, a tag name, etc.
**
** Because NAME can match so many different things (commit artifacts,
** wiki pages, ticket comments, forum posts...) the format of the output
** page depends on the type of artifact that NAME matches.
*/
void info_page(void){
const char *zName;
Blob uuid;
int rid;
int rc;
int nLen;
| > > > | 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 |
**
** The NAME argument is any valid artifact name: an artifact hash,
** a timestamp, a tag name, etc.
**
** Because NAME can match so many different things (commit artifacts,
** wiki pages, ticket comments, forum posts...) the format of the output
** page depends on the type of artifact that NAME matches.
**
** See the help screen for the /vdiff web page for a list of available
** keyboard shortcuts (if the NAME argument refers to a check-in).
*/
void info_page(void){
const char *zName;
Blob uuid;
int rid;
int rc;
int nLen;
|
| ︙ | ︙ |