From 9a1a338262caebd163bb90459e8014cb9108834b Mon Sep 17 00:00:00 2001 From: Dmytro Meleshko Date: Mon, 21 Jun 2021 19:00:00 +0300 Subject: [PATCH 1/3] [zsh] don't sync the cwd when a terminal is opened inside vscode (requested by @lexisother) --- zsh/zshrc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/zsh/zshrc b/zsh/zshrc index e8bf236..30832e9 100644 --- a/zsh/zshrc +++ b/zsh/zshrc @@ -65,6 +65,20 @@ if [[ -z "$DOTFILES_DISABLE_WELCOME" ]]; then welcome fi -if [[ -z "$DOTFILES_SYNC_LAST_WORKING_DIR" ]]; then +should_really_sync=0 +if [[ -v DOTFILES_SYNC_LAST_WORKING_DIR ]]; then + # Variable is defined + if [[ -n "$DOTFILES_SYNC_LAST_WORKING_DIR" ]]; then + # Variable is non-empty + should_really_sync=1 + fi +else + # Variable is undefined + if [[ "$TERM_PROGRAM" != "vscode" ]]; then + should_really_sync=1 + fi +fi +if (( should_really_sync )); then sync_working_dir_load fi +unset should_really_sync From 443f7aa32c3534e52c11f5e90d7913154e0da983 Mon Sep 17 00:00:00 2001 From: Dmytro Meleshko Date: Mon, 21 Jun 2021 19:26:58 +0300 Subject: [PATCH 2/3] [nvim] set the keymap globally in the switcher --- nvim/plugin/editing.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nvim/plugin/editing.vim b/nvim/plugin/editing.vim index 25a683e..bf4ece6 100644 --- a/nvim/plugin/editing.vim +++ b/nvim/plugin/editing.vim @@ -159,7 +159,7 @@ set commentstring=//%s nnoremap DotfilesSwapKeymaps let g:dotfiles_prev_keymap = &keymap - command! -nargs=0 DotfilesSwapKeymaps let [g:dotfiles_prev_keymap, &keymap] = [&keymap, g:dotfiles_prev_keymap] + command! -nargs=0 DotfilesSwapKeymaps let [g:dotfiles_prev_keymap, &g:keymap] = [&g:keymap, g:dotfiles_prev_keymap] " }}} From 4e8fbb481a745eb2eef471e8ece4f29d0b6794b6 Mon Sep 17 00:00:00 2001 From: Dmytro Meleshko Date: Mon, 21 Jun 2021 19:36:49 +0300 Subject: [PATCH 3/3] [crosscode] move most of the code into https://github.com/dmitmel/crosscode-tweak-pack --- .../assets/data/lang/sc/gui.en_US.json.patch | 16 - crosscode/btw-i-use-arch-mod/ccmod.json | 3 + crosscode/btw-i-use-arch-mod/package.json | 3 + crosscode/btw-i-use-arch-mod/poststart.js | 299 ------------------ crosscode/btw-i-use-arch-mod/prestart.js | 161 ---------- 5 files changed, 6 insertions(+), 476 deletions(-) delete mode 100644 crosscode/btw-i-use-arch-mod/assets/data/lang/sc/gui.en_US.json.patch diff --git a/crosscode/btw-i-use-arch-mod/assets/data/lang/sc/gui.en_US.json.patch b/crosscode/btw-i-use-arch-mod/assets/data/lang/sc/gui.en_US.json.patch deleted file mode 100644 index cf12f73..0000000 --- a/crosscode/btw-i-use-arch-mod/assets/data/lang/sc/gui.en_US.json.patch +++ /dev/null @@ -1,16 +0,0 @@ -{ - "labels": { - "options": { - "headers": { - "btw-i-use-arch": "btw I use Arch" - }, - "controls": { - "keys": { - "btw-i-use-arch": { - "open-map-menu": "Open/Close Map Menu" - } - } - } - } - } -} diff --git a/crosscode/btw-i-use-arch-mod/ccmod.json b/crosscode/btw-i-use-arch-mod/ccmod.json index 10f2db2..f5a112b 100644 --- a/crosscode/btw-i-use-arch-mod/ccmod.json +++ b/crosscode/btw-i-use-arch-mod/ccmod.json @@ -5,6 +5,9 @@ "icons": { "24": "icon24.png" }, + "dependencies": { + "crosscode-tweak-pack": "*" + }, "prestart": "prestart.js", "poststart": "poststart.js" } diff --git a/crosscode/btw-i-use-arch-mod/package.json b/crosscode/btw-i-use-arch-mod/package.json index e6d5b2e..fee2c33 100644 --- a/crosscode/btw-i-use-arch-mod/package.json +++ b/crosscode/btw-i-use-arch-mod/package.json @@ -2,6 +2,9 @@ "name": "btw-i-use-arch", "ccmodHumanName": "btw I use Arch", "description": "A mod for masochists like myself", + "dependencies": { + "crosscode-tweak-pack": "*" + }, "prestart": "prestart.js", "main": "poststart.js", "module": true diff --git a/crosscode/btw-i-use-arch-mod/poststart.js b/crosscode/btw-i-use-arch-mod/poststart.js index 0c99876..bf661c6 100644 --- a/crosscode/btw-i-use-arch-mod/poststart.js +++ b/crosscode/btw-i-use-arch-mod/poststart.js @@ -1,303 +1,4 @@ -// ac2pic: NOOOOO YOU CAN'T JUST PUT EVERYTHING IN POSTSTART/MAIN -// dmitmel: haha text editor go brrrr - export {}; ig.input.bind(ig.KEY.J, 'aim'); ig.input.bind(ig.KEY.K, 'dash'); - -function findRootGuiElement(clazz) { - return ig.gui.guiHooks.find(({ gui }) => gui instanceof clazz).gui; -} - -const quickMenu = findRootGuiElement(sc.QuickMenu); - -const myAddon = { - name: 'btw I use Arch addon', - - onPostUpdate() { - if (ig.loading || sc.model.isPlayerControlBlocked()) return; - - if (ig.input.pressed('btw-i-use-arch.open-map-menu')) { - if ( - sc.model.isGame() && - sc.model.isMenu() && - sc.menu.currentMenu === sc.MENU_SUBMENU.MAP && - // check if the help screen or a dialog isn't opened, otherwise it will - // block the screen after switching back to the game - ig.interact.entries.last() === sc.menu.buttonInteract - ) { - closeMapMenu(); - sc.BUTTON_SOUND.back.play(); - } else if ( - sc.model.isGame() && - sc.model.isRunning() && - // check if the quick menu has been unlocked yet, the map menu becomes - // available at the same moment - sc.model.player.getCore(sc.PLAYER_CORE.QUICK_MENU) - ) { - let openedMapMenu = openMapMenu(); - sc.BUTTON_SOUND[openedMapMenu ? 'submit' : 'denied'].play(); - } - } - }, -}; - -ig.ENTITY.Crosshair.inject({ - // Normally the `this._getThrowerPos` method is used to calculate where the - // balls are thrown _from_ in almost screen coordinates, but we can repurpose - // it to calculate where the balls should be thrown _at_ to hit an entity. - _getThrowPosForEntity(outVec2, entity) { - let realThrower = this.thrower; - try { - this.thrower = entity; - return this._getThrowerPos(outVec2); - } finally { - this.thrower = realThrower; - } - }, -}); - -// these two constants will come in handy later, see `focusNextEntity` -const ENTITY_FOCUS_DIRECTION = { - FARTHER: 1, - CLOSER: -1, -}; - -// buffer vectors for calculations -let vec2a = Vec2.create(); -let vec2b = Vec2.create(); - -sc.PlayerCrossHairController.inject({ - focusedEntity: null, - prevMousePos: Vec2.createC(-1, -1), - - updatePos(...args) { - // gamepad mode is unsupported because I don't have one to test this code on - if (this.gamepadMode) { - this.parent(...args); - return; - } - - let [crosshair] = args; - - // focus the next available entity if this combatant is e.g. dead - if ( - this.focusedEntity != null && - !this.shouldEntityBeFocused(this.focusedEntity) - ) { - this.focusNextEntity(crosshair, ENTITY_FOCUS_DIRECTION.CLOSER); - } - - let mouseX = sc.control.getMouseX(); - let mouseY = sc.control.getMouseY(); - if ( - this.focusedEntity != null && - // unfocus if the mouse has been moved - (this.prevMousePos.x !== mouseX || this.prevMousePos.y !== mouseY) - ) { - this.focusedEntity = null; - } - Vec2.assignC(this.prevMousePos, mouseX, mouseY); - - // handle controls - let pressedFocusCloser = ig.input.pressed('circle-left'); - let pressedFocusFarther = ig.input.pressed('circle-right'); - if (pressedFocusCloser) { - this.focusNextEntity(crosshair, ENTITY_FOCUS_DIRECTION.CLOSER); - } - if (pressedFocusFarther) { - this.focusNextEntity(crosshair, ENTITY_FOCUS_DIRECTION.FARTHER); - } - if ( - (pressedFocusCloser || pressedFocusFarther) && - this.focusedEntity == null - ) { - sc.BUTTON_SOUND.denied.play(); - } - - if (this.focusedEntity != null) { - this.calculateCrosshairPos(crosshair); - } else { - this.parent(...args); - } - }, - - focusNextEntity(crosshair, direction) { - let throwerPos = crosshair._getThrowerPos(vec2a); - - function getSqrDistToEntity(entity) { - let entityPos = crosshair._getThrowPosForEntity(vec2b, entity); - return Vec2.squareDistance(throwerPos, entityPos); - } - - let prevFocusedEntity = this.focusedEntity; - let prevFocusedSqrDist = - prevFocusedEntity != null ? getSqrDistToEntity(prevFocusedEntity) : null; - this.focusedEntity = null; - - let closestNextEntitySqrDist = null; - for (let entity of this.findFocusingCandidateEntities()) { - if (entity === prevFocusedEntity) continue; - - let sqrDist = getSqrDistToEntity(entity); - if ( - // multiplication by `dirFactor` effectively inverts the comparison - // operator when it is negative, otherwise logically the expression - // stays the same - (prevFocusedSqrDist == null || - sqrDist * direction > prevFocusedSqrDist * direction) && - (closestNextEntitySqrDist == null || - sqrDist * direction < closestNextEntitySqrDist * direction) - ) { - closestNextEntitySqrDist = sqrDist; - - this.focusedEntity = entity; - } - } - }, - - shouldEntityBeFocused(combatant) { - return ( - !combatant.isDefeated() && - // `sc.ENEMY_AGGRESSION.TEMP_THREAT` exists, but to be honest I have no - // idea what it is supposed to do - combatant.aggression === sc.ENEMY_AGGRESSION.THREAT - ); - }, - - findFocusingCandidateEntities() { - let allCombatants = sc.combat.activeCombatants[sc.COMBATANT_PARTY.ENEMY]; - let candidates = allCombatants.filter((enemy) => - this.shouldEntityBeFocused(enemy), - ); - - if (candidates.length === 0) { - candidates = ig.game.shownEntities.filter( - (entity) => - entity != null && - !entity._killed && - entity instanceof ig.ENTITY.Enemy && - ig.CollTools.isInScreen(entity.coll) && - this.shouldEntityBeFocused(entity), - ); - } - - return candidates; - }, - - calculateCrosshairPos(crosshair) { - let { thrower } = crosshair; - let throwerPos = crosshair._getThrowerPos(vec2a); - let entityPos = crosshair._getThrowPosForEntity(vec2b, this.focusedEntity); - let entityVel = this.focusedEntity.coll.vel; - - let ballInfo = sc.PlayerConfig.getElementBall( - thrower, - thrower.model.currentElementMode, - // NOTE: This causes glitches when the ball speed affects the crosshair - // position too much, in which case it begins jumping back and forth - // because the charged status is reset due to the movement. I hope this - // isn't to much of a problem. - crosshair.isThrowCharged(), - ); - let ballSpeed = ballInfo.data.speed; - - let crosshairPos = crosshair.coll.pos; - Vec2.assign(crosshairPos, entityPos); - // perform entity movement prediction repeatedly to increase the precision - for (let i = 0; i < 3; i++) { - let t = Vec2.distance(throwerPos, crosshairPos) / ballSpeed; - crosshairPos.x = entityPos.x + Math.round(entityVel.x) * t; - crosshairPos.y = entityPos.y + Math.round(entityVel.y) * t; - } - }, -}); - -const PLAYER_LOCATION_IN_ROOM_ICON = { - x: 280, - y: 436, - w: 10, - h: 9, -}; - -sc.MapCurrentRoomWrapper.inject({ - updateDrawables(renderer) { - this.parent(renderer); - - let player = ig.game.playerEntity; - let x = player.coll.pos.x * (this.hook.size.x / ig.game.size.x); - let y = player.coll.pos.y * (this.hook.size.y / ig.game.size.y); - - let sprite = PLAYER_LOCATION_IN_ROOM_ICON; - renderer.addGfx( - this.gfx, - Math.round(x - sprite.w / 2), - Math.round(y - sprite.h / 2), - sprite.x, - sprite.y, - sprite.w, - sprite.h, - ); - }, -}); - -function openMapMenu() { - // Check for the common conditions upfront, because opening and then - // immediately closing the quick menu causes the element indicator in the top - // left corner to jump, which is, of course, undesirable. Other conditions may - // be present implicitly or added explicitely in the future, but these two are - // the obvious ones I could find. - if (!sc.model.isSaveAllowed() || sc.model.isTeleportBlocked()) return false; - - // User's actions required in order to open the map need to be carefully - // emulated here instead of directly calling methods of `sc.model` and - // `sc.menu` because of the model notifications sent during the intended user - // interaction path (which trigger changes to the UI all over the codebase) - // and potential (although unlikely) changes to the internals of the methods - // I'm using here. Also, I chose to use the quick menu instead of the main one - // because the main one is unlocked at the end of the rhombus dungeon which is - // a bit later than the quick one and the map menu in particular both become - // available. - let enteredQuickMenu = sc.model.enterQuickMenu(); - if (!enteredQuickMenu) return false; - // I wonder why this variable isn't set internally by `enteredQuickMenu`, but - // I have to do this here because not doing that creates a very annoying bug - // when the quick menu access method is set to "hold": the quick menu becomes - // impossible to close by pressing shift and to close it you have to open and - // close the map menu again manually. - sc.quickmodel.activeState = true; - - let quickRingMenu = quickMenu.ringmenu; - let mapButton = quickRingMenu.map; - if (!mapButton.active) { - // some additional conditions may be present as noted above, so in the case - // the button intended to be pressed by user is inactive we bail out safely - sc.quickmodel.activeState = false; - sc.model.enterRunning(); - return false; - } - - // And finally, press the "map" button! - quickRingMenu.buttongroup._invokePressCallbacks( - mapButton, - /* fromMouse */ false, - ); - return true; -} - -function closeMapMenu() { - // Let's exit the world map just in case, for the same reason as I emulate - // user interactions in the `openMapMenu` function. - if (sc.menu.mapWorldmapActive) sc.menu.exitWorldMap(); - - sc.model.enterPrevSubState(); -} - -{ - let globalInputAddonIdx = ig.game.addons.postUpdate.findIndex( - (addon) => addon instanceof sc.GlobalInput, - ); - console.assert(globalInputAddonIdx >= 0, 'inputPostUpdateIdx >= 0'); - ig.game.addons.postUpdate.splice(globalInputAddonIdx + 1, 0, myAddon); -} diff --git a/crosscode/btw-i-use-arch-mod/prestart.js b/crosscode/btw-i-use-arch-mod/prestart.js index 9be33fe..e69de29 100644 --- a/crosscode/btw-i-use-arch-mod/prestart.js +++ b/crosscode/btw-i-use-arch-mod/prestart.js @@ -1,161 +0,0 @@ -sc.OPTIONS_DEFINITION['keys-btw-i-use-arch.open-map-menu'] = { - type: 'CONTROLS', - cat: sc.OPTION_CATEGORY.CONTROLS, - init: { key1: ig.KEY.M }, - hasDivider: true, - header: 'btw-i-use-arch', -}; - -ig.KEY.MOUSE_LEFT = ig.KEY.MOUSE1; -ig.KEY.MOUSE_RIGHT = ig.KEY.MOUSE2; -ig.KEY.MOUSE_MIDDLE = -6; -ig.KEY.MOUSE_BACK = -7; -ig.KEY.MOUSE_FORWARD = -8; - -// As for the copied implementations of ig.Input#keydown and ig.Input#keyup: -// there is probably a way to avoid copying, most notably by abusing the logic -// of the keyCode check. See, in both methods it is basically the same, just -// with differing event names, but the logic is as follows: if the event is a -// keyboard event, get the `keyCode` property, otherwise check if -// `event.button` is 2, then assume the key is `ig.KEY.MOUSE2`, otherwise -// `ig.KEY.MOUSE1`. This means that I could replace the value of the `MOUSE1` -// constant to the keyCode determined with my custom logic, and so the fallback -// path will read my value, but ultimately I didn't do that because I figured -// there might be other parts of these functions which can use some -// refactoring. -ig.Input.inject({ - keydown(event) { - if ( - ig.system.crashed || - this.isInIframeAndUnfocused() || - (this.ignoreKeyboard && event.type !== 'mousedown') - ) { - return; - } - - if (ig.system.hasFocusLost()) { - if (event.type === 'mousedown') { - ig.system.regainFocus(); - } - return; - } - - if (event.type === 'mousedown') { - this.mouseGuiActive = true; - } - this.currentDevice = ig.INPUT_DEVICES.KEYBOARD_AND_MOUSE; - - if (event.target.type === 'text') { - return; - } - - let keyCode = this.getKeyCodeFromEvent(event); - - if ( - // It's quite interesting that the game kinda supports touch events, but - // they are never actually used in practice. - event.type === 'touchstart' || - event.type === 'mousedown' - ) { - this.mousemove(event); - } - - let action = this.bindings[keyCode]; - if (action != null) { - this.actions[action] = true; - // Not sure what are locks supposed to do. Oh wait, I figured it out: - // this is so that if a button is detected to be pressed in a frame, but - // if an un-press event is caught during the processing of the frame, the - // button... Hmmm, still not sure. Entirety of the game logic blocks the - // main thread, so it's impossible to catch two events during processing - // of the frame. - if (!this.locks[action]) { - this.presses[action] = true; - this.locks[action] = true; - } - event.stopPropagation(); - event.preventDefault(); - } - }, - - keyup(event) { - if ( - ig.system.crashed || - this.isInIframeAndUnfocused() || - (this.ignoreKeyboard && event.type !== 'mouseup') || - event.target.type === 'text' || - (ig.system.hasFocusLost() && event.type === 'mouseup') - ) { - return; - } - - this.currentDevice = ig.INPUT_DEVICES.KEYBOARD_AND_MOUSE; - - let keyCode = this.getKeyCodeFromEvent(event); - - let action = this.bindings[keyCode]; - if (action != null) { - this.keyups[action] = true; - this.delayedKeyup.push(action); - event.stopPropagation(); - event.preventDefault(); - } - }, - - getKeyCodeFromEvent(event) { - switch (event.type) { - case 'keyup': - case 'keydown': - return event.keyCode; - - case 'mouseup': - case 'mousedown': - switch (event.button) { - case 0: - return ig.KEY.MOUSE_LEFT; - case 1: - return ig.KEY.MOUSE_MIDDLE; - case 2: - return ig.KEY.MOUSE_RIGHT; - case 3: - return ig.KEY.MOUSE_BACK; - case 4: - return ig.KEY.MOUSE_FORWARD; - } - } - - // idk, fall back to the left mouse button. That's kind of what the default - // implementation does though. - return ig.KEY.MOUSE_LEFT; - }, -}); - -// Finally, some nice injection places. -sc.KeyBinderGui.inject({ - show(...args) { - this.parent(...args); - window.addEventListener('mousedown', this.bindedKeyCheck, false); - }, - - hide(...args) { - this.parent(...args); - window.removeEventListener('mousedown', this.bindedKeyCheck); - }, - - onKeyCheck(event) { - event.preventDefault(); - - let keyCode = ig.input.getKeyCodeFromEvent(event); - if (ig.interact.isBlocked() || this._isBlackedListed(keyCode)) return; - - // This call was added by me. Just in case. Because the `stopPropagation` - // call in `ig.Input` saved me from re-binds of left/right mouse buttons to - // whatever else other than interactions with menus. - event.stopPropagation(); - - if (this.finishCallback != null) { - this.finishCallback(keyCode, this.isAlternative, false); - } - this.hide(); - }, -});