Interestingly, just the same day I find that xwidgets isn't dead anymore (https://github.com/emacs-mirror/emacs/commit/4e855f90d1b1c39...); life is funny!
HN user
qazxcvbnm
Finally found a working graphical Emacs browser! I've been looking for just this since webkit widgets died. In my experience on macOS, EAF was very buggy (plus spawning an ugly extra Python window).
This comes with a lovely transient menu even!
Installation was quite smooth, works just as advertised. Still have some hiccups (link hinting often requires multiple calls to detect; events get stuck after pressing Google AI Search popup; on first setup displays what appears to be an undismissable chromium video cast popup; consumes more CPU than ideal), but altogether something I definitely can work with!
My goodness, how so thoughtful Emacs Solo is!
The new Emacs features sound great! (We have native window management finally)
I wish we would someday be able to edit in xref too, wgrep having landed in Emacs 30 (especially since project.el grep goes to xref by default).
By the way, anyone more informed know about any work on getting a graphical browser to work on latest Emacs, now that webkit xwidgets is dead for Emacs 30+? (Have tried EAF; extremely buggy on Mac)
M-n, M-p. M-r for searching on past commands. C-c c-n/C-p for next/previous prompt. C-c C-r to scroll to focus on output.
Having switched recently to Emacs, my current issue is how to get Emacs shell history saved properly for my other shell buffers, and getting completions from shell (not Emacs) to work, planning to try MisTTY soon.
By the way, anyone have experience using emacs to analyse and visualise data (think spreadsheets and charts)? I’d really like to be able to use it to view any sort of data I happen to have.
An uninformed question: If the network is fully composed of 1x1 convolutions, doesn’t that mean no information mixing between pixels occur? Would that not imply that each pixel is independent of each other? How can that not lead to incoherent results?
What are some more information on the state of the art in runtime adaptation? I confess I do not feel like I possess such a thing from the databases I regularly use.
Adaptation sounds very compelling; if instead of emitting a plan based on a cardinality estimate, we emit a plan and a range of reasonable intermediate cardinalities together with expected time, and interrupt the original plan when the expectations are exceeded by an order of magnitude, and perform alternative plans based on newly gathered physical information, it sounds like it would be greatly beneficial. Are there concrete reasons that this has not been done (e.g. cost, complexity)?
When things aren’t ticking perfectly for Synology their software can be kind of weird. Sometimes after power failures, some disks get corrupted and… you simply can’t log in to the Synology UI during this time (unless you “synobootseq --set-boot-done”, why, of course) for an unspecified number of hours.
Their custom software has its quirks (eg scp doesn’t work unless you apply the -O flag, for “security” reasons), and the quirks change sometimes after updates.
I’ve once attempted to implement a solution where ids are generated by UUIDv5 from a certain owner and the relationship of the new item to the owner; that way, users cannot generate arbitrary ids but can still predict ahead of time their new ids to ease optimistic behaviour.
Yeah, its a theoretical general connection. Once you’ve pinned down the specific structure and know how many structures to skip by virtue of knowing how to count them, it becomes a somewhat practical algorithm.
For those who are not aware, knowing how to count the number of structures is (nearly) the same as knowing how to encode said structure as an integer (space-optimally) (the naive general algorithm would not have good time complexity); to convert to integer, simply define some ordering on said structures, enumerate until you find your structure, the index of the structure is the integer encoding; conversely, to decode, simply list all structures and pick the structure with the index of the integer.
A somewhat more “complete” solution that doesn’t give you hints (thus doesn’t rely on the plugin support for all of vim’s vast functionalities), but conditions your instincts to get better: increase the latency of my whole terminal (c.f. https://unix.stackexchange.com/questions/778196/how-to-add-d...) (also see the comment) by running my terminal session on a ssh session into my own machine through a ProxyCommand of the command delay.
And batching
You're right, it's not the same. Undecidable properties are not related in general.
Halting (problem) is undecidable. Undecidability is not just the halting problem. Whether you go to the park on a given day is undecidable (assuming you have free will, and all such assumptions), but that you can be an oracle for this does not solve the halting problem.
Note that succinct data structures may not be faster than conventional structures if your dataset fits in memory http://www.cs.cmu.edu/~huanche1/slides/FST.pdf . Of course, for large datasets where storage access times dominate, succinct data structures win all around. In any case, succinct trees are works of art (If I recall https://arxiv.org/pdf/1805.11255 was a good exposition) (just look at how that RMQ works)!
To be fair, searching with Spotlight has been equally slow and useless for me… Whenever I need to find a file and mistakenly use Command F in my Finder, the complete cessation of activity that inevitably results reminds me yet once again to just go to my terminal to use trusty GNU’s find instead.
You may be interested in my other comment. To put it simply, pure languages remove serialisation of false data dependencies, exposing data parallelism, and interaction nets remove serialisation of false control dependencies, exposing control parallelism.
Both lambda calculus and interaction nets are confluent. That is, for a term that can be normalised (i.e. evaluated), one can obtain the same answer by performing any available action in any order (n.b. if the chosen order terminates). For example, for `A (B) (C (D))`, I can choose to first evaluate either `A (B)` or `C (D)` and the final answer will be the same. This is true in both systems (although the reduction in interaction nets has more satisfactory properties).
The key reason one may consider interaction nets to be more parallelisable than lambda calculus is that the key evaluation operation is global in lambda calculus, but local in interaction nets. The key evaluation operation in labmda calculus is (beta) reduction. For instance, if one evaluates a lambda term `(\n -> f n n) x`, reduction takes this to the term `f x x`. To do so, one must duplicate the entire term `x` from the argument to perform the computation, by either 1) physical duplication, or 2) keeping track of references. Both are unsatisfactory solutions with many properties hindering parallelism. As I shall explain, the term `x` may be of unbounded size or be intertwined non-locally with a large part of the control graphs of other terms.
If `x` is simply a ground term (i.e. a piece of data), then it seems like either duplication or keeping track of the references would be an inevitable and reasonable cost, with the usual managed-language issues of garbage collection. If one decides to solve the problem by attempting to force the argument to be a ground term, one would find the only method to be to impose eager evaluation, evaluating terms by always first evaluating the leaf of the expression, before evaluating internal nodes in the expression. Eager evaluation can easily become unboundedly wasteful when one strives to reuse a general computation for some more specific use cases, so one may not prefer an eager evaluation doctrine.
However, once one evaluates in an order that is not strictly eager (e.g. lazy evaluation), the terms that one is duplicating or referencing are no longer simple pieces of data, but pieces of a (not necessarily acyclic) control graph, and any referencing logic quickly becomes very complicated. Moreover, the argument `x` could also be a function, and keeping track of references would involve keeping track of closures over different variables and scopes, which complicates the problem of sharing even further.
Thus, either one follows an eager evaluation order, in which most of the nodes in a term's expression tree are not available for evaluation yet, and available pieces of work for evaluation are only generated as evaluation happens, which imposes a global and somewhat strict serialised order of execution, or one deals with a big complicated shared graph, which is also inconvenient to be distributed across computational resources.
In contrast with lambda calculus, the key evaluation operation in interaction nets is local. Interaction nets can be seen as more low-level than lambda calculus, and both code and data are represented as graphs of nodes to be evaluated. Thus, a large term is represented as a large net, and regardless of the unbounded size of a term, in one unit of evaluation, only one node from the term's graph is involved.
Given a graph of some 'net' to be evaluated, one can choose any "active" node and begin evaluating right there, and the result of computation in that unit of evaluation will be guaranteed to affect only the nodes originally connected to the evaluated node, no referencing involved. Thus, the problem of computation becomes almost embarrassingly parallel, where workers simply pick any piece of a graph and locally add or remove from that piece of the graph.
This is what is meant when one refers to interaction nets being more parallelisable than lambda calculus.
This is very powerful. Unfortunately, as an Ex command, `!` only works on full lines. One can of course also teach vim to operate `!` over any motion (or visual selection), whether it is part of a line, a full line, or a block https://vi.stackexchange.com/a/46304/48750.
I read the paper a few years ago and I agree that for such an incredible algorithmic improvement, it’s not trivial to find a use case, as you still need to maintain a separate (albeit algorithmically insignificant) lookup table. When I read the paper I (mistakenly) hoped it could be used for indexing on-disk structures without ever hitting the disk for things like B tree internal nodes. To get its sweet sweet algorithmic complexity, up its sleeve is once again (as I recall) the age old trick of rebuilding the structure when the size doubles, which makes it much less efficient than it sounds for most practical use cases. I suppose one good use case for this might be compressing database indexes, where you need to maintain a separate structure anyway and the space savings can be worth it.
The example is meant to demonstrate that whether I say 平 as ping or peng changes the meaning of the sentence. It does not depend on how I feel like it.
Another example: I buy some raisins, and the lady gives me some. I say: 咁多! If I pronounce "gam3do1", I say "That's so much!". If I pronounce "gam3doe1", I say "That's so little!".
(Yes, contrived. Almost always the former is used. But both can be.)
A counterexample for you: 聶 nip6, never lip6. 獵 lip6, never nip6. 焫 naat3, "lazily" laat3. 辣 laat6, never naat6. (Yes, almost everywhere interchangeable)
Yes, I have mainly put awkward usages in the latter section, which will hopefully be useful to the author. If you compare the paragraphs, the outright grammatical problems I simply fixed. The author’s language is definitely comprehensible to a patient listener, but it can be much better still.
I cannot corroborate the experience of the other commenter. 念 is very definitively nim6, with lim6 as a common variant/lazy pronunciation. It is not at all uncommon that words have a variant pronunciation when used in certain contexts (e.g. as jargon or slang), such as Wing Chun in your case, but the word itself is certainly not properly or even commonly pronounced the "lazy" way otherwise (c.f. 執念 zap1nim6; 萬念俱灰 maan6nim6keoi1fui1; 惡念 ok3nim6).
There are many cases where variant pronunciations sound natural, but (individually) "correct" pronunciations sound unnatural (e.g. 土瓜灣 tou2gwaa1waan1 "correct" but unnatural, tou2gwaa1waan4 "variant" and natural). I have never encountered a case where a correct pronunciation would be unnatural where "lazy" pronunciations would be natural.
On another note, your Cantonese sounds a bit unnatural (without many of the connecting words between thoughts) (typical for learners). A more natural phrasing might be something like this: 我打詠春嘅。學院(?)入面我師父同我哋都係讀lim嘅。反而如果有人讀nim會好奇怪。我想你明白粵卷唔使百分百啱晒嘅。講嘢可能淨係使啱八成到九成,大部份人都明你講嘅嘢。咁都OK嘅。學廣東話嘅學生可以多啲地方繼續學廣東話就可以越來越好。
A few notes on your usage:
"我都打詠春" 都 here seems unnecessary, as you have not discussed 詠春 previously.
"學院" slightly dubious, usually used for more academic purposes. For martial arts, 館 or 武館 may be more typical, but I suppose it is possible that your school brands itself as 學院.
"我師傅" "師傅" and "師父" sound the same, but mean quite different things. 師傅 is a polite name for someone working in some field, but 師父 is your master. (In fact this is another example of "lazy" or variant pronunciations, which is emphatically not always the correct pronunciation; 父 here is fu2, but by itself is definitively fu6)
"都話"lim"" "話" probably refers more to the topic of what someone says rather than the pronunciation, which the word "讀" would make clear, that we discuss pronunciation
"我推介你試吓明粵卷唔使係一百%啱" too be honest I'm not completely sure what this sentence means. I hope what I put was what you intended.
"一百%" 百分百 is more natural
"八十到九十%" 八成到九成 (lit. 8 10%s to 9 10%s) is more natural
"明你講乜嘢" (sounds like: understand what on earth you're saying) "乜嘢" emphasises the object like a question (i.e. sounds like a rhetorical question; when not a question, usually would be used when expressing frustration/complaining/scolding); no need to emphasise, "明你講嘅嘢" would be fine.
"學生可以繼續學廣東話。越來越好。" disjointed sentences, not completely sure your intended meaning. I hope what I put was what you intended.
As a native speaker I assure you that 請 is pronounced differently in context, and that both readings are perfectly Cantonese.
For a more clear example, see 平: 大平賣 ("vernacular" reading; peng4) (lit. big cheap sale; i.e. sale) vs 平面 ("literary" reading; ping4) (lit. flat surface; i.e. surface). peng4 is the "vernacular" reading but used exclusively for meaning cheap. ping4 is "literary" but used everywhere else. "vernacular" versus "literary" is a linguistic classification, but do not necessarily represent either being more common than the other reading. Both readings exist.
When you get to using [count]g[something] and g[count][something] and <C-@>[count]g[something] etc a lot, you start getting a bit confused about where you need to put the count to make things work. So you can make putting the count anywhere work; now, don't worry and just start pressing g or <C-@>g for window actions, and put a count if you realise you need it:
map <expr> <C-@>1 Termcountmap(1, "")
map <expr> <C-@>2 Termcountmap(2, "")
map <expr> <C-@>3 Termcountmap(3, "")
map <expr> <C-@>4 Termcountmap(4, "")
map <expr> <C-@>5 Termcountmap(5, "")
map <expr> <C-@>6 Termcountmap(6, "")
map <expr> <C-@>7 Termcountmap(7, "")
map <expr> <C-@>8 Termcountmap(8, "")
map <expr> <C-@>9 Termcountmap(9, "")
map! <expr> <C-@>1 Termcountmap(1, '<Esc>')
map! <expr> <C-@>2 Termcountmap(2, '<Esc>')
map! <expr> <C-@>3 Termcountmap(3, '<Esc>')
map! <expr> <C-@>4 Termcountmap(4, '<Esc>')
map! <expr> <C-@>5 Termcountmap(5, '<Esc>')
map! <expr> <C-@>6 Termcountmap(6, '<Esc>')
map! <expr> <C-@>7 Termcountmap(7, '<Esc>')
map! <expr> <C-@>8 Termcountmap(8, '<Esc>')
map! <expr> <C-@>9 Termcountmap(9, '<Esc>')
tmap <expr> <C-@>1 Termcountmap(1, '<C-@>N')
tmap <expr> <C-@>2 Termcountmap(2, '<C-@>N')
tmap <expr> <C-@>3 Termcountmap(3, '<C-@>N')
tmap <expr> <C-@>4 Termcountmap(4, '<C-@>N')
tmap <expr> <C-@>5 Termcountmap(5, '<C-@>N')
tmap <expr> <C-@>6 Termcountmap(6, '<C-@>N')
tmap <expr> <C-@>7 Termcountmap(7, '<C-@>N')
tmap <expr> <C-@>8 Termcountmap(8, '<C-@>N')
tmap <expr> <C-@>9 Termcountmap(9, '<C-@>N')
function! Termcountmap(initcount, normalkeys)
let termcount = a:initcount
while 1
try
let char = getchar()
catch /^Vim:Interrupt$/
return ""
endtry
if type(char) == 0
let char = nr2char(char)
endif
if char == '0'
let termcount = termcount * 10
elseif char == '1'
let termcount = termcount * 10 + 1
elseif char == '2'
let termcount = termcount * 10 + 2
elseif char == '3'
let termcount = termcount * 10 + 3
elseif char == '4'
let termcount = termcount * 10 + 4
elseif char == '5'
let termcount = termcount * 10 + 5
elseif char == '6'
let termcount = termcount * 10 + 6
elseif char == '7'
let termcount = termcount * 10 + 7
elseif char == '8'
let termcount = termcount * 10 + 8
elseif char == '9'
let termcount = termcount * 10 + 9
elseif char == 'g'
return a:normalkeys .. termcount .. 'g'
elseif char == "\<C-g>"
return a:normalkeys .. termcount .. "\<C-@>\<C-g>"
elseif char == 'w'
return a:normalkeys .. termcount .. "\<C-@>w"
elseif char == 'W'
return a:normalkeys .. termcount .. "\<C-@>W"
elseif char == 't'
return a:normalkeys .. termcount .. "\<C-@>t"
elseif char == 'b'
return a:normalkeys .. termcount .. "\<C-@>b"
else
return a:normalkeys .. ":\<C-u>" .. termcount .. ' wincmd ' .. char .. "\<CR>\<C-l>"
endif
endwhile
endfunction
map <expr> g<C-@> <C-@>g
map <expr> g1 Prefixcountmap (v:count * 10 + 1, "", 'g')
map <expr> g2 Prefixcountmap (v:count * 10 + 2, "", 'g')
map <expr> g3 Prefixcountmap (v:count * 10 + 3, "", 'g')
map <expr> g4 Prefixcountmap (v:count * 10 + 4, "", 'g')
map <expr> g5 Prefixcountmap (v:count * 10 + 5, "", 'g')
map <expr> g6 Prefixcountmap (v:count * 10 + 6, "", 'g')
map <expr> g7 Prefixcountmap (v:count * 10 + 7, "", 'g')
map <expr> g8 Prefixcountmap (v:count * 10 + 8, "", 'g')
map <expr> g9 Prefixcountmap (v:count * 10 + 9, "", 'g')
tmap <expr> <c-@>g1 Prefixcountmap (v:count * 10 + 1, '<c-@>n', 'g')
tmap <expr> <c-@>g2 Prefixcountmap (v:count * 10 + 2, '<c-@>n', 'g')
tmap <expr> <c-@>g3 Prefixcountmap (v:count * 10 + 3, '<c-@>n', 'g')
tmap <expr> <c-@>g4 Prefixcountmap (v:count * 10 + 4, '<c-@>n', 'g')
tmap <expr> <c-@>g5 Prefixcountmap (v:count * 10 + 5, '<c-@>n', 'g')
tmap <expr> <c-@>g6 Prefixcountmap (v:count * 10 + 6, '<c-@>n', 'g')
tmap <expr> <c-@>g7 Prefixcountmap (v:count * 10 + 7, '<c-@>n', 'g')
tmap <expr> <c-@>g8 Prefixcountmap (v:count * 10 + 8, '<c-@>n', 'g')
tmap <expr> <c-@>g9 Prefixcountmap (v:count * 10 + 9, '<c-@>n', 'g')
map <expr> <C-@><C-g>1 Prefixcountmap (v:count * 10 + 1, "", '<C-@><C-g>')
map <expr> <C-@><C-g>2 Prefixcountmap (v:count * 10 + 2, "", '<C-@><C-g>')
map <expr> <C-@><C-g>3 Prefixcountmap (v:count * 10 + 3, "", '<C-@><C-g>')
map <expr> <C-@><C-g>4 Prefixcountmap (v:count * 10 + 4, "", '<C-@><C-g>')
map <expr> <C-@><C-g>5 Prefixcountmap (v:count * 10 + 5, "", '<C-@><C-g>')
map <expr> <C-@><C-g>6 Prefixcountmap (v:count * 10 + 6, "", '<C-@><C-g>')
map <expr> <C-@><C-g>7 Prefixcountmap (v:count * 10 + 7, "", '<C-@><C-g>')
map <expr> <C-@><C-g>8 Prefixcountmap (v:count * 10 + 8, "", '<C-@><C-g>')
map <expr> <C-@><C-g>9 Prefixcountmap (v:count * 10 + 9, "", '<C-@><C-g>')
map! <expr> <C-@><C-g>1 Prefixcountmap (v:count * 10 + 1, '<Esc>', '<C-@><C-g>')
map! <expr> <C-@><C-g>2 Prefixcountmap (v:count * 10 + 2, '<Esc>', '<C-@><C-g>')
map! <expr> <C-@><C-g>3 Prefixcountmap (v:count * 10 + 3, '<Esc>', '<C-@><C-g>')
map! <expr> <C-@><C-g>4 Prefixcountmap (v:count * 10 + 4, '<Esc>', '<C-@><C-g>')
map! <expr> <C-@><C-g>5 Prefixcountmap (v:count * 10 + 5, '<Esc>', '<C-@><C-g>')
map! <expr> <C-@><C-g>6 Prefixcountmap (v:count * 10 + 6, '<Esc>', '<C-@><C-g>')
map! <expr> <C-@><C-g>7 Prefixcountmap (v:count * 10 + 7, '<Esc>', '<C-@><C-g>')
map! <expr> <C-@><C-g>8 Prefixcountmap (v:count * 10 + 8, '<Esc>', '<C-@><C-g>')
map! <expr> <C-@><C-g>9 Prefixcountmap (v:count * 10 + 9, '<Esc>', '<C-@><C-g>')
tmap <expr> <C-@><C-g>1 Prefixcountmap (v:count * 10 + 1, '<C-@>N', '<C-@><C-g>')
tmap <expr> <C-@><C-g>2 Prefixcountmap (v:count * 10 + 2, '<C-@>N', '<C-@><C-g>')
tmap <expr> <C-@><C-g>3 Prefixcountmap (v:count * 10 + 3, '<C-@>N', '<C-@><C-g>')
tmap <expr> <C-@><C-g>4 Prefixcountmap (v:count * 10 + 4, '<C-@>N', '<C-@><C-g>')
tmap <expr> <C-@><C-g>5 Prefixcountmap (v:count * 10 + 5, '<C-@>N', '<C-@><C-g>')
tmap <expr> <C-@><C-g>6 Prefixcountmap (v:count * 10 + 6, '<C-@>N', '<C-@><C-g>')
tmap <expr> <C-@><C-g>7 Prefixcountmap (v:count * 10 + 7, '<C-@>N', '<C-@><C-g>')
tmap <expr> <C-@><C-g>8 Prefixcountmap (v:count * 10 + 8, '<C-@>N', '<C-@><C-g>')
tmap <expr> <C-@><C-g>9 Prefixcountmap (v:count * 10 + 9, '<C-@>N', '<C-@><C-g>')
function! Prefixcountmap(initcount, prefix, countprefix)
let termcount = a:initcount
while 1
try
let char = getchar()
catch /^Vim:Interrupt$/
return ""
endtry
if type(char) == 0
let char = nr2char(char)
endif
if char == '0'
let termcount = termcount * 10
elseif char == '1'
let termcount = termcount * 10 + 1
elseif char == '2'
let termcount = termcount * 10 + 2
elseif char == '3'
let termcount = termcount * 10 + 3
elseif char == '4'
let termcount = termcount * 10 + 4
elseif char == '5'
let termcount = termcount * 10 + 5
elseif char == '6'
let termcount = termcount * 10 + 6
elseif char == '7'
let termcount = termcount * 10 + 7
elseif char == '8'
let termcount = termcount * 10 + 8
elseif char == '9'
let termcount = termcount * 10 + 9
else
return a:prefix .. termcount .. a:countprefix .. char
endif
endwhile
endfunctionSome other things I do:
Invoke terminals on directories (instead of netrw). So, I can e.g. sp. to split to a new terminal.
function! Isdir(dir) abort
return !empty(a:dir) && (isdirectory(a:dir) ||
\ (!empty($SYSTEMDRIVE) && isdirectory('/'..tolower($SYSTEMDRIVE[0])..a:dir)))
endfunction
augroup terminal-explorer
au!
au VimEnter * sil! au! FileExplorer *
au VimEnter * sil! au! Network *
au VimEnter * sil! au! AuNetrwEvent *
" au FileType netrw cd % | bw | exe 'terminal ++curwin'
au BufEnter * if &filetype != 'netrw' && Isdir(expand('%')) | lcd % | exe bufnr("%") ..'bufdo terminal ++curwin' | endif
augroup end
Make <C-@>m close windows instead: noremap <C-@>m <C-w>c
noremap! <C-@>m <Esc><C-w>c
tnoremap <C-@>m <C-@>c
Make <C-@>p find the next window if there is no previous window: noremap <expr> <silent> <C-@>p ':<C-u>wincmd p <Bar> if win_getid () == ' .. win_getid () .. ' <Bar> wincmd w <Bar> endif <CR>'
noremap! <expr> <silent> <C-@>p '<Esc>:<C-u>wincmd p <Bar> if win_getid () == ' .. win_getid () .. ' <Bar> wincmd w <Bar> endif <CR>'
tnoremap <expr> <silent> <C-@>p '<C-@>:<C-u>wincmd p <Bar> if win_getid () == ' .. win_getid () .. ' <Bar> wincmd w <Bar> endif <CR>'
Use <C-@>~. to detach the GNU screen that my vim is running in (I put my vim in a screen with `unbindall` i.e. I use screen merely for keeping my vim alive) (<C-@>~. is in analogy to the SSH quit keybinding <CR>~.). noremap <expr> <silent> <C-@>~. ':<C-u>silent !screen -X detach<CR>'
noremap! <expr> <silent> <C-@>~. '<C-@>:<C-u>silent !screen -X detach<CR>'
tnoremap <expr> <silent> <C-@>~. '<C-@>:<C-u>silent !screen -X detach<CR>'
With gf and gF, opening files just from a terminal grep is practically more convenient than vim's :grep. For gf in a new tab: map <silent> <C-@><C-f> :<C-u>tab split<CR>gf
With terminal multiplexing in vim, you start getting a lot of buffers. You can consider getting a custom tabline. Other tab management features become more important too. You might expect [count]gt to behave just like gt for [count] times: nnoremap <expr> gt '@_' .. ((v:count1 + (tabpagenr () - 1)) % (tabpagenr('$') ) + 1) .. 'gt'
For ease of moving to the last tab: nnoremap <expr> g<C-t> '@_' .. (((v:count == 0) ? tabpagenr ('$') : v:count)) .. 'gt'
To consistently access the gt family of bindings regardless of mode: map <C-@>gt gt
map <C-@>gT gT
map <C-@>g<C-t> g<C-t>
map! <C-@>gt <Esc>gt
map! <C-@>gT <Esc>gT
map! <C-@>g<C-t> <Esc>g<C-t>
tmap <C-@>gt <C-@>Ngt
tmap <C-@>gT <C-@>NgT
tmap <C-@>g<C-t> <C-@>Ng<C-t>
When you use <C-w>T a lot to move your windows in to new tabs, you might sometimes want to move them to the previous tab instead of the next one: nnoremap <silent> <C-@><C-t> <C-w>T
nnoremap <silent> <C-@>T <C-w>T:<C-u>tabm -1<CR>
To access these two in any mode consistently: map! <C-@><C-t> <Esc><C-@><C-t>
map! <C-@>T <Esc><C-@>T
tmap <C-@><C-t> <C-@>N<C-@><C-t>
tmap <C-@>T <C-@>N<C-@>T
Analogously to gt and gT, sometimes you may want to move your tabs around, or split them: function! SSStabmadjust(tabmnum)
if a:tabmnum < tabpagenr ()
return a:tabmnum - 1
else
return a:tabmnum
endif
endfunction
noremap <silent> <C-@><C-g>s :<C-u>tab split<CR>
noremap <expr> <silent> <C-@><C-g>t '@_:<C-u>' .. SSStabmadjust ((v:count1 + (tabpagenr () - 1 )) % (tabpagenr('$') ) + 1) .. 'tabm<CR>'
noremap <expr> <silent> <C-@><C-g>T '@_:<C-u>' .. SSStabmadjust (((- v:count1 + (tabpagenr () - 1 )) % (tabpagenr('$') ) + tabpagenr('$') ) % (tabpagenr('$') ) + 1) .. 'tabm<CR>'
noremap <expr> <silent> <C-@><C-g><C-t> ':<C-u>' .. ((v:count == 0) ? "" : SSStabmadjust ((v:count % (tabpagenr ('$') )) )) .. 'tabm<CR>'
map! <C-@><C-g>s <Esc><C-@><C-g>s
map! <C-@><C-g>t <Esc><C-@><C-g>t
map! <C-@><C-g>T <Esc><C-@><C-g>T
map! <C-@><C-g><C-t> <Esc><C-@><C-g><C-t>
tmap <C-@><C-g>s <C-@>N<C-@><C-g>s
tmap <C-@><C-g>t <C-@>N<C-@><C-g>t
tmap <C-@><C-g>T <C-@>N<C-@><C-g>T
tmap <C-@><C-g><C-t> <C-@>N<C-@><C-g><C-t>vimrc for 4)
vnoremap <C-@>s <C-w>sgv
vnoremap <C-@>v <C-w>vgv
nnoremap <expr> <C-@>w '@_' .. ((v:count1 + (winnr() - 1)) % (winnr('$')) + 1) .. '<C-w>w'
nnoremap <expr> <C-@>W '@_' .. (((- v:count1 + (winnr() - 1)) % (winnr('$')) + winnr('$')) % (winnr('$')) + 1) .. '<C-w>w'
nnoremap <expr> <C-@>t '@_' .. ((v:count1 - 1) % (winnr('$')) + 1) .. '<C-w>w'
nnoremap <expr> <C-@>b '@_' .. (((- v:count1) % (winnr('$')) + winnr('$')) % (winnr('$')) + 1) .. '<C-w>w'
inoremap <C-@><C-@> <C-@>
map! <C-@>w <Esc><C-@>w
map! <C-@>W <Esc><C-@>W
map! <C-@>t <Esc><C-@>t
map! <C-@>b <Esc><C-@>b
tmap <C-@>w <C-@>N<C-@>w
tmap <C-@>W <C-@>N<C-@>W
tmap <C-@>t <C-@>N<C-@>t
tmap <C-@>b <C-@>N<C-@>b