Saving Tab names and ConqueShells along with Vim sessions - shell

Is there any way to get vim to save the tab names (assigned via the Tab Name script) and/or a terminal emulator (set up via the Conque Shell script) upon issuing the :mksession [fileName] command?
Observe below (zoom in), I have a working session on the left, and the same session loaded via the vim -S fileName command, on the right. The assigned tab labels revert to absolute paths, ConqueShell terminal is interpreted as a file.

After learning some basic VimScript I just gave up and used Python instead (to cite one example, you can't save global information to a session if it is a list). Here is a solution I found for saving tab names (will post a solution for ConqueShell if I find one)
Put the following in your .vimrc file and use whatever mapping you want to quickly save and load your sessions
"Tokenize it so it has the following form (without spaces)
"Label1 JJ Label2 JJ Label3 JJ Label4
"Or if you prefer use something other than 'JJ' but DO NOT
"use symbols as they could interfere with the shell command
"line
function RecordTabNames()
"Start at the first tab with no tab names assigned
let g:TabNames = ''
tabfirst
"Iterate over all the tabs and determine whether g:TabNames
"needs to be updated
for i in range(1, tabpagenr('$'))
"If tabnames.vim created the variable 't:tab_name', append it
"to g:TabNames, otherwise, append nothing, but the delimiter
if exists('t:tab_name')
let g:TabNames = g:TabNames . t:tab_name . 'JJ'
else
let g:TabNames = g:TabNames . 'JJ'
endif
"iterate to next tab
tabnext
endfor
endfunction
func! MakeFullSession()
call RecordTabNames()
mksession! ~/.vim/sessions/Session.vim
"Call the Pythin script, passing to it as an argument, all the
"tab names. Make sure to put g:TabNames in double quotes, o.w.
"a tab label with spaces will be passed as two separate arguments
execute "!mksession.py '" . g:TabNames . "'"
endfunc
func! LoadFullSession()
source ~/.vim/sessions/Session.vim
endfunc
nnoremap <leader>mks :call MakeFullSession()<CR>
nnoremap <leader>lks :call LoadFullSession()<CR>
Now create the following text file and put it somewhere in your PATH variable (echo $PATH to get it, mine is at /home/user/bin/mksession.py) and make sure to make it executable (chmod 0700 /home/user/bin/mksession.py)
#!/usr/bin/env python
"""This script attempts to fix the Session.vim file by saving the
tab names. The tab names must be passed at the command line,
delimitted by a unique string (in this case 'JJ'). Also, although
spaces are handled, symbols such as '!' can lead to problems.
Steer clear of symbols and file names with 'JJ' in them (Sorry JJ
Abrams, that's what you get for making the worst TV show in history,
you jerk)
"""
import sys
import copy
if __name__ == "__main__":
labels = sys.argv[1].split('JJ')
labels = labels[:len(labels)-1]
"""read the session file to add commands after tabedit
" "(replace 'USER' with your username)
"
f = open('/home/USER/.vim/sessions/Session.vim', 'r')
text = f.read()
f.close()
"""If the text file does not contain the word "tabedit" that means there
" "are no tabs. Therefore, do not continue
"""
if text.find('tabedit') >=0:
text = text.split('\n')
"""Must start at index 1 as the first "tab" is technically not a tab
" "until the second tab is added
"""
labelIndex = 1
newText = ''
for i, line in enumerate(text):
newText +=line + '\n'
"""Remember that vim is not very smart with tabs. It does not understand
" "the concept of a single tab. Therefore, the first "tab" is opened
" "as a buffer. In other words, first look for the keyword 'edit', then
" "subsequently look for 'tabedit'. However, when being sourced, the
" "first tab opened is still a buffer, therefore, at the end we will
" "have to return and take care of the first "tab"
"""
if line.startswith('tabedit'):
"""If the labelIndex is empty that means it was never set,
" "therefore, do nothing
"""
if labels[labelIndex] != '':
newText += 'TName "%s"\n'%(labels[labelIndex])
labelIndex += 1
"""Now that the tabbed windowing environment has been established,
" "we can return to the first "tab" and set its name. This serves
" "the double purpose of selecting the first tab (if it has not
" "already been selected)
"""
newText += "tabfirst\n"
newText += 'TName "%s"\n'%(labels[0])
#(replace 'USER' with your username)
f = open('/home/USER/.vim/sessions/Session.vim', 'w')
f.write(newText)
f.close()

Related

Having trouble with a vbscript creating a new vbscript containing a variable from the original

I am trying to make a vbs that creates a new vbs file, but im having some trouble with the creation of the second file.
Earlier in the first script it asks for your desired username, which is then assigned to a variable named user.
When it creates the second script, i want the user name to display in a message saying Welcome back [insert username here]. Please input a program value.
problem is, i cant get it to place your username inside of the new scripts code.
attempt 1
If VTCreate1 = 6 And VTCreate2 = 7 And VTCreate3 = 7 And VTCreate4 = 7 And VTCreate5 = 7 Then
Set objFile = objFS.CreateTextFile("C:\Users\Public\Desktop\Aeshnidae_1627374757.vbs")
objFile.WriteLine("vtcmd=inputbox(""Welcome back "")" & user & "("". Please input a program value."")")
attempt 1 results in the newly created script containing the following
vtcmd=inputbox("Welcome back ")Human(". Please input a program value.")
attempt 2
If VTCreate1 = 6 And VTCreate2 = 7 And VTCreate3 = 7 And VTCreate4 = 7 And VTCreate5 = 7 Then
Set objFile = objFS.CreateTextFile("C:\Users\Public\Desktop\Aeshnidae_1627374757.vbs")
objFile.WriteLine("vtcmd=inputbox(""Welcome back & user & . Please input a program value."")")
attempt 2 results in the following
vtcmd=inputbox("Welcome back & user & . Please input a program value.")
any idea how to get the desired username properly inside of the message?
Let's start with the final desired output line
vtcmd=inputbox("Welcome back xxxxxx. Please input a program value")
To place it inside a string variable (what we will later write) we need to quote the line and escape inner double quotes
"vtcmd=inputbox(""Welcome back xxxxxx. Please input a program value"")"
To replace the placeholder we need to cut our string
"vtcmd=inputbox(""Welcome back " ". Please input a program value"")"
close quote ^ ^ open quote
And concatenate the variable with the two strings
"vtcmd=inputbox(""Welcome back " & user & ". Please input a program value"")"
So, the final code line will be
objFile.WriteLine "vtcmd=inputbox(""Welcome back " & user & ". Please input a program value"")"

Locating and opening programs based on a word in python

I have a script where a user will input a program to open, and that script will open the program. The way I've done it isn't very efficient and so I'm leading into problems.
If I input "Open chrome", the script starts a search for a file called chrome.exe on your computer and then launches it. This works for a few programs like chrome.exe, steam.exe etc, but there are programs where their exe file is named differently.
For example, "Open word". The script will search for a program named word.exe, but the Microsoft Word exe file is actually named WINWORD.EXE, so the search will fail.
So my question is how can I make this more efficient? I know I could add exceptions and find the directory of the file myself but this would be impractical to do for many programs.
with sr.Microphone() as source:
success = False
print (">")
audio = r.listen(source)
try:
print("Processing...")
t = r.recognize_google(audio)
print (": " + t)
except sr.UnknownValueError:
print("Unknown input")
continue
except sr.RequestError as e:
print("An error occured at GAPI\nA common cause is lack of internet connection")
continue
if "open" in t:
t = t.replace("open","")
t = t.replace(" ","")
z = t
speak = "Opening " + z
t = t + ".exe"
print (t)
for a,d,f in os.walk("C:\\"):
for files in f:
if files == t.lower() or files == t.capitalize() or files == t.upper():
s.Speak(speak)
pat = os.path.join(a,files)
print (pat)
sp.call([pat])
success = True
Edit:
I did some research and found out about something called filename pattern searching. I've been unable get it running, any ideas?

Use CMD-mappings in console Vim

Is there a way to use Cmd key for Vim in terminal? Something MacVim does.
I have remapped Cmd+S in iTerm2 to send Esc:w!<CR> to save files in Vim, but this sounds a bit weak.
With all the power of iTerm and Vim there should be some way to do this right?
It is possible, but it takes some doing and has some downsides.
The first set of issues is that:
although iTerm2 can accept the Command keys and pass them on to terminal programs, it can only do so by remapping them as something else, e.g. the Left Option or Control keys.
it can only remap each modifier key everywhere in iTerm2; you can't do it just for certain windows, panes, or profiles.
in order to remap a modifier within the terminal, you need to allow iTerm2 to control the computer in the Security & Privacy preference pane; when you configure iTerm2 to do remapping, it will direct you there automatically.
once you've remapped Left Command, things like Left Command+N to open a new window no longer work. Luckily, though, you can remap e.g. Left Option to Left Command and still have your Right Command key available for Mac shortcuts; or you can switch around your Command and Option keys.
The remaining issue is that Vim isn't configured out of the box with Mac-like key bindings. Luckily, MacVim includes most of its Mac-style GUI bindings in /Applications/MacVim.app/Contents/Resources/vim/runtime/macmap.vim rather than coding them in Interface Builder or Objective-C source; so I was able to copy those and adapt them for the terminal. Here is a config that works pretty closely to MacVim (and other Mac apps):
" Keybindings for terminal vim; mostly to emulate MacVim (somewhat)
" See /Applications/MacVim.app/Contents/Resources/vim/runtime/macmap.vim (from
" which many of the following are taken); and menu.vim in the same directory.
" Since these all have native (Cmd-modified) versions in MacVim, don't bother
" defining them there.
" A utility function to help cover our bases when mapping.
"
" Example of use:
" call NvicoMapMeta('n', ':new<CR>', 1)
" is equivalent to:
" exec "set <M-n>=\<Esc>n"
" nnoremap <special> <Esc>n :new<CR>
" vnoremap <special> <Esc>n <Esc><Esc>ngv
" inoremap <special> <Esc>n <C-o><Esc>n
" cnoremap <special> <Esc>n <C-c><Esc>n
" onoremap <special> <Esc>n <Esc><Esc>n
function! NvicoMapMeta(key, cmd, add_gv)
" TODO: Make this detect whether key is something that has a Meta
" equivalent.
let l:keycode = "<M-" . a:key . ">"
let l:set_line = "set " . l:keycode . "=\<Esc>" . a:key
let l:nmap_line = 'nmap <silent> <special> ' . l:keycode . ' ' . a:cmd
let l:vnoremap_line = 'vnoremap <silent> <special> ' . l:keycode . ' <Esc>' . l:keycode
if(a:add_gv)
let l:vnoremap_line.='gv'
endif
let l:inoremap_line = 'inoremap <silent> <special> ' . l:keycode . ' <C-o>' . l:keycode
let l:cnoremap_line = 'cnoremap <special> ' . l:keycode . ' <C-c>' . l:keycode
let l:onoremap_line = 'onoremap <silent> <special> ' . l:keycode . ' <Esc>' . l:keycode
exec l:set_line
exec l:nmap_line
exec l:vnoremap_line
exec l:inoremap_line
exec l:cnoremap_line
exec l:onoremap_line
endfunction
" I can't think of a good function to assign to Meta+n, since in MacVim Cmd+N
" opens a whole new editing session.
" Meta+Shift+N
" No equivalent to this in standard MacVim. Here " it just opens a window on a
" new buffer.
call NvicoMapMeta('N', ':new<CR>', 1)
" Meta+o
" Open netrw file browser
call NvicoMapMeta('o', ':split %:p:h<CR>', 1)
" Meta+w
" Close window
call NvicoMapMeta('w', ':confirm close<CR>', 1)
" Meta+s
" Save buffer
call NvicoMapMeta('s', ':confirm w<CR>', 1)
" Meta+Shift+S
" Save as
" TODO: This is silent, so you can't tell it's waiting for input. If anyone can
" fix this, please do!
call NvicoMapMeta('S', ':confirm saveas ', 1)
" Meta+z
" Undo
call NvicoMapMeta('z', 'u', 1)
" Meta+Shift+Z
" Redo
call NvicoMapMeta('Z', '<C-r>', 1)
" Meta+x
" Cut to system clipboard (requires register +")
exec "set <M-x>=\<Esc>x"
vnoremap <special> <M-x> "+x
" Meta+c
" Copy to system clipboard (requires register +")
exec "set <M-c>=\<Esc>c"
vnoremap <special> <M-c> "+y
" Meta+v
" Paste from system clipboard (requires register +")
exec "set <M-v>=\<Esc>v"
nnoremap <silent> <special> <M-v> "+gP
cnoremap <special> <M-v> <C-r>+
execute 'vnoremap <silent> <script> <special> <M-v>' paste#paste_cmd['v']
execute 'inoremap <silent> <script> <special> <M-v>' paste#paste_cmd['i']
" Meta+a
" Select all
call NvicoMapMeta('a', ':if &slm != ""<Bar>exe ":norm gggH<C-o>G"<Bar> else<Bar>exe ":norm ggVG"<Bar>endif<CR>', 0)
" Meta+f
" Find regexp. NOTE: MacVim's Cmd+f does a non-regexp search.
call NvicoMapMeta('f', '/', 0)
" Meta+g
" Find again
call NvicoMapMeta('g', 'n', 0)
" Meta+Shift+G
" Find again, reverse direction
call NvicoMapMeta('G', 'N', 0)
" Meta+q
" Quit Vim
" Not quite identical to MacVim default (which is actually coded in the app
" itself rather than in macmap.vim)
call NvicoMapMeta('q', ':confirm qa<CR>', 0)
" Meta+Shift+{
" Switch tab left
call NvicoMapMeta('{', ':tabN<CR>', 0)
" Meta+Shift+}
" Switch tab right
call NvicoMapMeta('}', ':tabn<CR>', 0)
" Meta+t
" Create new tab
call NvicoMapMeta('t', ':tabnew<CR>', 0)
" Meta+Shift+T
" Open netrw file browser in new tab
call NvicoMapMeta('T', ':tab split %:p:h<CR>', 0)
" Meta+b
" Call :make
call NvicoMapMeta('b', ':make<CR>', 1)
" Meta+l
" Open error list
call NvicoMapMeta('l', ':cl<CR>', 1)
" TODO: We need to configure iTerm2 to be able to send Cmd+Ctrl+arrow keys, so
" we can duplicate the :cnext/:cprevious/:colder/:cnewer bindings to those keys
" in MacVim.
" There may be a few others I've missed, too.
The NvicoMakeMeta function maps a meta-key-modified version of the key passed into it to the specified action; "meta-key" here is just a generic term for Command- or Option-modified. The "Nvico" in its name represents the fact that it maps in normal, visual, insert, command, and operator pending modes.
Due to the way way Vim works when interpreting the ESC character (which is the beginning of all meta key sequences as well as arrow keys, etc.), if we simply mapped sequences of ESC plus another character, we would end up with Vim waiting a noticeable amount of time after receiving the actual Esc keypress (e.g. to signal a desire to return to normal mode). The way my function avoids this is by using :set to set a key code (see :help :set-termcap).
To summarize, here's what you need to do:
Put the above code in your .vimrc.
Go to the general iTerm2 preferences (iTerm menu > Preferences…); go to the Keys tab; remap your whatever key you'd like to use as a modifier so that it sends Left Option or Right Option. Follow the advice to allow iTerm2 to control the computer; it should open up the right preference pane for you to do that. You'll have to click the lock and type in your password before you can check the box next to iTerm.
Open the preferences for the terminal profile you'd like to use (e.g. by opening it in the app-wide Preferences dialog in the Profiles tab) and ensure that +Esc is checked next to Left option key acts as (and/or Right option key acts as, depending on whether you've made your meta key send Right Option).

Print current frame during command line render?

Is there a way to basically print my own output during a command line render?
Let's say I don't need/want all the other output that maya spits out by default, I know you can change the verbosity level, but there's very specific things I'd like to output but I can't figure it out. I currently render out the verbosity output to file, so I wanted to print in the terminal (I'm using MAC) the frame that the render is currently up to.
This may just be simple minded, but here's what I tried:
Render -preFrame "print `currentTime -q`;" -s 1 -e 20 -rd /render/directory/ maya_file.mb
Obviously, -preFrame expects a string, according to the docs this can take mel commands, but obviously this is limited to certain commands, I'm assuming the currentTime command is pulling the information from the timeline in maya, not queering it from the Renderer it self... When I run the above command, straight away, it spits out this: -bash: currentTime: command not found and soon after the render fails/doesn't start.
Idealy, I'd like to print the following as it starts each frame:
"Started rendering frame XXXX at TIME GOES HERE", that way, I can quickly look at the terminal, and see if the renderer has failed, stuck or where it's up to and when it started it.
So my question is, seeing is currentTime is a mel command used from within Maya, is there another way I could print this information?
Cheers,
Shannon
After many hours of searching for this answer, I ended up finding out that you can start maya as an interactive shell. By doing this, I was able to source a script as I opened it, and run whatever I want into memory as If I had Maya open at the time.
/Applications/Autodesk/maya2014/Maya.app/Contents/MacOS/maya -prompt -script "/Volumes/raid/farm_script/setupRender.mel"
In the setupRender.mel file, I was able to assign variables, containing options for renders etc, in doing this, I was also able to create a global variable for the frame number, and increment it during the preFrame callback, like so:
int $startFrame = 100;
int $endFrame = 1110;
global int $frameCount = 0;
string $preRenderStatistics = "'global int $frameCount; $frameCount = " + $startFrame + ";'";
string $preFrameStatistics = "'print(\"Rendering frame: \" + $frameCount++)'";
string $additionalFlags = "";
string $sceneFilePath = "'/Volumes/path/to/file/intro_video_001.mb'";
system("Render -preRender " + $preRenderStatistics + " -preFrame " + $preFrameStatistics + " -s " + $startFrame + " -e " + $endFrame + " -x " + $additionalFlags + " " + $sceneFilePath);
This is a very simplified version of what I currently have, but hopefully this will help others if they stumble across it.
Take a look at the pre render layer MEL and/or pre render frame MEL section of the Render Settings.
It expects MEL, so you'll either need to write it in MEL or wrap your python in MEL. For such a simple use, I'd say just write it in MEL:
print `currentTime -q`

a file is copied to a specific folder and renamed to x.txt how do i open x.txt and paste "X:"

EDIT: regulus6633 has made a script that's a lot better than my outline below, it works perfectly IF you're template file isn't completely empty (I think this caused an error originally). Thanks!
This script is supposed to (1) copy a x.txt to a specific folder rename it to new_name, (2) open it, (3) paste "new_name" in all caps, and (4) insert ":" followed by return & return. The first part is working, but I'm having trouble figuring out (2), (3) and (4). The code I've written so far is pasted below.
tell application "Finder"
display dialog "new_name_dialogue" default answer " "
set new_name to (text returned of result)
set Selected_Finder_Item to (folder of the front window) as text
duplicate file "Q:x:7:n7:GTD scripting:template folder:x.txt" to "Q:X:7:SI:SIAG1"
set Path_Of_X to "Q:X:7:SI:SIAG1:" & "x.txt" as string
set name of file Path_Of_X to (new_name as text) & ".txt"
#[something that let's me open the file is needed here]
#[something that pastes "new_name" & ":" in ALL CAPS]
#[something that inserts two lineshifts]
end tell
In general since you're dealing with a txt file, you do not need to "open" the file in an application and paste in text. We can read and write to text files directly from applescript. As such we read in the text from the template file, add whatever text we want to that, and then write the new text to a new file. If you then want to open and view the new file you can do that after. I did that in the "TextEdit" section of the code.
You can see at the end of the script I have subroutines to write a text file and also to change the file name to CAPS. So try the following...
-- initial variables
set templateFile to "Q:x:7:n7:GTD scripting:template folder:x.txt"
set copyFolder to "Q:X:7:SI:SIAG1:" -- notice this path ends in ":" because it's a folder
-- get the new name
display dialog "new_name_dialogue" default answer ""
set newName to (text returned of result)
set newPath to copyFolder & newName
-- get the text of the template file
set templateText to read file templateFile
-- add the file name in CAPS, a colon, and 2 returns at the beginning of templateText
set capsName to upperCase(newName)
set newText to capsName & ":" & return & return & templateText
-- write the newText to newPath
writeTo(newPath, newText, text, false)
-- open the new file in textedit
tell application "TextEdit" to open file newPath
(*============== SUBROUTINES ==============*)
on writeTo(targetFile, theData, dataType, apendData)
-- targetFile is the path to the file you want to write
-- theData is the data you want in the file.
-- dataType is the data type of theData and it can be text, list, record etc.
-- apendData is true to append theData to the end of the current contents of the file or false to overwrite it
try
set targetFile to targetFile as text
if targetFile does not contain ":" then set targetFile to POSIX file targetFile as text
set openFile to open for access file targetFile with write permission
if apendData is false then set eof of openFile to 0
write theData to openFile starting at eof as dataType
close access openFile
return true
on error
try
close access file targetFile
end try
return false
end try
end writeTo
on upperCase(theText)
set chrIDs to id of theText
set a to {}
repeat with i from 1 to (count of chrIDs)
set chrID to item i of chrIDs
if chrID ≥ 97 and chrID ≤ 122 then set chrID to (chrID - 32)
set end of a to chrID
end repeat
return string id a
end upperCase
something that lets me open the file is needed here
tell application "TextEdit" to open Path_Of_X
something that pastes new_name in ALL CAPS
There is a really good third party scripting addition (Satimage OSAX) that you can use for things just like this (this will only work if you've downloaded the scripting addition)...
set UPPER_CASE to uppercase new_name & ":"
something that inserts two lineshifts
return & return

Resources