How to load fish command history from file - fish

Is there a way to load commands-history of fish from a file?
I like to clear my history periodically, but keep a set of useful commands always in history for easily accessing.
In bash this can be done via:
history -r file.txt
Can this be done in fish?

In my experience what you want to do isn't really necessary since a) fish only remembers the most recent instance of a command and b) generally does a really good job of using available context to provide the most appropriate entry from the command history, and c) already trims old entries once the number of saved commands reaches a limit.
But, assuming you've saved your preferred history subset to ~/.local/share/fish/fish_history.save:
builtin history clear
cp ~/.local/share/fish/fish_history.save ~/.local/share/fish/fish_history
history merge
The builtin in the first instance is to avoid the prompt asking if you really want to clear your history. Note that your saved history has to be valid YAML. It's a text file but is a little more complex than just each command on a separate line.

Related

Can I have VS Code skip opening previous workspaces one time only?

I use many VS Code workspaces throughout the day. Most of them are backed by directories on NFS-mounted drives, which are only mounted while I'm VPN'd in to my employer's network. Opening VS Code while not VPN'd in will cause all of my windows to close, leaving me with blank/empty workspaces, and then I have to set them all back up again in the morning. It only takes a few minutes to do, but I'm lazy and it's not neat; I like things neat. I know that I can start VS Code without any workspaces using the -n option, which is great, but then the next time I start up the editor for real (i.e. for work purposes), all of my workspaces need to be reopened again (see previous statement re: I'm lazy and I like things neat).
Is there a way to indicate that I want to start VS Code without any project just this one time, and then the next time I start I want all of my old workspaces to reopen as normal? Alternately, does anyone know where the state information is stored and how to edit it? I have no qualms about saving it off and then restoring it after I'm done.
Absent any miracle solution, I've at least found the correct file to manipulate: the storage.json file, which on MacOS is found at:
~/Library/Application Support/Code/storage.json
I wrote a Perl script to do the manipulation. When I want to go "offline" it reads in the JSON file, loops through the opened windows, identifies the ones I don't want, and removes them using jq, then launches VS Code. When I'm ready to go back "online", I read a backup of the original file looking for the windows I previously removed, adds them back in (also using jq), and then launches VS Code.
The Perl script is a bit rough around the edges to be posted publicly, but people might find the jq helpful. To delete, you want to identify the windows to be removed as (zero-based) indexes in the array, and then delete them with the following:
jq '. | del(.windowsState.openedWindows[1,2,5])' '/Users/me/backups/online-storage.json' >'/Users/me/Library/Application Support/Code/storage.json'
If you want to add them back in at some point, you extract the full JSON bits from the backup file, and then use the following command to append them to the back of the array:
jq '.windowsState.openedWindows += [{"backupPath":"...",...,"workspaceIdentifier": {...}}, {"backupPath":"...",...,"workspaceIdentifier": {...}}, {"backupPath":"...",...,"workspaceIdentifier": {...}}]' '/Users/me/backups/offline-storage.json' >'/Users/me/Library/Application Support/Code/storage.json'
The inserted JSON is elided for clarity; you'll want to include the full JSON strings, of course. I don't know what significance the ordering has, so pulling them out of the middle of the array and appending them to the end of the array will likely have some consequence; it's not significant for my purposes, but YMMV.

VSCode - How to delete a specific command history in command palette (as opposed to clearing everything)?

I would like to delete several commands from VSCode command palette's "recently used" section, but not clear the entire history. How?
So in Chrome's Omnibar, you can use Shift+del to delete a suggestion. But I cannot find an analogous shortcut in VSCode's command palette.
I also looked for a "meta-command" for this, but I only found Clear Command History in the command palette. I want something like Edit/Manage Command History instead.
Edit: a history file that I can directly edit (analogous to ~/.bash_history for Bash) would also do.
Okay, so this question was upvoted today, which brought it back to my attention. I decided to bite the bullet this time and dug into the nuts and bolts of VSCode's files and found where this history is stored.
TLDR
Modifying the history is doable (obviously, because it has to be stored somewhere), but it's not very practical at all. Unfortunately it will continue to be very difficult, until VSCode implements official support (which may be never). I recommend using the following method ONLY IF you absolutely need a history entry deleted.
The method
Note:
I'm using Code OSS (the debranded build of VSCode) on Linux. The method should be applicable to other OSes, but the specific commands and paths will be different.
This method works on VSCode 1.74.2, the latest version as of 2023-01-04. It may or may not work with future versions.
0. Exit VSCode completely
Obviously.
Check with your resource/task/process manager to make sure VSCode is completely killed. If you're not sure, just reboot.
1. Locate lastSyncglobalState.json
This file contains the command palette history data. On Linux it's located at $XDG_CONFIG_HOME/Code - OSS/User/sync/globalState/lastSyncglobalState.json. On Windows it's probably under a similar path in %APPDATA%. Not sure about MacOS. Copy this file to somewhere convenient.
If you are curious how I discovered this file, I did a search of a command I recently ran using rg in $XDG_CONFIG_HOME/Code - OSS/. Note that you have to search the "programmatic name" of the command, not its display name (e.g. rust-analyzer.reload, not rust-analyzer: Restart server).
2. Extract the relevant data
If you open up lastSyncglobalState.json with a text editor directly, you'll find a Russian doll of escaped JSON. Technically you can do the modification straight from here, but I'm not eating this 💩.
Fortunately jq makes this somewhat easier:
# This is Bash but I think it works on Windows CMD too? Not sure.
jq '.syncData.content | fromjson.storage."commandPalette.mru.cache".value | fromjson.entries' lastSyncglobalState.json > history.json
The extracted history.json should look something like this:
[
{
"key": "rust-analyzer.debug",
"value": 297
},
{
"key": "rust-analyzer.syntaxTree",
"value": 298
},
// more entries...
]
3. Modify
Copy history.json to history-new.json, and simply remove the entries you want to delete from history-new.json. Do not modify history.json; we will need it in a bit.
Check that it's still valid JSON after your edits; in particular make sure that you have not left a trailing comma in the array.
4. Write back
The responsible way to do this is to perform the inverse of step 2, starting from the bottom up, update a field, json-encode, then update the field one level up, json-encode again, etc, until we get to the top level. But that's an enormous pain in the arse to do with jq.
Much easier I think, simply double (triple?) json-encode history-new.json, and perform a textual replacement. This is where the original history.json comes in handy:
# In lastSyncglobalState.json, replace the output of...
jq 'tojson | tojson' history.json
# with the output of...
jq 'tojson | tojson' history-new.json
Note that since the output of jq is quoted, it's necessary to remove the outmost layer of quotes (") on both the search string and the replace string. With rg we can automate this:
jq 'tojson | tojson' history.json | rg '^"(.+)"$' -r '$1'
jq 'tojson | tojson' history-new.json | rg '^"(.+)"$' -r '$1'
Of course there's nothing wrong with doing it manually, or with using sed instead if you want to. Again, just be careful you're not creating invalid JSON.
5. Copy back into VSCode directory
Honestly, you probably want to make a backup of the entire $XDG_CONFIG_HOME/Code - OSS/ directory (or whatever it is on your machine) before doing this. It's probably big I know, but I'm not sure what crazy thing VSCode will do if it finds lastSyncglobalState.json unparseable. Better be safe than sorry.
After you've done that, just copy your modified lastSyncglobalState.json back into $XDG_CONFIG_HOME/Code - OSS/User/sync/globalState/lastSyncglobalState.json and voila.
VSCode terminal uses external shell. For linux the default shell it's bash, for windows it's powershell.
If your terminal shell is powershell, go to C:\Users\john\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline on your file explorer
Visit this link for more details, if the above does not help.

Changing the commit message while grafting a large number of changesets using Mercurial

I need to graft a large number (thousands) of small changesets from branch A to branch B - but need to alter the commit message in the process.
The message change needs to look roughly like this:
"Ref XXX: Fixed foo and bar" -> "GRAFT: Ref YYY: Fixed foo and bar".
In other words, I need to prepend "GRAFT:" and change a reference number. If I can't make these replacements directly with Mercurial, I could create the new commit messages all in advance then make a script to apply each new message during its respective graft. Happily, Mercurial allows editing commit messages during grafting, with the -e argument:
https://www.mercurial-scm.org/repo/hg/help/graft
The problem is that this pops up a text editor for each changeset for me to make the change manually. There doesn't seem to be a way to amend the message in a programmatic way, or just to provide an entirely new message, at the comment line. Given the size of operation, using the editor each time isn't plausible.
My last option would be to use the text editor with some sort of AutoIt/Macro script to enter the right things in the places at the right times - but the thought of needing to resort to this is frankly making me feel a bit ill.
Save me from this ugly fate.
Thanks in advance.
A possible workaround is to specify the use of a shell script in lieu of an editor. For example:
#!/bin/sh
sed -e '1,1s/^/GRAFT: /' -i "$1"
We're making use of the fact that with -i, sed will do an in-place edit. Don't forget to make the shell script executable. Then you can run
hg graft --config ui.editor=/path/to/prepend-graft.sh -e -r <revision>
where /path/to/prepend-graft.sh is the path of the aforementioned shell script.
Changing a number may require code that's more complex than a sed script, but would follow the same approach.

Perl script to find out add/edit or delete done by an user for a workspace in Perforce

perforce list out the files submitted by an user i.e.
p4 changes -u
what i would like to do is write a small function in perl which will find
what changes have been submitted by user
what operations has been performed for those changes i.e. add, edit or delete and print those .
so logic is something like this
1. find changes submitted by an user
2. what operation has been performed on those changes
result :
user has 5 change list submitted after date ...
5 add, 2 delete and 1 edit operation found in all changes.
It's not clear what you are stumbling on.
If it's connecting to perforce from Perl, you can use one of several CPAN modules for the purpose: see the first hits in googling for "CPAN perforce".
If you wish to parse STDOUT output from p4 changes -u command line instead, please post the exact output format from the command, what you tried so far to parse it, and desired matching output from your program.

Emacs: Is there a way to generate a skeleton ChangeLog from diff?

I'd like to partly automate creation of GNU-style ChangeLog entries when working with source code in version control. The add-changelog-entry-other-window works with one file at a time and you have to visit the file to use it.
What I'd like to see instead is to have some command that would take an output of diff -u -p (or have integration with VC modes so it could process svn diff etc) and to create all the skeleton entries at once.
For example, if svn status shows
D file1.c
M file2.c
A file3.c
the command would create
2009-09-05 My Name <my.email>
* file1.c: Removed.
* file2.c: WRITE YOUR CHANGES HERE
* file3.c: New.
Better yet, if it could parse the changed files in some languages to an extent so it could offer:
* file2.c (new_function): New function.
(deleted_function): Removed.
(changed_function): WRITE YOUR CHANGES HERE
I have found this feature in Emacs manual, but I don't see how I could apply it here.
Any suggestions? Thanks.
EDIT: One answer suggested vc-update-change-log. Unfortunately it only supports CVS and it creates ChangeLog entries by querying the already-commited VC logs. Thus even if it supported svn and others, it would be impossible to commit the changes and the ChangeLog in the same commit.
EDIT2: Apparently add-changelog-entry-other-window (C-x 4 a) works not only from visited file but from diff hunk involving that file too. (Source) This is almost what I am looking for. This together with elisp loop to iterate through all hunks should solve it.
There is a function vc-update-change-log that automatically generates change log entries from the version control log entries.
diff-add-change-log-entries-other-window is documented to do exactly what you mentioned in EDIT2:
diff-add-change-log-entries-other-window is an interactive compiled
Lisp function in `diff-mode.el'.
(diff-add-change-log-entries-other-window)
Iterate through the current diff and create ChangeLog entries.
I.e. like `add-change-log-entry-other-window' but applied to all hunks.
Unfortunately, it doesn't work very well for, say, new files: it doesn't even include the filenames of such files in the skeletal changelog entry.
You might have better luck with gcc's mklog script, which you can get from http://gcc.gnu.org/viewcvs/gcc/trunk/contrib/mklog.
I don't know of a function that does this, but it should be easy to implement. Basically, you want to
get the changed files
for each file, call add-change-log
"Find change log file, and add an entry for today and an item for this file.
Optional arg WHOAMI (interactive prefix) non-nil means prompt for user
name and email (stored in `add-log-full-name' and `add-log-mailing-address').
Second arg FILE-NAME is file name of the change log.
If nil, use the value of `change-log-default-name'.
Third arg OTHER-WINDOW non-nil means visit in other window.
Fourth arg NEW-ENTRY non-nil means always create a new entry at the front;
never append to an existing entry. Option `add-log-keep-changes-together'
otherwise affects whether a new entry is created.
Option `add-log-always-start-new-record' non-nil means always create a
new record, even when the last record was made on the same date and by
the same person.
The change log file can start with a copyright notice and a copying
permission notice. The first blank line indicates the end of these
notices.
Today's date is calculated according to `add-log-time-zone-rule' if
non-nil, otherwise in local time."
so the magic code is going to look something like
(apply 'make-magic-change-log-entry changed-files-list)
and make-magic-change-log-entry simply curries the add-change-log function so that the only argument is file-name — you set the other ones.
I've written a function to do something similar to what you were talking about. You can get the code at http://www.emacswiki.org/emacs/log-edit-fill